From 86b7ea6bf36faf0db468acac473bda4bc4f90483 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Tue, 24 Mar 2026 20:48:30 +0300 Subject: [PATCH 1/2] overlays/sdf: Avoid 0-height inner boxes for switch capsule - Can introduce dfdx/dfdy discontinuities on the midline as the distance changes direction - The seams can sometimes become visible if a border is applied on some GPUs --- rpcs3/Emu/RSX/Overlays/overlay_checkbox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rpcs3/Emu/RSX/Overlays/overlay_checkbox.cpp b/rpcs3/Emu/RSX/Overlays/overlay_checkbox.cpp index 0c5c087ce0..304c07a1f6 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_checkbox.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_checkbox.cpp @@ -99,7 +99,7 @@ namespace rsx::overlays ellipse_part->set_size(dim * 2, dim); ellipse_part->set_padding(1); ellipse_part->set_pos(0, 0); - ellipse_part->border_radius = (dim - 2) / 2; + ellipse_part->border_radius = (dim - 4) / 2; // Avoid perfect capsule shape since we want a border and perfect capsules can have a false border along the midline due to subgroup shenanigans circle_part->set_size(dim, dim); circle_part->set_padding(4); From 9b6bc7c1b441a19000925ba79886dddaf6cb0cb7 Mon Sep 17 00:00:00 2001 From: kd-11 Date: Wed, 25 Mar 2026 01:40:09 +0300 Subject: [PATCH 2/2] rsx: Make resolution scaling configuration non-global - Paves the way for other changes. - The main goal is to be able to switch the resolution scale and MSAA level at runtime. --- rpcs3/Emu/RSX/Common/surface_store.h | 12 ++- rpcs3/Emu/RSX/Common/surface_utils.h | 45 +++++--- rpcs3/Emu/RSX/Common/texture_cache.h | 20 ++-- rpcs3/Emu/RSX/Common/texture_cache_helpers.h | 43 ++++---- rpcs3/Emu/RSX/Core/RSXDisplay.cpp | 4 +- rpcs3/Emu/RSX/Core/RSXDisplay.h | 4 +- rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp | 4 +- rpcs3/Emu/RSX/GL/GLDraw.cpp | 2 +- rpcs3/Emu/RSX/GL/GLGSRender.cpp | 3 +- rpcs3/Emu/RSX/GL/GLPresent.cpp | 7 +- rpcs3/Emu/RSX/GL/GLRenderTargets.cpp | 5 +- rpcs3/Emu/RSX/GL/GLRenderTargets.h | 24 +++-- rpcs3/Emu/RSX/GL/GLTextureCache.h | 4 +- rpcs3/Emu/RSX/RSXThread.cpp | 10 +- rpcs3/Emu/RSX/RSXThread.h | 2 + rpcs3/Emu/RSX/RSXZCULL.cpp | 2 +- rpcs3/Emu/RSX/VK/VKDraw.cpp | 2 +- rpcs3/Emu/RSX/VK/VKGSRender.cpp | 6 +- rpcs3/Emu/RSX/VK/VKPresent.cpp | 7 +- rpcs3/Emu/RSX/VK/VKRenderTargets.cpp | 4 +- rpcs3/Emu/RSX/VK/VKRenderTargets.h | 16 ++- rpcs3/Emu/RSX/VK/VKResourceManager.cpp | 2 +- rpcs3/Emu/RSX/rsx_utils.h | 106 ++++++++++--------- rpcs3/rpcs3qt/gs_frame.cpp | 3 +- 24 files changed, 207 insertions(+), 130 deletions(-) diff --git a/rpcs3/Emu/RSX/Common/surface_store.h b/rpcs3/Emu/RSX/Common/surface_store.h index 4476930607..51152ea32a 100644 --- a/rpcs3/Emu/RSX/Common/surface_store.h +++ b/rpcs3/Emu/RSX/Common/surface_store.h @@ -398,6 +398,7 @@ namespace rsx surface_antialiasing antialias, usz width, usz height, usz pitch, u8 bpp, + const rsx::surface_scaling_config_t& scaling_config, Args&&... extra_params) { surface_storage_type old_surface_storage; @@ -531,7 +532,7 @@ namespace rsx if (!new_surface) { ensure(store); - new_surface_storage = Traits::create_new_surface(address, format, width, height, pitch, antialias, std::forward(extra_params)...); + new_surface_storage = Traits::create_new_surface(address, format, width, height, pitch, antialias, scaling_config, std::forward(extra_params)...); new_surface = Traits::get(new_surface_storage); Traits::prepare_surface_for_drawing(command_list, new_surface); allocate_rsx_memory(new_surface); @@ -842,11 +843,13 @@ namespace rsx surface_color_format color_format, surface_antialiasing antialias, usz width, usz height, usz pitch, + const rsx::surface_scaling_config_t& scaling_config, Args&&... extra_params) { return bind_surface_address( command_list, address, color_format, antialias, width, height, pitch, get_format_block_size_in_bytes(color_format), + scaling_config, std::forward(extra_params)...); } @@ -857,12 +860,14 @@ namespace rsx surface_depth_format2 depth_format, surface_antialiasing antialias, usz width, usz height, usz pitch, + const rsx::surface_scaling_config_t& scaling_config, Args&&... extra_params) { return bind_surface_address( command_list, address, depth_format, antialias, width, height, pitch, get_format_block_size_in_bytes(depth_format), + scaling_config, std::forward(extra_params)...); } @@ -969,6 +974,7 @@ namespace rsx surface_raster_type raster_type, const std::array &surface_addresses, u32 address_z, const std::array &surface_pitch, u32 zeta_pitch, + const rsx::surface_scaling_config_t& scaling_config, Args&&... extra_params) { u32 clip_width = clip_horizontal_reg; @@ -998,7 +1004,7 @@ namespace rsx m_bound_render_targets[surface_index] = std::make_pair(surface_addresses[surface_index], bind_address_as_render_targets(command_list, surface_addresses[surface_index], color_format, antialias, - clip_width, clip_height, surface_pitch[surface_index], std::forward(extra_params)...)); + clip_width, clip_height, surface_pitch[surface_index], scaling_config, std::forward(extra_params)...)); m_bound_render_target_ids.push_back(surface_index); } @@ -1014,7 +1020,7 @@ namespace rsx { m_bound_depth_stencil = std::make_pair(address_z, bind_address_as_depth_stencil(command_list, address_z, depth_format, antialias, - clip_width, clip_height, zeta_pitch, std::forward(extra_params)...)); + clip_width, clip_height, zeta_pitch, scaling_config, std::forward(extra_params)...)); } else { diff --git a/rpcs3/Emu/RSX/Common/surface_utils.h b/rpcs3/Emu/RSX/Common/surface_utils.h index bf7dee2db3..ffd71e6003 100644 --- a/rpcs3/Emu/RSX/Common/surface_utils.h +++ b/rpcs3/Emu/RSX/Common/surface_utils.h @@ -88,18 +88,18 @@ namespace rsx auto dst_h = std::get<3>(region); // Apply resolution scale if needed - if (g_cfg.video.resolution_scale_percent != 100) - { - auto src = static_cast(source); + auto src = static_cast(source); + std::tie(src_w, src_h) = rsx::apply_resolution_scale( + src->resolution_scaling_config, + src_w, src_h, + src->template get_surface_width(), + src->template get_surface_height()); - std::tie(src_w, src_h) = rsx::apply_resolution_scale(src_w, src_h, - src->template get_surface_width(), - src->template get_surface_height()); - - std::tie(dst_w, dst_h) = rsx::apply_resolution_scale(dst_w, dst_h, - target_surface->template get_surface_width(), - target_surface->template get_surface_height()); - } + std::tie(dst_w, dst_h) = rsx::apply_resolution_scale( + target_surface->resolution_scaling_config, + dst_w, dst_h, + target_surface->template get_surface_width(), + target_surface->template get_surface_height()); width = src_w; height = src_h; @@ -146,6 +146,9 @@ namespace rsx u8 samples_x = 1; u8 samples_y = 1; + // Scaling configuration + surface_scaling_config_t resolution_scaling_config; + rsx::address_range32 memory_range; std::unique_ptr> resolve_surface; @@ -303,6 +306,11 @@ namespace rsx format_info.gcm_depth_format = format; } + void set_resolution_scaling_config(const surface_scaling_config_t& config) + { + resolution_scaling_config = config; + } + inline rsx::surface_color_format get_surface_color_format() const { return format_info.gcm_color_format; @@ -323,6 +331,11 @@ namespace rsx ); } + inline const rsx::surface_scaling_config_t& get_resolution_scaling_config() const + { + return resolution_scaling_config; + } + inline bool dirty() const { return (state_flags != rsx::surface_state_flags::ready) || !old_contents.empty(); @@ -541,10 +554,10 @@ namespace rsx } // Apply resolution scale if needed - if (g_cfg.video.resolution_scale_percent != 100) + if (resolution_scaling_config.scale_percent != 100) { - 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()); + auto [src_width, src_height] = rsx::apply_resolution_scale(resolution_scaling_config, slice.width, slice.height, slice.source->width(), slice.source->height()); + auto [dst_width, dst_height] = rsx::apply_resolution_scale(resolution_scaling_config, 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; @@ -552,8 +565,8 @@ namespace rsx slice.width = src_width; slice.height = src_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()); + std::tie(slice.src_x, slice.src_y) = rsx::apply_resolution_scale(resolution_scaling_config, slice.src_x, slice.src_y, slice.source->width(), slice.source->height()); + std::tie(slice.dst_x, slice.dst_y) = rsx::apply_resolution_scale(resolution_scaling_config, slice.dst_x, slice.dst_y, slice.target->width(), slice.target->height()); } } diff --git a/rpcs3/Emu/RSX/Common/texture_cache.h b/rpcs3/Emu/RSX/Common/texture_cache.h index dfe8043bd3..8aed0ccc34 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache.h +++ b/rpcs3/Emu/RSX/Common/texture_cache.h @@ -2413,9 +2413,13 @@ namespace rsx // 2. The image has to have been generated on the GPU (fbo or blit target only) rsx::simple_array sections; - const bool use_upscaling = (result.upload_context == rsx::texture_upload_context::framebuffer_storage && g_cfg.video.resolution_scale_percent != 100); + const bool use_upscaling = (result.upload_context == rsx::texture_upload_context::framebuffer_storage); + auto to_surface_type = [](const copy_region_descriptor& rgn) -> typename surface_store_type::surface_type + { + return static_cast(rgn.src); + }; - if (!helpers::append_mipmap_level(sections, result, attributes, 0, use_upscaling, attributes)) [[unlikely]] + if (!helpers::append_mipmap_level(to_surface_type, sections, result, attributes, 0, use_upscaling, attributes)) [[unlikely]] { // Abort if mip0 is not compatible return result; @@ -2445,7 +2449,7 @@ namespace rsx options, range, extended_dimension, m_rtts, std::forward(extras)...); if (!ret.validate() || - !helpers::append_mipmap_level(sections, ret, attr2, subsurface, use_upscaling, attributes)) + !helpers::append_mipmap_level(to_surface_type, sections, ret, attr2, subsurface, use_upscaling, attributes)) { // Abort break; @@ -2778,7 +2782,7 @@ namespace rsx surf->template get_surface_height() != surf->height()) { // Must go through a scaling operation due to resolution scaling being present - ensure(g_cfg.video.resolution_scale_percent != 100); + ensure(src_subres.surface->resolution_scaling_config.scale_percent != 100); use_null_region = false; } } @@ -3389,8 +3393,8 @@ namespace rsx { const auto surface_width = src_subres.surface->template get_surface_width(); const auto surface_height = src_subres.surface->template get_surface_height(); - std::tie(src_area.x1, src_area.y1) = rsx::apply_resolution_scale(src_area.x1, src_area.y1, surface_width, surface_height); - std::tie(src_area.x2, src_area.y2) = rsx::apply_resolution_scale(src_area.x2, src_area.y2, surface_width, surface_height); + std::tie(src_area.x1, src_area.y1) = rsx::apply_resolution_scale(src_subres.surface->resolution_scaling_config, src_area.x1, src_area.y1, surface_width, surface_height); + std::tie(src_area.x2, src_area.y2) = rsx::apply_resolution_scale(src_subres.surface->resolution_scaling_config, src_area.x2, src_area.y2, surface_width, surface_height); // The resource is of surface type; possibly disabled AA emulation src_subres.surface->transform_blit_coordinates(rsx::surface_access::transfer_read, src_area); @@ -3400,8 +3404,8 @@ namespace rsx { const auto surface_width = dst_subres.surface->template get_surface_width(); const auto surface_height = dst_subres.surface->template get_surface_height(); - std::tie(dst_area.x1, dst_area.y1) = rsx::apply_resolution_scale(dst_area.x1, dst_area.y1, surface_width, surface_height); - std::tie(dst_area.x2, dst_area.y2) = rsx::apply_resolution_scale(dst_area.x2, dst_area.y2, surface_width, surface_height); + std::tie(dst_area.x1, dst_area.y1) = rsx::apply_resolution_scale(dst_subres.surface->resolution_scaling_config, dst_area.x1, dst_area.y1, surface_width, surface_height); + std::tie(dst_area.x2, dst_area.y2) = rsx::apply_resolution_scale(dst_subres.surface->resolution_scaling_config, dst_area.x2, dst_area.y2, surface_width, surface_height); // The resource is of surface type; possibly disabled AA emulation dst_subres.surface->transform_blit_coordinates(rsx::surface_access::transfer_write, dst_area); diff --git a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h index 1560f40ad4..8898830034 100644 --- a/rpcs3/Emu/RSX/Common/texture_cache_helpers.h +++ b/rpcs3/Emu/RSX/Common/texture_cache_helpers.h @@ -357,11 +357,11 @@ namespace rsx const auto surface_width = section.surface->template get_surface_width(); const auto surface_height = section.surface->template get_surface_height(); - const auto [src_width, src_height] = rsx::apply_resolution_scale(section.src_area.width, h, surface_width, surface_height); - const auto [dst_width, dst_height] = rsx::apply_resolution_scale(section.dst_area.width, h, attr.width, attr.height); + const auto [src_width, src_height] = rsx::apply_resolution_scale(section.surface->resolution_scaling_config, section.src_area.width, h, surface_width, surface_height); + const auto [dst_width, dst_height] = rsx::apply_resolution_scale(section.surface->resolution_scaling_config, section.dst_area.width, h, attr.width, attr.height); - std::tie(src_x, src_y) = rsx::apply_resolution_scale(src_x, src_y, surface_width, surface_height); - std::tie(dst_x, dst_y) = rsx::apply_resolution_scale(dst_x, dst_y, attr.width, attr.height); + std::tie(src_x, src_y) = rsx::apply_resolution_scale(section.surface->resolution_scaling_config, src_x, src_y, surface_width, surface_height); + std::tie(dst_x, dst_y) = rsx::apply_resolution_scale(section.surface->resolution_scaling_config, dst_x, dst_y, attr.width, attr.height); section.surface->memory_barrier(cmd, rsx::surface_access::transfer_read); @@ -430,8 +430,10 @@ namespace rsx if (scaling) { // Since output is upscaled, also upscale on dst - const auto [_dst_x, _dst_y] = rsx::apply_resolution_scale(static_cast(dst_offset.x), static_cast(dst_y - dst_slice_begin), attr.width, attr.height); - const auto [_dst_w, _dst_h] = rsx::apply_resolution_scale(dst_w, height, attr.width, attr.height); + + const auto& scaling_config = rsx::get_current_renderer()->resolution_scaling_config; + const auto [_dst_x, _dst_y] = rsx::apply_resolution_scale(scaling_config, static_cast(dst_offset.x), static_cast(dst_y - dst_slice_begin), attr.width, attr.height); + const auto [_dst_w, _dst_h] = rsx::apply_resolution_scale(scaling_config, dst_w, height, attr.width, attr.height); out.push_back ({ @@ -660,10 +662,10 @@ namespace rsx bool is_depth = texptr->is_depth_surface(); auto attr2 = attr; - if (rsx::get_resolution_scale_percent() != 100) + if (texptr->resolution_scaling_config.scale_percent != 100) { - const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(attr.width, attr.height, surface_width, surface_height); - const auto [unused, scaled_slice_h] = rsx::apply_resolution_scale(RSX_SURFACE_DIMENSION_IGNORED, attr.slice_h, surface_width, surface_height); + const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(texptr->resolution_scaling_config, attr.width, attr.height, surface_width, surface_height); + const auto [unused, scaled_slice_h] = rsx::apply_resolution_scale(texptr->resolution_scaling_config, RSX_SURFACE_DIMENSION_IGNORED, attr.slice_h, surface_width, surface_height); attr2.width = scaled_w; attr2.height = scaled_h; attr2.slice_h = scaled_slice_h; @@ -841,7 +843,8 @@ namespace rsx } // If this method was called, there is no easy solution, likely means atlas gather is needed - const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(attr2.width, attr2.height); + const auto& scaling_config = rsx::get_current_renderer()->resolution_scaling_config; + const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(scaling_config, attr2.width, attr2.height); const auto format_class = classify_format(attr2.gcm_format); const auto upload_context = (fbos.empty()) ? texture_upload_context::shader_read : texture_upload_context::framebuffer_storage; @@ -892,14 +895,15 @@ namespace rsx return result; } - template + template bool append_mipmap_level( + to_surface_type_converter&& as_surface_type, // Cast function to surface type rsx::simple_array& sections, // Destination list - const sampled_image_descriptor& level, // Descriptor for the image level being checked - const image_section_attributes_t& attr, // Attributes of image level - u8 mipmap_level, // Level index - bool apply_upscaling, // Whether to upscale the results or not - const image_section_attributes_t& level0_attr) // Attributes of the first mipmap level + const sampled_image_descriptor& level, // Descriptor for the image level being checked + const image_section_attributes_t& attr, // Attributes of image level + u8 mipmap_level, // Level index + bool apply_upscaling, // Whether to upscale the results or not + const image_section_attributes_t& level0_attr) // Attributes of the first mipmap level { if (level.image_handle) { @@ -916,7 +920,8 @@ namespace rsx // Calculate transfer dimensions from attr if (level.upload_context == rsx::texture_upload_context::framebuffer_storage) [[likely]] { - std::tie(mip.src_w, mip.src_h) = rsx::apply_resolution_scale(attr.width, attr.height); + auto rtv = as_surface_type(mip); + std::tie(mip.src_w, mip.src_h) = rsx::apply_resolution_scale(rtv->resolution_scaling_config, attr.width, attr.height); } else { @@ -964,7 +969,9 @@ namespace rsx if (apply_upscaling) { auto& mip = sections.back(); - std::tie(mip.dst_w, mip.dst_h) = rsx::apply_resolution_scale(mip.dst_w, mip.dst_h, level0_attr.width, level0_attr.height); + std::tie(mip.dst_w, mip.dst_h) = rsx::apply_resolution_scale( + as_surface_type(mip)->resolution_scaling_config, + mip.dst_w, mip.dst_h, level0_attr.width, level0_attr.height); } return true; diff --git a/rpcs3/Emu/RSX/Core/RSXDisplay.cpp b/rpcs3/Emu/RSX/Core/RSXDisplay.cpp index e263a945ef..f86c6dea04 100644 --- a/rpcs3/Emu/RSX/Core/RSXDisplay.cpp +++ b/rpcs3/Emu/RSX/Core/RSXDisplay.cpp @@ -49,7 +49,7 @@ namespace rsx } } - std::string framebuffer_statistics_t::to_string(bool squash) const + std::string framebuffer_statistics_t::to_string(const surface_scaling_config_t& scaling_config, bool squash) const { // Format is sorted by sample count struct sorted_message_t @@ -70,7 +70,7 @@ namespace rsx for (const auto& [aa_mode, stat] : data) { auto real_stat = stat; - std::tie(real_stat.width, real_stat.height) = apply_resolution_scale(stat.width, stat.height); + std::tie(real_stat.width, real_stat.height) = apply_resolution_scale(scaling_config, stat.width, stat.height); real_stats.push_back(real_stat); sorted_message_t msg; diff --git a/rpcs3/Emu/RSX/Core/RSXDisplay.h b/rpcs3/Emu/RSX/Core/RSXDisplay.h index 77407f2f19..6a04374e1b 100644 --- a/rpcs3/Emu/RSX/Core/RSXDisplay.h +++ b/rpcs3/Emu/RSX/Core/RSXDisplay.h @@ -12,6 +12,8 @@ namespace rsx { enum class surface_antialiasing : u8; + struct surface_scaling_config_t; + struct framebuffer_dimensions_t { u16 width; @@ -42,7 +44,7 @@ namespace rsx void add(u16 width, u16 height, rsx::surface_antialiasing aa); // Returns a formatted string representing the statistics collected over the frame. - std::string to_string(bool squash) const; + std::string to_string(const surface_scaling_config_t& scaling_config, bool squash) const; }; struct frame_statistics_t diff --git a/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp b/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp index 53f6ce31e7..8ef45e1f06 100644 --- a/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp +++ b/rpcs3/Emu/RSX/Core/RSXDrawCommands.cpp @@ -699,7 +699,9 @@ namespace rsx const auto window_origin = REGS(m_ctx)->shader_window_origin(); const u32 window_height = REGS(m_ctx)->shader_window_height(); const auto pixel_center = REGS(m_ctx)->pixel_center(); - const f32 resolution_scale = (window_height <= static_cast(g_cfg.video.min_scalable_dimension)) ? 1.f : rsx::get_resolution_scale(); + const f32 resolution_scale = (window_height <= RSX(m_ctx)->resolution_scaling_config.min_scalable_dimension) + ? 1.f + : RSX(m_ctx)->resolution_scaling_config.scale_factor(); payload.wpos_scale = (window_origin == rsx::window_origin::top) ? (1.f / resolution_scale) : (-1.f / resolution_scale); payload.wpos_bias[0] = 0.f; diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index 3de2585523..d0c2e233e9 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -227,7 +227,7 @@ void GLGSRender::update_draw_state() case rsx::primitive_type::lines: case rsx::primitive_type::line_loop: case rsx::primitive_type::line_strip: - gl_state.line_width(rsx::method_registers.line_width() * rsx::get_resolution_scale()); + gl_state.line_width(rsx::method_registers.line_width() * resolution_scaling_config.scale_factor()); gl_state.enable(rsx::method_registers.line_smooth_enabled(), GL_LINE_SMOOTH); break; default: diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.cpp b/rpcs3/Emu/RSX/GL/GLGSRender.cpp index 20553eeb00..c1acabd601 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.cpp +++ b/rpcs3/Emu/RSX/GL/GLGSRender.cpp @@ -73,6 +73,7 @@ void GLGSRender::set_viewport() { // NOTE: scale offset matrix already contains the viewport transformation const auto [clip_width, clip_height] = rsx::apply_resolution_scale( + resolution_scaling_config, rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height()); glViewport(0, 0, clip_width, clip_height); @@ -936,7 +937,7 @@ void GLGSRender::load_program_env() m_draw_processor.fill_scale_offset_data(buf, false); m_draw_processor.fill_user_clip_data(buf + 64); *(reinterpret_cast(buf + 68)) = rsx::method_registers.transform_branch_bits(); - *(reinterpret_cast(buf + 72)) = rsx::method_registers.point_size() * rsx::get_resolution_scale(); + *(reinterpret_cast(buf + 72)) = rsx::method_registers.point_size() * resolution_scaling_config.scale_factor(); *(reinterpret_cast(buf + 76)) = rsx::method_registers.clip_min(); *(reinterpret_cast(buf + 80)) = rsx::method_registers.clip_max(); diff --git a/rpcs3/Emu/RSX/GL/GLPresent.cpp b/rpcs3/Emu/RSX/GL/GLPresent.cpp index 68a570e359..e101d77e03 100644 --- a/rpcs3/Emu/RSX/GL/GLPresent.cpp +++ b/rpcs3/Emu/RSX/GL/GLPresent.cpp @@ -95,6 +95,7 @@ gl::texture* GLGSRender::get_present_source(gl::present_surface_info* info, cons image = section.surface->get_surface(rsx::surface_access::transfer_read); std::tie(info->width, info->height) = rsx::apply_resolution_scale( + resolution_scaling_config, std::min(surface_width, info->width), std::min(surface_height, info->height)); } @@ -225,7 +226,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) if (avconfig.stereo_enabled) [[unlikely]] { - const auto [unused, min_expected_height] = rsx::apply_resolution_scale(RSX_SURFACE_DIMENSION_IGNORED, buffer_height + 30); + const auto [unused, min_expected_height] = rsx::apply_resolution_scale(resolution_scaling_config, RSX_SURFACE_DIMENSION_IGNORED, buffer_height + 30); if (image_to_flip->height() < min_expected_height) { // Get image for second eye @@ -240,7 +241,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) else { // Account for possible insets - const auto [unused2, scaled_buffer_height] = rsx::apply_resolution_scale(RSX_SURFACE_DIMENSION_IGNORED, buffer_height); + const auto [unused2, scaled_buffer_height] = rsx::apply_resolution_scale(resolution_scaling_config, RSX_SURFACE_DIMENSION_IGNORED, buffer_height); buffer_height = std::min(image_to_flip->height() - min_expected_height, scaled_buffer_height); } } @@ -477,7 +478,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) "Texture uploads: %11u (%u from CPU - %02u%%, %u copies avoided)\n" "Vertex cache hits: %9u/%u (%u%%)\n" "Program cache lookup ellision: %u/%u (%u%%)", - info.stats.framebuffer_stats.to_string(!backend_config.supports_hw_msaa), + info.stats.framebuffer_stats.to_string(resolution_scaling_config, !backend_config.supports_hw_msaa), get_load(), info.stats.draw_calls, info.stats.setup_time, info.stats.vertex_upload_time, info.stats.textures_upload_time, info.stats.draw_exec_time, num_dirty_textures, texture_memory_size, num_flushes, num_misses, cache_miss_ratio, num_unavoidable, num_mispredict, num_speculate, diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp index a61fb4b365..34c2ca72d3 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.cpp @@ -141,7 +141,8 @@ void GLGSRender::init_buffers(rsx::framebuffer_creation_context context, bool /* m_framebuffer_layout.width, m_framebuffer_layout.height, m_framebuffer_layout.target, m_framebuffer_layout.aa_mode, m_framebuffer_layout.raster_type, m_framebuffer_layout.color_addresses, m_framebuffer_layout.zeta_address, - m_framebuffer_layout.actual_color_pitch, m_framebuffer_layout.actual_zeta_pitch); + m_framebuffer_layout.actual_color_pitch, m_framebuffer_layout.actual_zeta_pitch, + resolution_scaling_config); std::array color_targets; GLuint depth_stencil_target; @@ -448,7 +449,7 @@ void gl::render_target::load_memory(gl::command_context& cmd) subres.data = { vm::get_super_ptr(base_addr), static_cast::size_type>(rsx_pitch * surface_height * samples_y) }; // TODO: MSAA support - if (g_cfg.video.resolution_scale_percent == 100 && spp == 1) [[likely]] + if (resolution_scaling_config.scale_percent == 100 && spp == 1) [[likely]] { gl::upload_texture(cmd, this, get_gcm_format(), is_swizzled, { subres }); } diff --git a/rpcs3/Emu/RSX/GL/GLRenderTargets.h b/rpcs3/Emu/RSX/GL/GLRenderTargets.h index ee3bc03956..ecf7e161da 100644 --- a/rpcs3/Emu/RSX/GL/GLRenderTargets.h +++ b/rpcs3/Emu/RSX/GL/GLRenderTargets.h @@ -98,7 +98,7 @@ namespace gl bool matches_dimensions(u16 _width, u16 _height) const { //Use forward scaling to account for rounding and clamping errors - const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(_width, _height); + const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(resolution_scaling_config, _width, _height); return (scaled_w == width()) && (scaled_h == height()); } @@ -138,11 +138,12 @@ struct gl_render_target_traits u32 address, rsx::surface_color_format surface_color_format, usz width, usz height, usz pitch, - rsx::surface_antialiasing antialias + rsx::surface_antialiasing antialias, + const rsx::surface_scaling_config_t& resolution_scaling_config ) { 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)); + const auto [width_, height_] = rsx::apply_resolution_scale(resolution_scaling_config, static_cast(width), static_cast(height)); u8 samples; rsx::surface_sample_layout sample_layout; @@ -162,6 +163,7 @@ struct gl_render_target_traits result->set_name(fmt::format("RTV_%u@0x%x", result->id(), address)); result->set_aa_mode(antialias); + result->set_resolution_scaling_config(resolution_scaling_config); result->set_native_pitch(static_cast(width) * get_format_block_size_in_bytes(surface_color_format) * result->samples_x); result->set_surface_dimensions(static_cast(width), static_cast(height), static_cast(pitch)); result->set_format(surface_color_format); @@ -182,11 +184,12 @@ struct gl_render_target_traits u32 address, rsx::surface_depth_format2 surface_depth_format, usz width, usz height, usz pitch, - rsx::surface_antialiasing antialias + rsx::surface_antialiasing antialias, + const rsx::surface_scaling_config_t& resolution_scaling_config ) { auto format = rsx::internals::surface_depth_format_to_gl(surface_depth_format); - const auto [width_, height_] = rsx::apply_resolution_scale(static_cast(width), static_cast(height)); + const auto [width_, height_] = rsx::apply_resolution_scale(resolution_scaling_config, static_cast(width), static_cast(height)); u8 samples; rsx::surface_sample_layout sample_layout; @@ -206,6 +209,7 @@ struct gl_render_target_traits result->set_name(fmt::format("DSV_%u@0x%x", result->id(), address)); result->set_aa_mode(antialias); + result->set_resolution_scaling_config(resolution_scaling_config); result->set_surface_dimensions(static_cast(width), static_cast(height), static_cast(pitch)); result->set_format(surface_depth_format); result->set_native_pitch(static_cast(width) * get_format_block_size_in_bytes(surface_depth_format) * result->samples_x); @@ -230,8 +234,11 @@ struct gl_render_target_traits if (!sink) { auto internal_format = static_cast(ref->get_internal_format()); - const auto [new_w, new_h] = rsx::apply_resolution_scale(prev.width, prev.height, - ref->get_surface_width(), ref->get_surface_height()); + const auto [new_w, new_h] = rsx::apply_resolution_scale( + ref->resolution_scaling_config, + prev.width, prev.height, + ref->get_surface_width(), + ref->get_surface_height()); sink = std::make_unique(new_w, new_h, ref->samples(), internal_format, ref->format_class()); sink->add_ref(); @@ -240,6 +247,9 @@ struct gl_render_target_traits sink->state_flags = rsx::surface_state_flags::erase_bkgnd; sink->format_info = ref->format_info; + sink->sample_layout = ref->sample_layout; + sink->resolution_scaling_config = ref->resolution_scaling_config; + sink->set_name(fmt::format("SINK_%u@0x%x", sink->id(), address)); sink->set_spp(ref->get_spp()); sink->set_native_pitch(static_cast(prev.width) * ref->get_bpp() * ref->samples_x); diff --git a/rpcs3/Emu/RSX/GL/GLTextureCache.h b/rpcs3/Emu/RSX/GL/GLTextureCache.h index a4b931186f..27b455374e 100644 --- a/rpcs3/Emu/RSX/GL/GLTextureCache.h +++ b/rpcs3/Emu/RSX/GL/GLTextureCache.h @@ -287,6 +287,7 @@ namespace gl u32 transfer_width = width; u32 transfer_height = height; u32 transfer_x = 0, transfer_y = 0; + u16 resolution_scale_percent = 100; if (context == rsx::texture_upload_context::framebuffer_storage) { @@ -295,9 +296,10 @@ namespace gl target_texture = surface->get_surface(rsx::surface_access::transfer_read); transfer_width *= surface->samples_x; transfer_height *= surface->samples_y; + resolution_scale_percent = surface->resolution_scaling_config.scale_percent; } - if ((rsx::get_resolution_scale_percent() != 100 && context == rsx::texture_upload_context::framebuffer_storage) || + if ((resolution_scale_percent != 100 && context == rsx::texture_upload_context::framebuffer_storage) || (vram_texture->pitch() != rsx_pitch)) { areai src_area = { 0, 0, 0, 0 }; diff --git a/rpcs3/Emu/RSX/RSXThread.cpp b/rpcs3/Emu/RSX/RSXThread.cpp index 7d634de677..6ffa8f2e9a 100644 --- a/rpcs3/Emu/RSX/RSXThread.cpp +++ b/rpcs3/Emu/RSX/RSXThread.cpp @@ -996,6 +996,12 @@ namespace rsx fifo_ctrl = std::make_unique<::rsx::FIFO::FIFO_control>(this); fifo_ctrl->set_get(ctrl->get); + resolution_scaling_config = + { + .scale_percent = static_cast(g_cfg.video.resolution_scale_percent), + .min_scalable_dimension = static_cast(g_cfg.video.min_scalable_dimension), + }; + last_guest_flip_timestamp = get_system_time() - 1000000; vblank_count = 0; @@ -1940,8 +1946,8 @@ namespace rsx m_graphics_state.set(rsx::rtt_config_valid); } - std::tie(region.x1, region.y1) = rsx::apply_resolution_scale(x1, y1, m_framebuffer_layout.width, m_framebuffer_layout.height); - std::tie(region.x2, region.y2) = rsx::apply_resolution_scale(x2, y2, m_framebuffer_layout.width, m_framebuffer_layout.height); + std::tie(region.x1, region.y1) = rsx::apply_resolution_scale(resolution_scaling_config, x1, y1, m_framebuffer_layout.width, m_framebuffer_layout.height); + std::tie(region.x2, region.y2) = rsx::apply_resolution_scale(resolution_scaling_config, x2, y2, m_framebuffer_layout.width, m_framebuffer_layout.height); return true; } diff --git a/rpcs3/Emu/RSX/RSXThread.h b/rpcs3/Emu/RSX/RSXThread.h index 4b2de0acc4..cdeaa9f419 100644 --- a/rpcs3/Emu/RSX/RSXThread.h +++ b/rpcs3/Emu/RSX/RSXThread.h @@ -215,6 +215,8 @@ namespace rsx atomic_bitmask_t async_flip_requested{}; u8 async_flip_buffer{ 0 }; + surface_scaling_config_t resolution_scaling_config{}; + void capture_frame(const std::string& name); const backend_configuration& get_backend_config() const { return backend_config; } diff --git a/rpcs3/Emu/RSX/RSXZCULL.cpp b/rpcs3/Emu/RSX/RSXZCULL.cpp index 54b7ed4139..51052c8879 100644 --- a/rpcs3/Emu/RSX/RSXZCULL.cpp +++ b/rpcs3/Emu/RSX/RSXZCULL.cpp @@ -335,7 +335,7 @@ namespace rsx auto scale_result = [](u32 value) { - const auto scale = rsx::get_resolution_scale_percent(); + const auto scale = get_current_renderer()->resolution_scaling_config.scale_percent; const auto result = (value * 10000ull) / (scale * scale); return std::max(1u, static_cast(result)); }; diff --git a/rpcs3/Emu/RSX/VK/VKDraw.cpp b/rpcs3/Emu/RSX/VK/VKDraw.cpp index b18ebaed3a..5c3737fdf2 100644 --- a/rpcs3/Emu/RSX/VK/VKDraw.cpp +++ b/rpcs3/Emu/RSX/VK/VKDraw.cpp @@ -164,7 +164,7 @@ void VKGSRender::update_draw_state() rsx::method_registers.current_draw_clause.primitive <= rsx::primitive_type::line_strip) { const float actual_line_width = - m_device->get_wide_lines_support() ? rsx::method_registers.line_width() * rsx::get_resolution_scale() : 1.f; + m_device->get_wide_lines_support() ? rsx::method_registers.line_width() * resolution_scaling_config.scale_factor() : 1.f; vkCmdSetLineWidth(*m_current_command_buffer, actual_line_width); } diff --git a/rpcs3/Emu/RSX/VK/VKGSRender.cpp b/rpcs3/Emu/RSX/VK/VKGSRender.cpp index 8d90f9a09f..5906c14824 100644 --- a/rpcs3/Emu/RSX/VK/VKGSRender.cpp +++ b/rpcs3/Emu/RSX/VK/VKGSRender.cpp @@ -1152,6 +1152,7 @@ void VKGSRender::check_present_status() void VKGSRender::set_viewport() { const auto [clip_width, clip_height] = rsx::apply_resolution_scale( + resolution_scaling_config, rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height()); const auto zclip_near = rsx::method_registers.clip_min(); @@ -1952,7 +1953,7 @@ void VKGSRender::load_program_env() m_draw_processor.fill_scale_offset_data(buf, false); m_draw_processor.fill_user_clip_data(buf + 64); *(reinterpret_cast(buf + 68)) = ctx->transform_branch_bits(); - *(reinterpret_cast(buf + 72)) = ctx->point_size() * rsx::get_resolution_scale(); + *(reinterpret_cast(buf + 72)) = ctx->point_size() * resolution_scaling_config.scale_factor(); *(reinterpret_cast(buf + 76)) = ctx->clip_min(); *(reinterpret_cast(buf + 80)) = ctx->clip_max(); @@ -2441,6 +2442,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context) m_framebuffer_layout.target, m_framebuffer_layout.aa_mode, m_framebuffer_layout.raster_type, m_framebuffer_layout.color_addresses, m_framebuffer_layout.zeta_address, m_framebuffer_layout.actual_color_pitch, m_framebuffer_layout.actual_zeta_pitch, + resolution_scaling_config, (*m_device), *m_current_command_buffer); // Reset framebuffer information @@ -2620,7 +2622,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, fbo_height] = rsx::apply_resolution_scale(m_framebuffer_layout.width, m_framebuffer_layout.height); + const auto [fbo_width, fbo_height] = rsx::apply_resolution_scale(resolution_scaling_config, 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 f8345726ef..3b47e28162 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -341,6 +341,7 @@ vk::viewable_image* VKGSRender::get_present_source(/* inout */ vk::present_surfa image_to_flip = section.surface->get_surface(rsx::surface_access::transfer_read); std::tie(info->width, info->height) = rsx::apply_resolution_scale( + resolution_scaling_config, std::min(surface_width, info->width), std::min(surface_height, info->height)); } @@ -550,7 +551,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) if (avconfig.stereo_enabled) [[unlikely]] { - const auto [unused, min_expected_height] = rsx::apply_resolution_scale(RSX_SURFACE_DIMENSION_IGNORED, buffer_height + 30); + const auto [unused, min_expected_height] = rsx::apply_resolution_scale(resolution_scaling_config, RSX_SURFACE_DIMENSION_IGNORED, buffer_height + 30); if (image_to_flip->height() < min_expected_height) { // Get image for second eye @@ -565,7 +566,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) else { // Account for possible insets - const auto [unused2, scaled_buffer_height] = rsx::apply_resolution_scale(RSX_SURFACE_DIMENSION_IGNORED, buffer_height); + const auto [unused2, scaled_buffer_height] = rsx::apply_resolution_scale(resolution_scaling_config, RSX_SURFACE_DIMENSION_IGNORED, buffer_height); buffer_height = std::min(image_to_flip->height() - min_expected_height, scaled_buffer_height); } } @@ -935,7 +936,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) "Texture uploads: %12u (%u from CPU - %02u%%, %u copies avoided)\n" "Vertex cache hits: %10u/%u (%u%%)\n" "Program cache lookup ellision: %u/%u (%u%%)", - info.stats.framebuffer_stats.to_string(!backend_config.supports_hw_msaa), + info.stats.framebuffer_stats.to_string(resolution_scaling_config, !backend_config.supports_hw_msaa), get_load(), info.stats.draw_calls, info.stats.submit_count, info.stats.setup_time, info.stats.vertex_upload_time, info.stats.textures_upload_time, info.stats.draw_exec_time, info.stats.flip_time, num_dirty_textures, texture_memory_size, tmp_texture_memory_size, diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp b/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp index 9d66baa9d2..138f7e46aa 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.cpp @@ -735,7 +735,7 @@ namespace vk #endif } - if (g_cfg.video.resolution_scale_percent == 100 && spp == 1) [[likely]] + if (resolution_scaling_config.scale_percent == 100 && spp == 1) [[likely]] { push_layout(cmd, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); vk::upload_image(cmd, this, { subres }, get_gcm_format(), is_swizzled, 1, aspect(), upload_heap, heap_align, upload_flags); @@ -842,7 +842,7 @@ namespace vk bool render_target::matches_dimensions(u16 _width, u16 _height) const { // Use forward scaling to account for rounding and clamping errors - const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(_width, _height); + const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(resolution_scaling_config, _width, _height); return (scaled_w == width()) && (scaled_h == height()); } diff --git a/rpcs3/Emu/RSX/VK/VKRenderTargets.h b/rpcs3/Emu/RSX/VK/VKRenderTargets.h index 3c3ef0acbd..7d4f515b4e 100644 --- a/rpcs3/Emu/RSX/VK/VKRenderTargets.h +++ b/rpcs3/Emu/RSX/VK/VKRenderTargets.h @@ -200,6 +200,7 @@ namespace vk rsx::surface_color_format format, usz width, usz height, usz pitch, rsx::surface_antialiasing antialias, + const rsx::surface_scaling_config_t& resolution_scaling_config, vk::render_device& device, vk::command_buffer& cmd) { const auto fmt = vk::get_compatible_surface_format(format); @@ -231,7 +232,7 @@ namespace vk } std::unique_ptr rtt; - const auto [width_, height_] = rsx::apply_resolution_scale(static_cast(width), static_cast(height)); + const auto [width_, height_] = rsx::apply_resolution_scale(resolution_scaling_config, static_cast(width), static_cast(height)); rtt = std::make_unique(device, device.get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, @@ -251,6 +252,7 @@ namespace vk rtt->set_format(format); rtt->set_aa_mode(antialias); + rtt->set_resolution_scaling_config(resolution_scaling_config); rtt->sample_layout = sample_layout; rtt->memory_usage_flags = rsx::surface_usage_flags::attachment; rtt->state_flags = rsx::surface_state_flags::erase_bkgnd; @@ -270,6 +272,7 @@ namespace vk rsx::surface_depth_format2 format, usz width, usz height, usz pitch, rsx::surface_antialiasing antialias, + const rsx::surface_scaling_config_t& resolution_scaling_config, vk::render_device& device, vk::command_buffer& cmd) { const VkFormat requested_format = vk::get_compatible_depth_surface_format(device.get_formats_support(), format); @@ -296,7 +299,7 @@ namespace vk } std::unique_ptr ds; - const auto [width_, height_] = rsx::apply_resolution_scale(static_cast(width), static_cast(height)); + const auto [width_, height_] = rsx::apply_resolution_scale(resolution_scaling_config, static_cast(width), static_cast(height)); ds = std::make_unique(device, device.get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, @@ -316,6 +319,7 @@ namespace vk ds->set_format(format); ds->set_aa_mode(antialias); + ds->set_resolution_scaling_config(resolution_scaling_config); ds->sample_layout = sample_layout; ds->memory_usage_flags = rsx::surface_usage_flags::attachment; ds->state_flags = rsx::surface_state_flags::erase_bkgnd; @@ -337,7 +341,9 @@ namespace vk { if (!sink) { - const auto [new_w, new_h] = rsx::apply_resolution_scale(prev.width, prev.height, + const auto [new_w, new_h] = rsx::apply_resolution_scale( + ref->resolution_scaling_config, + prev.width, prev.height, ref->get_surface_width(), ref->get_surface_height()); auto& dev = cmd.get_command_pool().get_owner(); @@ -355,6 +361,10 @@ namespace vk ref->format_class()); sink->add_ref(); + + sink->sample_layout = ref->sample_layout; + sink->resolution_scaling_config = ref->resolution_scaling_config; + sink->set_spp(ref->get_spp()); sink->format_info = ref->format_info; sink->memory_usage_flags = rsx::surface_usage_flags::storage; diff --git a/rpcs3/Emu/RSX/VK/VKResourceManager.cpp b/rpcs3/Emu/RSX/VK/VKResourceManager.cpp index 9d34509a09..82be25194f 100644 --- a/rpcs3/Emu/RSX/VK/VKResourceManager.cpp +++ b/rpcs3/Emu/RSX/VK/VKResourceManager.cpp @@ -214,7 +214,7 @@ namespace vk const auto local_memory_usage = vmm_get_application_memory_usage(mem_info.device_local); constexpr u64 _1M = 0x100000; - const auto res_scale = rsx::get_resolution_scale(); + const auto res_scale = rsx::get_current_renderer()->resolution_scaling_config.scale_factor(); const auto mem_threshold_1 = static_cast(256 * res_scale * res_scale) * _1M; const auto mem_threshold_2 = static_cast(64 * res_scale * res_scale) * _1M; diff --git a/rpcs3/Emu/RSX/rsx_utils.h b/rpcs3/Emu/RSX/rsx_utils.h index 8fec69f88a..310af56dab 100644 --- a/rpcs3/Emu/RSX/rsx_utils.h +++ b/rpcs3/Emu/RSX/rsx_utils.h @@ -37,7 +37,38 @@ namespace rsx fatal }; - //Base for resources with reference counting + namespace limits + { + enum + { + fragment_textures_count = 16, + vertex_textures_count = 4, + vertex_count = 16, + fragment_count = 32, + tiles_count = 15, + zculls_count = 8, + color_buffers_count = 4 + }; + } + + namespace constants + { + constexpr std::array fragment_texture_names = + { + "tex0", "tex1", "tex2", "tex3", "tex4", "tex5", "tex6", "tex7", + "tex8", "tex9", "tex10", "tex11", "tex12", "tex13", "tex14", "tex15", + }; + + constexpr std::array vertex_texture_names = + { + "vtex0", "vtex1", "vtex2", "vtex3", + }; + + // Local RSX memory base (known as constant) + constexpr u32 local_mem_base = 0xC0000000; + } + + // Base for resources with reference counting class ref_counted { protected: @@ -73,37 +104,6 @@ namespace rsx } }; - namespace limits - { - enum - { - fragment_textures_count = 16, - vertex_textures_count = 4, - vertex_count = 16, - fragment_count = 32, - tiles_count = 15, - zculls_count = 8, - color_buffers_count = 4 - }; - } - - namespace constants - { - constexpr std::array fragment_texture_names = - { - "tex0", "tex1", "tex2", "tex3", "tex4", "tex5", "tex6", "tex7", - "tex8", "tex9", "tex10", "tex11", "tex12", "tex13", "tex14", "tex15", - }; - - constexpr std::array vertex_texture_names = - { - "vtex0", "vtex1", "vtex2", "vtex3", - }; - - // Local RSX memory base (known as constant) - constexpr u32 local_mem_base = 0xC0000000; - } - /** * Holds information about a framebuffer */ @@ -214,6 +214,14 @@ namespace rsx bool swizzled; }; + struct surface_scaling_config_t + { + u16 scale_percent = 100; + u16 min_scalable_dimension = 0; + + f32 scale_factor() const { return scale_percent * 0.01f; } + }; + template void pad_texture(const void* input_pixels, void* output_pixels, u16 input_width, u16 input_height, u16 output_width, u16 /*output_height*/) { @@ -575,28 +583,23 @@ namespace rsx } } - static inline f32 get_resolution_scale() - { - return g_cfg.video.strict_rendering_mode ? 1.f : (g_cfg.video.resolution_scale_percent / 100.f); - } - - static inline int get_resolution_scale_percent() - { - return g_cfg.video.strict_rendering_mode ? 100 : g_cfg.video.resolution_scale_percent; - } - template - static inline const std::pair apply_resolution_scale(u16 width, u16 height, u16 ref_width = 0, u16 ref_height = 0) + static inline const std::pair apply_resolution_scale( + const surface_scaling_config_t& config, + u16 width, + u16 height, + u16 ref_width = 0, + u16 ref_height = 0) { ref_width = (ref_width) ? ref_width : width; ref_height = (ref_height) ? ref_height : height; const u16 ref = std::max(ref_width, ref_height); - if (ref > g_cfg.video.min_scalable_dimension) + if (ref > config.min_scalable_dimension) { // Upscale both width and height - width = (get_resolution_scale_percent() * width) / 100; - height = (get_resolution_scale_percent() * height) / 100; + width = (config.scale_percent * width) / 100; + height = (config.scale_percent * height) / 100; if constexpr (clamp) { @@ -609,11 +612,14 @@ namespace rsx } template - static inline const std::pair apply_inverse_resolution_scale(u16 width, u16 height) + static inline const std::pair apply_inverse_resolution_scale( + const surface_scaling_config_t& config, + u16 width, + u16 height) { // Inverse scale - auto width_ = (width * 100) / get_resolution_scale_percent(); - auto height_ = (height * 100) / get_resolution_scale_percent(); + auto width_ = (width * 100) / config.scale_percent; + auto height_ = (height * 100) / config.scale_percent; if constexpr (clamp) { @@ -621,7 +627,7 @@ namespace rsx height_ = std::max(height_, 1); } - if (std::max(width_, height_) > g_cfg.video.min_scalable_dimension) + if (std::max(width_, height_) > config.min_scalable_dimension) { return { width_, height_ }; } diff --git a/rpcs3/rpcs3qt/gs_frame.cpp b/rpcs3/rpcs3qt/gs_frame.cpp index 67a750316e..c73db8a687 100644 --- a/rpcs3/rpcs3qt/gs_frame.cpp +++ b/rpcs3/rpcs3qt/gs_frame.cpp @@ -15,6 +15,7 @@ #include "Emu/Cell/Modules/cellScreenshot.h" #include "Emu/Cell/Modules/cellAudio.h" #include "Emu/Cell/lv2/sys_rsxaudio.h" +#include "Emu/RSX/RSXThread.h" #include "Emu/RSX/rsx_utils.h" #include "Emu/RSX/Overlays/overlay_message.h" #include "Emu/Io/interception.h" @@ -1040,7 +1041,7 @@ void gs_frame::take_screenshot(std::vector&& data, u32 sshot_width, u32 ssho if (new_size.width != static_cast(img.width()) || new_size.height != static_cast(img.height())) { - const int scale = rsx::get_resolution_scale_percent(); + const int scale = rsx::get_current_renderer()->resolution_scaling_config.scale_percent; const int x = (scale * manager.overlay_offset_x) / 100; const int y = (scale * manager.overlay_offset_y) / 100; const int width = (scale * overlay_img.width()) / 100;