Merge branch 'master' into feature/perf-overlay-window-space

This commit is contained in:
kd-11 2026-03-25 21:58:54 +03:00 committed by GitHub
commit 35ab5e1bb2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 208 additions and 131 deletions

View File

@ -398,6 +398,7 @@ namespace rsx
surface_antialiasing antialias, surface_antialiasing antialias,
usz width, usz height, usz pitch, usz width, usz height, usz pitch,
u8 bpp, u8 bpp,
const rsx::surface_scaling_config_t& scaling_config,
Args&&... extra_params) Args&&... extra_params)
{ {
surface_storage_type old_surface_storage; surface_storage_type old_surface_storage;
@ -531,7 +532,7 @@ namespace rsx
if (!new_surface) if (!new_surface)
{ {
ensure(store); ensure(store);
new_surface_storage = Traits::create_new_surface(address, format, width, height, pitch, antialias, std::forward<Args>(extra_params)...); new_surface_storage = Traits::create_new_surface(address, format, width, height, pitch, antialias, scaling_config, std::forward<Args>(extra_params)...);
new_surface = Traits::get(new_surface_storage); new_surface = Traits::get(new_surface_storage);
Traits::prepare_surface_for_drawing(command_list, new_surface); Traits::prepare_surface_for_drawing(command_list, new_surface);
allocate_rsx_memory(new_surface); allocate_rsx_memory(new_surface);
@ -842,11 +843,13 @@ namespace rsx
surface_color_format color_format, surface_color_format color_format,
surface_antialiasing antialias, surface_antialiasing antialias,
usz width, usz height, usz pitch, usz width, usz height, usz pitch,
const rsx::surface_scaling_config_t& scaling_config,
Args&&... extra_params) Args&&... extra_params)
{ {
return bind_surface_address<false>( return bind_surface_address<false>(
command_list, address, color_format, antialias, command_list, address, color_format, antialias,
width, height, pitch, get_format_block_size_in_bytes(color_format), width, height, pitch, get_format_block_size_in_bytes(color_format),
scaling_config,
std::forward<Args>(extra_params)...); std::forward<Args>(extra_params)...);
} }
@ -857,12 +860,14 @@ namespace rsx
surface_depth_format2 depth_format, surface_depth_format2 depth_format,
surface_antialiasing antialias, surface_antialiasing antialias,
usz width, usz height, usz pitch, usz width, usz height, usz pitch,
const rsx::surface_scaling_config_t& scaling_config,
Args&&... extra_params) Args&&... extra_params)
{ {
return bind_surface_address<true>( return bind_surface_address<true>(
command_list, address, depth_format, antialias, command_list, address, depth_format, antialias,
width, height, pitch, width, height, pitch,
get_format_block_size_in_bytes(depth_format), get_format_block_size_in_bytes(depth_format),
scaling_config,
std::forward<Args>(extra_params)...); std::forward<Args>(extra_params)...);
} }
@ -969,6 +974,7 @@ namespace rsx
surface_raster_type raster_type, surface_raster_type raster_type,
const std::array<u32, 4> &surface_addresses, u32 address_z, const std::array<u32, 4> &surface_addresses, u32 address_z,
const std::array<u32, 4> &surface_pitch, u32 zeta_pitch, const std::array<u32, 4> &surface_pitch, u32 zeta_pitch,
const rsx::surface_scaling_config_t& scaling_config,
Args&&... extra_params) Args&&... extra_params)
{ {
u32 clip_width = clip_horizontal_reg; 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], 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, bind_address_as_render_targets(command_list, surface_addresses[surface_index], color_format, antialias,
clip_width, clip_height, surface_pitch[surface_index], std::forward<Args>(extra_params)...)); clip_width, clip_height, surface_pitch[surface_index], scaling_config, std::forward<Args>(extra_params)...));
m_bound_render_target_ids.push_back(surface_index); m_bound_render_target_ids.push_back(surface_index);
} }
@ -1014,7 +1020,7 @@ namespace rsx
{ {
m_bound_depth_stencil = std::make_pair(address_z, m_bound_depth_stencil = std::make_pair(address_z,
bind_address_as_depth_stencil(command_list, address_z, depth_format, antialias, bind_address_as_depth_stencil(command_list, address_z, depth_format, antialias,
clip_width, clip_height, zeta_pitch, std::forward<Args>(extra_params)...)); clip_width, clip_height, zeta_pitch, scaling_config, std::forward<Args>(extra_params)...));
} }
else else
{ {

View File

@ -88,18 +88,18 @@ namespace rsx
auto dst_h = std::get<3>(region); auto dst_h = std::get<3>(region);
// Apply resolution scale if needed // Apply resolution scale if needed
if (g_cfg.video.resolution_scale_percent != 100) auto src = static_cast<T>(source);
{ std::tie(src_w, src_h) = rsx::apply_resolution_scale<true>(
auto src = static_cast<T>(source); src->resolution_scaling_config,
src_w, src_h,
src->template get_surface_width<rsx::surface_metrics::pixels>(),
src->template get_surface_height<rsx::surface_metrics::pixels>());
std::tie(src_w, src_h) = rsx::apply_resolution_scale<true>(src_w, src_h, std::tie(dst_w, dst_h) = rsx::apply_resolution_scale<true>(
src->template get_surface_width<rsx::surface_metrics::pixels>(), target_surface->resolution_scaling_config,
src->template get_surface_height<rsx::surface_metrics::pixels>()); dst_w, dst_h,
target_surface->template get_surface_width<rsx::surface_metrics::pixels>(),
std::tie(dst_w, dst_h) = rsx::apply_resolution_scale<true>(dst_w, dst_h, target_surface->template get_surface_height<rsx::surface_metrics::pixels>());
target_surface->template get_surface_width<rsx::surface_metrics::pixels>(),
target_surface->template get_surface_height<rsx::surface_metrics::pixels>());
}
width = src_w; width = src_w;
height = src_h; height = src_h;
@ -146,6 +146,9 @@ namespace rsx
u8 samples_x = 1; u8 samples_x = 1;
u8 samples_y = 1; u8 samples_y = 1;
// Scaling configuration
surface_scaling_config_t resolution_scaling_config;
rsx::address_range32 memory_range; rsx::address_range32 memory_range;
std::unique_ptr<typename std::remove_pointer_t<image_storage_type>> resolve_surface; std::unique_ptr<typename std::remove_pointer_t<image_storage_type>> resolve_surface;
@ -303,6 +306,11 @@ namespace rsx
format_info.gcm_depth_format = format; 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 inline rsx::surface_color_format get_surface_color_format() const
{ {
return format_info.gcm_color_format; 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 inline bool dirty() const
{ {
return (state_flags != rsx::surface_state_flags::ready) || !old_contents.empty(); return (state_flags != rsx::surface_state_flags::ready) || !old_contents.empty();
@ -541,10 +554,10 @@ namespace rsx
} }
// Apply resolution scale if needed // 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<true>(slice.width, slice.height, slice.source->width(), slice.source->height()); auto [src_width, src_height] = rsx::apply_resolution_scale<true>(resolution_scaling_config, slice.width, slice.height, slice.source->width(), slice.source->height());
auto [dst_width, dst_height] = rsx::apply_resolution_scale<true>(slice.width, slice.height, slice.target->width(), slice.target->height()); auto [dst_width, dst_height] = rsx::apply_resolution_scale<true>(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_x *= f32(dst_width) / src_width;
slice.transfer_scale_y *= f32(dst_height) / src_height; slice.transfer_scale_y *= f32(dst_height) / src_height;
@ -552,8 +565,8 @@ namespace rsx
slice.width = src_width; slice.width = src_width;
slice.height = src_height; slice.height = src_height;
std::tie(slice.src_x, slice.src_y) = rsx::apply_resolution_scale<false>(slice.src_x, slice.src_y, slice.source->width(), slice.source->height()); std::tie(slice.src_x, slice.src_y) = rsx::apply_resolution_scale<false>(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<false>(slice.dst_x, slice.dst_y, slice.target->width(), slice.target->height()); std::tie(slice.dst_x, slice.dst_y) = rsx::apply_resolution_scale<false>(resolution_scaling_config, slice.dst_x, slice.dst_y, slice.target->width(), slice.target->height());
} }
} }

View File

@ -2413,9 +2413,13 @@ namespace rsx
// 2. The image has to have been generated on the GPU (fbo or blit target only) // 2. The image has to have been generated on the GPU (fbo or blit target only)
rsx::simple_array<copy_region_descriptor> sections; rsx::simple_array<copy_region_descriptor> 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<typename surface_store_type::surface_type>(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 // Abort if mip0 is not compatible
return result; return result;
@ -2445,7 +2449,7 @@ namespace rsx
options, range, extended_dimension, m_rtts, std::forward<Args>(extras)...); options, range, extended_dimension, m_rtts, std::forward<Args>(extras)...);
if (!ret.validate() || 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 // Abort
break; break;
@ -2778,7 +2782,7 @@ namespace rsx
surf->template get_surface_height<rsx::surface_metrics::pixels>() != surf->height()) surf->template get_surface_height<rsx::surface_metrics::pixels>() != surf->height())
{ {
// Must go through a scaling operation due to resolution scaling being present // 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; use_null_region = false;
} }
} }
@ -3389,8 +3393,8 @@ namespace rsx
{ {
const auto surface_width = src_subres.surface->template get_surface_width<rsx::surface_metrics::pixels>(); const auto surface_width = src_subres.surface->template get_surface_width<rsx::surface_metrics::pixels>();
const auto surface_height = src_subres.surface->template get_surface_height<rsx::surface_metrics::pixels>(); const auto surface_height = src_subres.surface->template get_surface_height<rsx::surface_metrics::pixels>();
std::tie(src_area.x1, src_area.y1) = rsx::apply_resolution_scale<false>(src_area.x1, src_area.y1, surface_width, surface_height); std::tie(src_area.x1, src_area.y1) = rsx::apply_resolution_scale<false>(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<true>(src_area.x2, src_area.y2, surface_width, surface_height); std::tie(src_area.x2, src_area.y2) = rsx::apply_resolution_scale<true>(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 // The resource is of surface type; possibly disabled AA emulation
src_subres.surface->transform_blit_coordinates(rsx::surface_access::transfer_read, src_area); 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<rsx::surface_metrics::pixels>(); const auto surface_width = dst_subres.surface->template get_surface_width<rsx::surface_metrics::pixels>();
const auto surface_height = dst_subres.surface->template get_surface_height<rsx::surface_metrics::pixels>(); const auto surface_height = dst_subres.surface->template get_surface_height<rsx::surface_metrics::pixels>();
std::tie(dst_area.x1, dst_area.y1) = rsx::apply_resolution_scale<false>(dst_area.x1, dst_area.y1, surface_width, surface_height); std::tie(dst_area.x1, dst_area.y1) = rsx::apply_resolution_scale<false>(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<true>(dst_area.x2, dst_area.y2, surface_width, surface_height); std::tie(dst_area.x2, dst_area.y2) = rsx::apply_resolution_scale<true>(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 // The resource is of surface type; possibly disabled AA emulation
dst_subres.surface->transform_blit_coordinates(rsx::surface_access::transfer_write, dst_area); dst_subres.surface->transform_blit_coordinates(rsx::surface_access::transfer_write, dst_area);

View File

@ -357,11 +357,11 @@ namespace rsx
const auto surface_width = section.surface->template get_surface_width<rsx::surface_metrics::pixels>(); const auto surface_width = section.surface->template get_surface_width<rsx::surface_metrics::pixels>();
const auto surface_height = section.surface->template get_surface_height<rsx::surface_metrics::pixels>(); const auto surface_height = section.surface->template get_surface_height<rsx::surface_metrics::pixels>();
const auto [src_width, src_height] = rsx::apply_resolution_scale<true>(section.src_area.width, h, surface_width, surface_height); const auto [src_width, src_height] = rsx::apply_resolution_scale<true>(section.surface->resolution_scaling_config, section.src_area.width, h, surface_width, surface_height);
const auto [dst_width, dst_height] = rsx::apply_resolution_scale<true>(section.dst_area.width, h, attr.width, attr.height); const auto [dst_width, dst_height] = rsx::apply_resolution_scale<true>(section.surface->resolution_scaling_config, section.dst_area.width, h, attr.width, attr.height);
std::tie(src_x, src_y) = rsx::apply_resolution_scale<false>(src_x, src_y, surface_width, surface_height); std::tie(src_x, src_y) = rsx::apply_resolution_scale<false>(section.surface->resolution_scaling_config, src_x, src_y, surface_width, surface_height);
std::tie(dst_x, dst_y) = rsx::apply_resolution_scale<false>(dst_x, dst_y, attr.width, attr.height); std::tie(dst_x, dst_y) = rsx::apply_resolution_scale<false>(section.surface->resolution_scaling_config, dst_x, dst_y, attr.width, attr.height);
section.surface->memory_barrier(cmd, rsx::surface_access::transfer_read); section.surface->memory_barrier(cmd, rsx::surface_access::transfer_read);
@ -430,8 +430,10 @@ namespace rsx
if (scaling) if (scaling)
{ {
// Since output is upscaled, also upscale on dst // Since output is upscaled, also upscale on dst
const auto [_dst_x, _dst_y] = rsx::apply_resolution_scale<false>(static_cast<u16>(dst_offset.x), static_cast<u16>(dst_y - dst_slice_begin), attr.width, attr.height);
const auto [_dst_w, _dst_h] = rsx::apply_resolution_scale<true>(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<false>(scaling_config, static_cast<u16>(dst_offset.x), static_cast<u16>(dst_y - dst_slice_begin), attr.width, attr.height);
const auto [_dst_w, _dst_h] = rsx::apply_resolution_scale<true>(scaling_config, dst_w, height, attr.width, attr.height);
out.push_back out.push_back
({ ({
@ -660,10 +662,10 @@ namespace rsx
bool is_depth = texptr->is_depth_surface(); bool is_depth = texptr->is_depth_surface();
auto attr2 = attr; 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<true>(attr.width, attr.height, surface_width, surface_height); const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale<true>(texptr->resolution_scaling_config, attr.width, attr.height, surface_width, surface_height);
const auto [unused, scaled_slice_h] = rsx::apply_resolution_scale<false>(RSX_SURFACE_DIMENSION_IGNORED, attr.slice_h, surface_width, surface_height); const auto [unused, scaled_slice_h] = rsx::apply_resolution_scale<false>(texptr->resolution_scaling_config, RSX_SURFACE_DIMENSION_IGNORED, attr.slice_h, surface_width, surface_height);
attr2.width = scaled_w; attr2.width = scaled_w;
attr2.height = scaled_h; attr2.height = scaled_h;
attr2.slice_h = scaled_slice_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 // 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 format_class = classify_format(attr2.gcm_format);
const auto upload_context = (fbos.empty()) ? texture_upload_context::shader_read : texture_upload_context::framebuffer_storage; const auto upload_context = (fbos.empty()) ? texture_upload_context::shader_read : texture_upload_context::framebuffer_storage;
@ -892,14 +895,15 @@ namespace rsx
return result; return result;
} }
template<typename sampled_image_descriptor, typename copy_region_descriptor_type> template<typename to_surface_type_converter, typename sampled_image_descriptor, typename copy_region_descriptor_type>
bool append_mipmap_level( bool append_mipmap_level(
to_surface_type_converter&& as_surface_type, // Cast function to surface type
rsx::simple_array<copy_region_descriptor_type>& sections, // Destination list rsx::simple_array<copy_region_descriptor_type>& sections, // Destination list
const sampled_image_descriptor& level, // Descriptor for the image level being checked const sampled_image_descriptor& level, // Descriptor for the image level being checked
const image_section_attributes_t& attr, // Attributes of image level const image_section_attributes_t& attr, // Attributes of image level
u8 mipmap_level, // Level index u8 mipmap_level, // Level index
bool apply_upscaling, // Whether to upscale the results or not bool apply_upscaling, // Whether to upscale the results or not
const image_section_attributes_t& level0_attr) // Attributes of the first mipmap level const image_section_attributes_t& level0_attr) // Attributes of the first mipmap level
{ {
if (level.image_handle) if (level.image_handle)
{ {
@ -916,7 +920,8 @@ namespace rsx
// Calculate transfer dimensions from attr // Calculate transfer dimensions from attr
if (level.upload_context == rsx::texture_upload_context::framebuffer_storage) [[likely]] if (level.upload_context == rsx::texture_upload_context::framebuffer_storage) [[likely]]
{ {
std::tie(mip.src_w, mip.src_h) = rsx::apply_resolution_scale<true>(attr.width, attr.height); auto rtv = as_surface_type(mip);
std::tie(mip.src_w, mip.src_h) = rsx::apply_resolution_scale<true>(rtv->resolution_scaling_config, attr.width, attr.height);
} }
else else
{ {
@ -964,7 +969,9 @@ namespace rsx
if (apply_upscaling) if (apply_upscaling)
{ {
auto& mip = sections.back(); auto& mip = sections.back();
std::tie(mip.dst_w, mip.dst_h) = rsx::apply_resolution_scale<true>(mip.dst_w, mip.dst_h, level0_attr.width, level0_attr.height); std::tie(mip.dst_w, mip.dst_h) = rsx::apply_resolution_scale<true>(
as_surface_type(mip)->resolution_scaling_config,
mip.dst_w, mip.dst_h, level0_attr.width, level0_attr.height);
} }
return true; return true;

View File

@ -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 // Format is sorted by sample count
struct sorted_message_t struct sorted_message_t
@ -70,7 +70,7 @@ namespace rsx
for (const auto& [aa_mode, stat] : data) for (const auto& [aa_mode, stat] : data)
{ {
auto real_stat = stat; 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); real_stats.push_back(real_stat);
sorted_message_t msg; sorted_message_t msg;

View File

@ -12,6 +12,8 @@ namespace rsx
{ {
enum class surface_antialiasing : u8; enum class surface_antialiasing : u8;
struct surface_scaling_config_t;
struct framebuffer_dimensions_t struct framebuffer_dimensions_t
{ {
u16 width; u16 width;
@ -42,7 +44,7 @@ namespace rsx
void add(u16 width, u16 height, rsx::surface_antialiasing aa); void add(u16 width, u16 height, rsx::surface_antialiasing aa);
// Returns a formatted string representing the statistics collected over the frame. // 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 struct frame_statistics_t

View File

@ -699,7 +699,9 @@ namespace rsx
const auto window_origin = REGS(m_ctx)->shader_window_origin(); const auto window_origin = REGS(m_ctx)->shader_window_origin();
const u32 window_height = REGS(m_ctx)->shader_window_height(); const u32 window_height = REGS(m_ctx)->shader_window_height();
const auto pixel_center = REGS(m_ctx)->pixel_center(); const auto pixel_center = REGS(m_ctx)->pixel_center();
const f32 resolution_scale = (window_height <= static_cast<u32>(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_scale = (window_origin == rsx::window_origin::top) ? (1.f / resolution_scale) : (-1.f / resolution_scale);
payload.wpos_bias[0] = 0.f; payload.wpos_bias[0] = 0.f;

View File

@ -227,7 +227,7 @@ void GLGSRender::update_draw_state()
case rsx::primitive_type::lines: case rsx::primitive_type::lines:
case rsx::primitive_type::line_loop: case rsx::primitive_type::line_loop:
case rsx::primitive_type::line_strip: 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); gl_state.enable(rsx::method_registers.line_smooth_enabled(), GL_LINE_SMOOTH);
break; break;
default: default:

View File

@ -73,6 +73,7 @@ void GLGSRender::set_viewport()
{ {
// NOTE: scale offset matrix already contains the viewport transformation // NOTE: scale offset matrix already contains the viewport transformation
const auto [clip_width, clip_height] = rsx::apply_resolution_scale<true>( const auto [clip_width, clip_height] = rsx::apply_resolution_scale<true>(
resolution_scaling_config,
rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height()); rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height());
glViewport(0, 0, clip_width, 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_scale_offset_data(buf, false);
m_draw_processor.fill_user_clip_data(buf + 64); m_draw_processor.fill_user_clip_data(buf + 64);
*(reinterpret_cast<u32*>(buf + 68)) = rsx::method_registers.transform_branch_bits(); *(reinterpret_cast<u32*>(buf + 68)) = rsx::method_registers.transform_branch_bits();
*(reinterpret_cast<f32*>(buf + 72)) = rsx::method_registers.point_size() * rsx::get_resolution_scale(); *(reinterpret_cast<f32*>(buf + 72)) = rsx::method_registers.point_size() * resolution_scaling_config.scale_factor();
*(reinterpret_cast<f32*>(buf + 76)) = rsx::method_registers.clip_min(); *(reinterpret_cast<f32*>(buf + 76)) = rsx::method_registers.clip_min();
*(reinterpret_cast<f32*>(buf + 80)) = rsx::method_registers.clip_max(); *(reinterpret_cast<f32*>(buf + 80)) = rsx::method_registers.clip_max();

View File

@ -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); image = section.surface->get_surface(rsx::surface_access::transfer_read);
std::tie(info->width, info->height) = rsx::apply_resolution_scale<true>( std::tie(info->width, info->height) = rsx::apply_resolution_scale<true>(
resolution_scaling_config,
std::min(surface_width, info->width), std::min(surface_width, info->width),
std::min(surface_height, info->height)); 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]] if (avconfig.stereo_enabled) [[unlikely]]
{ {
const auto [unused, min_expected_height] = rsx::apply_resolution_scale<true>(RSX_SURFACE_DIMENSION_IGNORED, buffer_height + 30); const auto [unused, min_expected_height] = rsx::apply_resolution_scale<true>(resolution_scaling_config, RSX_SURFACE_DIMENSION_IGNORED, buffer_height + 30);
if (image_to_flip->height() < min_expected_height) if (image_to_flip->height() < min_expected_height)
{ {
// Get image for second eye // Get image for second eye
@ -240,7 +241,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
else else
{ {
// Account for possible insets // Account for possible insets
const auto [unused2, scaled_buffer_height] = rsx::apply_resolution_scale<true>(RSX_SURFACE_DIMENSION_IGNORED, buffer_height); const auto [unused2, scaled_buffer_height] = rsx::apply_resolution_scale<true>(resolution_scaling_config, RSX_SURFACE_DIMENSION_IGNORED, buffer_height);
buffer_height = std::min<u32>(image_to_flip->height() - min_expected_height, scaled_buffer_height); buffer_height = std::min<u32>(image_to_flip->height() - min_expected_height, scaled_buffer_height);
} }
} }
@ -479,7 +480,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
"Texture uploads: %11u (%u from CPU - %02u%%, %u copies avoided)\n" "Texture uploads: %11u (%u from CPU - %02u%%, %u copies avoided)\n"
"Vertex cache hits: %9u/%u (%u%%)\n" "Vertex cache hits: %9u/%u (%u%%)\n"
"Program cache lookup ellision: %u/%u (%u%%)", "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, 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, 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, num_flushes, num_misses, cache_miss_ratio, num_unavoidable, num_mispredict, num_speculate,

View File

@ -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.width, m_framebuffer_layout.height,
m_framebuffer_layout.target, m_framebuffer_layout.aa_mode, m_framebuffer_layout.raster_type, 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.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<GLuint, 4> color_targets; std::array<GLuint, 4> color_targets;
GLuint depth_stencil_target; GLuint depth_stencil_target;
@ -448,7 +449,7 @@ void gl::render_target::load_memory(gl::command_context& cmd)
subres.data = { vm::get_super_ptr<const std::byte>(base_addr), static_cast<std::span<const std::byte>::size_type>(rsx_pitch * surface_height * samples_y) }; subres.data = { vm::get_super_ptr<const std::byte>(base_addr), static_cast<std::span<const std::byte>::size_type>(rsx_pitch * surface_height * samples_y) };
// TODO: MSAA support // 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 }); gl::upload_texture(cmd, this, get_gcm_format(), is_swizzled, { subres });
} }

View File

@ -98,7 +98,7 @@ namespace gl
bool matches_dimensions(u16 _width, u16 _height) const bool matches_dimensions(u16 _width, u16 _height) const
{ {
//Use forward scaling to account for rounding and clamping errors //Use forward scaling to account for rounding and clamping errors
const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale<true>(_width, _height); const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale<true>(resolution_scaling_config, _width, _height);
return (scaled_w == width()) && (scaled_h == height()); return (scaled_w == width()) && (scaled_h == height());
} }
@ -138,11 +138,12 @@ struct gl_render_target_traits
u32 address, u32 address,
rsx::surface_color_format surface_color_format, rsx::surface_color_format surface_color_format,
usz width, usz height, usz pitch, 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); auto format = rsx::internals::surface_color_format_to_gl(surface_color_format);
const auto [width_, height_] = rsx::apply_resolution_scale<true>(static_cast<u16>(width), static_cast<u16>(height)); const auto [width_, height_] = rsx::apply_resolution_scale<true>(resolution_scaling_config, static_cast<u16>(width), static_cast<u16>(height));
u8 samples; u8 samples;
rsx::surface_sample_layout sample_layout; 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_name(fmt::format("RTV_%u@0x%x", result->id(), address));
result->set_aa_mode(antialias); result->set_aa_mode(antialias);
result->set_resolution_scaling_config(resolution_scaling_config);
result->set_native_pitch(static_cast<u32>(width) * get_format_block_size_in_bytes(surface_color_format) * result->samples_x); result->set_native_pitch(static_cast<u32>(width) * get_format_block_size_in_bytes(surface_color_format) * result->samples_x);
result->set_surface_dimensions(static_cast<u16>(width), static_cast<u16>(height), static_cast<u32>(pitch)); result->set_surface_dimensions(static_cast<u16>(width), static_cast<u16>(height), static_cast<u32>(pitch));
result->set_format(surface_color_format); result->set_format(surface_color_format);
@ -182,11 +184,12 @@ struct gl_render_target_traits
u32 address, u32 address,
rsx::surface_depth_format2 surface_depth_format, rsx::surface_depth_format2 surface_depth_format,
usz width, usz height, usz pitch, 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); auto format = rsx::internals::surface_depth_format_to_gl(surface_depth_format);
const auto [width_, height_] = rsx::apply_resolution_scale<true>(static_cast<u16>(width), static_cast<u16>(height)); const auto [width_, height_] = rsx::apply_resolution_scale<true>(resolution_scaling_config, static_cast<u16>(width), static_cast<u16>(height));
u8 samples; u8 samples;
rsx::surface_sample_layout sample_layout; 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_name(fmt::format("DSV_%u@0x%x", result->id(), address));
result->set_aa_mode(antialias); result->set_aa_mode(antialias);
result->set_resolution_scaling_config(resolution_scaling_config);
result->set_surface_dimensions(static_cast<u16>(width), static_cast<u16>(height), static_cast<u32>(pitch)); result->set_surface_dimensions(static_cast<u16>(width), static_cast<u16>(height), static_cast<u32>(pitch));
result->set_format(surface_depth_format); result->set_format(surface_depth_format);
result->set_native_pitch(static_cast<u32>(width) * get_format_block_size_in_bytes(surface_depth_format) * result->samples_x); result->set_native_pitch(static_cast<u32>(width) * get_format_block_size_in_bytes(surface_depth_format) * result->samples_x);
@ -230,8 +234,11 @@ struct gl_render_target_traits
if (!sink) if (!sink)
{ {
auto internal_format = static_cast<GLenum>(ref->get_internal_format()); auto internal_format = static_cast<GLenum>(ref->get_internal_format());
const auto [new_w, new_h] = rsx::apply_resolution_scale<true>(prev.width, prev.height, const auto [new_w, new_h] = rsx::apply_resolution_scale<true>(
ref->get_surface_width<rsx::surface_metrics::pixels>(), ref->get_surface_height<rsx::surface_metrics::pixels>()); ref->resolution_scaling_config,
prev.width, prev.height,
ref->get_surface_width<rsx::surface_metrics::pixels>(),
ref->get_surface_height<rsx::surface_metrics::pixels>());
sink = std::make_unique<gl::render_target>(new_w, new_h, ref->samples(), internal_format, ref->format_class()); sink = std::make_unique<gl::render_target>(new_w, new_h, ref->samples(), internal_format, ref->format_class());
sink->add_ref(); sink->add_ref();
@ -240,6 +247,9 @@ struct gl_render_target_traits
sink->state_flags = rsx::surface_state_flags::erase_bkgnd; sink->state_flags = rsx::surface_state_flags::erase_bkgnd;
sink->format_info = ref->format_info; 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_name(fmt::format("SINK_%u@0x%x", sink->id(), address));
sink->set_spp(ref->get_spp()); sink->set_spp(ref->get_spp());
sink->set_native_pitch(static_cast<u32>(prev.width) * ref->get_bpp() * ref->samples_x); sink->set_native_pitch(static_cast<u32>(prev.width) * ref->get_bpp() * ref->samples_x);

View File

@ -287,6 +287,7 @@ namespace gl
u32 transfer_width = width; u32 transfer_width = width;
u32 transfer_height = height; u32 transfer_height = height;
u32 transfer_x = 0, transfer_y = 0; u32 transfer_x = 0, transfer_y = 0;
u16 resolution_scale_percent = 100;
if (context == rsx::texture_upload_context::framebuffer_storage) if (context == rsx::texture_upload_context::framebuffer_storage)
{ {
@ -295,9 +296,10 @@ namespace gl
target_texture = surface->get_surface(rsx::surface_access::transfer_read); target_texture = surface->get_surface(rsx::surface_access::transfer_read);
transfer_width *= surface->samples_x; transfer_width *= surface->samples_x;
transfer_height *= surface->samples_y; 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)) (vram_texture->pitch() != rsx_pitch))
{ {
areai src_area = { 0, 0, 0, 0 }; areai src_area = { 0, 0, 0, 0 };

View File

@ -99,7 +99,7 @@ namespace rsx::overlays
ellipse_part->set_size(dim * 2, dim); ellipse_part->set_size(dim * 2, dim);
ellipse_part->set_padding(1); ellipse_part->set_padding(1);
ellipse_part->set_pos(0, 0); 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_size(dim, dim);
circle_part->set_padding(4); circle_part->set_padding(4);

View File

@ -996,6 +996,12 @@ namespace rsx
fifo_ctrl = std::make_unique<::rsx::FIFO::FIFO_control>(this); fifo_ctrl = std::make_unique<::rsx::FIFO::FIFO_control>(this);
fifo_ctrl->set_get(ctrl->get); fifo_ctrl->set_get(ctrl->get);
resolution_scaling_config =
{
.scale_percent = static_cast<u16>(g_cfg.video.resolution_scale_percent),
.min_scalable_dimension = static_cast<u16>(g_cfg.video.min_scalable_dimension),
};
last_guest_flip_timestamp = get_system_time() - 1000000; last_guest_flip_timestamp = get_system_time() - 1000000;
vblank_count = 0; vblank_count = 0;
@ -1940,8 +1946,8 @@ namespace rsx
m_graphics_state.set(rsx::rtt_config_valid); m_graphics_state.set(rsx::rtt_config_valid);
} }
std::tie(region.x1, region.y1) = rsx::apply_resolution_scale<false>(x1, y1, m_framebuffer_layout.width, m_framebuffer_layout.height); std::tie(region.x1, region.y1) = rsx::apply_resolution_scale<false>(resolution_scaling_config, x1, y1, m_framebuffer_layout.width, m_framebuffer_layout.height);
std::tie(region.x2, region.y2) = rsx::apply_resolution_scale<true>(x2, y2, m_framebuffer_layout.width, m_framebuffer_layout.height); std::tie(region.x2, region.y2) = rsx::apply_resolution_scale<true>(resolution_scaling_config, x2, y2, m_framebuffer_layout.width, m_framebuffer_layout.height);
return true; return true;
} }

View File

@ -215,6 +215,8 @@ namespace rsx
atomic_bitmask_t<flip_request> async_flip_requested{}; atomic_bitmask_t<flip_request> async_flip_requested{};
u8 async_flip_buffer{ 0 }; u8 async_flip_buffer{ 0 };
surface_scaling_config_t resolution_scaling_config{};
void capture_frame(const std::string& name); void capture_frame(const std::string& name);
const backend_configuration& get_backend_config() const { return backend_config; } const backend_configuration& get_backend_config() const { return backend_config; }

View File

@ -335,7 +335,7 @@ namespace rsx
auto scale_result = [](u32 value) 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); const auto result = (value * 10000ull) / (scale * scale);
return std::max(1u, static_cast<u32>(result)); return std::max(1u, static_cast<u32>(result));
}; };

View File

@ -164,7 +164,7 @@ void VKGSRender::update_draw_state()
rsx::method_registers.current_draw_clause.primitive <= rsx::primitive_type::line_strip) rsx::method_registers.current_draw_clause.primitive <= rsx::primitive_type::line_strip)
{ {
const float actual_line_width = 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); vkCmdSetLineWidth(*m_current_command_buffer, actual_line_width);
} }

View File

@ -1152,6 +1152,7 @@ void VKGSRender::check_present_status()
void VKGSRender::set_viewport() void VKGSRender::set_viewport()
{ {
const auto [clip_width, clip_height] = rsx::apply_resolution_scale<true>( const auto [clip_width, clip_height] = rsx::apply_resolution_scale<true>(
resolution_scaling_config,
rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height()); rsx::method_registers.surface_clip_width(), rsx::method_registers.surface_clip_height());
const auto zclip_near = rsx::method_registers.clip_min(); 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_scale_offset_data(buf, false);
m_draw_processor.fill_user_clip_data(buf + 64); m_draw_processor.fill_user_clip_data(buf + 64);
*(reinterpret_cast<u32*>(buf + 68)) = ctx->transform_branch_bits(); *(reinterpret_cast<u32*>(buf + 68)) = ctx->transform_branch_bits();
*(reinterpret_cast<f32*>(buf + 72)) = ctx->point_size() * rsx::get_resolution_scale(); *(reinterpret_cast<f32*>(buf + 72)) = ctx->point_size() * resolution_scaling_config.scale_factor();
*(reinterpret_cast<f32*>(buf + 76)) = ctx->clip_min(); *(reinterpret_cast<f32*>(buf + 76)) = ctx->clip_min();
*(reinterpret_cast<f32*>(buf + 80)) = ctx->clip_max(); *(reinterpret_cast<f32*>(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.target, m_framebuffer_layout.aa_mode, m_framebuffer_layout.raster_type,
m_framebuffer_layout.color_addresses, m_framebuffer_layout.zeta_address, 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,
(*m_device), *m_current_command_buffer); (*m_device), *m_current_command_buffer);
// Reset framebuffer information // 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); m_cached_renderpass = vk::get_renderpass(*m_device, m_current_renderpass_key);
// Search old framebuffers for this same configuration // Search old framebuffers for this same configuration
const auto [fbo_width, fbo_height] = rsx::apply_resolution_scale<true>(m_framebuffer_layout.width, m_framebuffer_layout.height); const auto [fbo_width, fbo_height] = rsx::apply_resolution_scale<true>(resolution_scaling_config, m_framebuffer_layout.width, m_framebuffer_layout.height);
if (m_draw_fbo) if (m_draw_fbo)
{ {

View File

@ -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); image_to_flip = section.surface->get_surface(rsx::surface_access::transfer_read);
std::tie(info->width, info->height) = rsx::apply_resolution_scale<true>( std::tie(info->width, info->height) = rsx::apply_resolution_scale<true>(
resolution_scaling_config,
std::min(surface_width, info->width), std::min(surface_width, info->width),
std::min(surface_height, info->height)); 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]] if (avconfig.stereo_enabled) [[unlikely]]
{ {
const auto [unused, min_expected_height] = rsx::apply_resolution_scale<true>(RSX_SURFACE_DIMENSION_IGNORED, buffer_height + 30); const auto [unused, min_expected_height] = rsx::apply_resolution_scale<true>(resolution_scaling_config, RSX_SURFACE_DIMENSION_IGNORED, buffer_height + 30);
if (image_to_flip->height() < min_expected_height) if (image_to_flip->height() < min_expected_height)
{ {
// Get image for second eye // Get image for second eye
@ -565,7 +566,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
else else
{ {
// Account for possible insets // Account for possible insets
const auto [unused2, scaled_buffer_height] = rsx::apply_resolution_scale<true>(RSX_SURFACE_DIMENSION_IGNORED, buffer_height); const auto [unused2, scaled_buffer_height] = rsx::apply_resolution_scale<true>(resolution_scaling_config, RSX_SURFACE_DIMENSION_IGNORED, buffer_height);
buffer_height = std::min<u32>(image_to_flip->height() - min_expected_height, scaled_buffer_height); buffer_height = std::min<u32>(image_to_flip->height() - min_expected_height, scaled_buffer_height);
} }
} }
@ -937,7 +938,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
"Texture uploads: %12u (%u from CPU - %02u%%, %u copies avoided)\n" "Texture uploads: %12u (%u from CPU - %02u%%, %u copies avoided)\n"
"Vertex cache hits: %10u/%u (%u%%)\n" "Vertex cache hits: %10u/%u (%u%%)\n"
"Program cache lookup ellision: %u/%u (%u%%)", "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, 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, info.stats.textures_upload_time, info.stats.draw_exec_time, info.stats.flip_time,
num_dirty_textures, texture_memory_size, tmp_texture_memory_size, num_dirty_textures, texture_memory_size, tmp_texture_memory_size,

View File

@ -735,7 +735,7 @@ namespace vk
#endif #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); 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); 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 bool render_target::matches_dimensions(u16 _width, u16 _height) const
{ {
// Use forward scaling to account for rounding and clamping errors // Use forward scaling to account for rounding and clamping errors
const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale<true>(_width, _height); const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale<true>(resolution_scaling_config, _width, _height);
return (scaled_w == width()) && (scaled_h == height()); return (scaled_w == width()) && (scaled_h == height());
} }

View File

@ -200,6 +200,7 @@ namespace vk
rsx::surface_color_format format, rsx::surface_color_format format,
usz width, usz height, usz pitch, usz width, usz height, usz pitch,
rsx::surface_antialiasing antialias, rsx::surface_antialiasing antialias,
const rsx::surface_scaling_config_t& resolution_scaling_config,
vk::render_device& device, vk::command_buffer& cmd) vk::render_device& device, vk::command_buffer& cmd)
{ {
const auto fmt = vk::get_compatible_surface_format(format); const auto fmt = vk::get_compatible_surface_format(format);
@ -231,7 +232,7 @@ namespace vk
} }
std::unique_ptr<vk::render_target> rtt; std::unique_ptr<vk::render_target> rtt;
const auto [width_, height_] = rsx::apply_resolution_scale<true>(static_cast<u16>(width), static_cast<u16>(height)); const auto [width_, height_] = rsx::apply_resolution_scale<true>(resolution_scaling_config, static_cast<u16>(width), static_cast<u16>(height));
rtt = std::make_unique<vk::render_target>(device, device.get_memory_mapping().device_local, rtt = std::make_unique<vk::render_target>(device, device.get_memory_mapping().device_local,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
@ -251,6 +252,7 @@ namespace vk
rtt->set_format(format); rtt->set_format(format);
rtt->set_aa_mode(antialias); rtt->set_aa_mode(antialias);
rtt->set_resolution_scaling_config(resolution_scaling_config);
rtt->sample_layout = sample_layout; rtt->sample_layout = sample_layout;
rtt->memory_usage_flags = rsx::surface_usage_flags::attachment; rtt->memory_usage_flags = rsx::surface_usage_flags::attachment;
rtt->state_flags = rsx::surface_state_flags::erase_bkgnd; rtt->state_flags = rsx::surface_state_flags::erase_bkgnd;
@ -270,6 +272,7 @@ namespace vk
rsx::surface_depth_format2 format, rsx::surface_depth_format2 format,
usz width, usz height, usz pitch, usz width, usz height, usz pitch,
rsx::surface_antialiasing antialias, rsx::surface_antialiasing antialias,
const rsx::surface_scaling_config_t& resolution_scaling_config,
vk::render_device& device, vk::command_buffer& cmd) vk::render_device& device, vk::command_buffer& cmd)
{ {
const VkFormat requested_format = vk::get_compatible_depth_surface_format(device.get_formats_support(), format); const VkFormat requested_format = vk::get_compatible_depth_surface_format(device.get_formats_support(), format);
@ -296,7 +299,7 @@ namespace vk
} }
std::unique_ptr<vk::render_target> ds; std::unique_ptr<vk::render_target> ds;
const auto [width_, height_] = rsx::apply_resolution_scale<true>(static_cast<u16>(width), static_cast<u16>(height)); const auto [width_, height_] = rsx::apply_resolution_scale<true>(resolution_scaling_config, static_cast<u16>(width), static_cast<u16>(height));
ds = std::make_unique<vk::render_target>(device, device.get_memory_mapping().device_local, ds = std::make_unique<vk::render_target>(device, device.get_memory_mapping().device_local,
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
@ -316,6 +319,7 @@ namespace vk
ds->set_format(format); ds->set_format(format);
ds->set_aa_mode(antialias); ds->set_aa_mode(antialias);
ds->set_resolution_scaling_config(resolution_scaling_config);
ds->sample_layout = sample_layout; ds->sample_layout = sample_layout;
ds->memory_usage_flags = rsx::surface_usage_flags::attachment; ds->memory_usage_flags = rsx::surface_usage_flags::attachment;
ds->state_flags = rsx::surface_state_flags::erase_bkgnd; ds->state_flags = rsx::surface_state_flags::erase_bkgnd;
@ -337,7 +341,9 @@ namespace vk
{ {
if (!sink) if (!sink)
{ {
const auto [new_w, new_h] = rsx::apply_resolution_scale<true>(prev.width, prev.height, const auto [new_w, new_h] = rsx::apply_resolution_scale<true>(
ref->resolution_scaling_config,
prev.width, prev.height,
ref->get_surface_width<rsx::surface_metrics::pixels>(), ref->get_surface_height<rsx::surface_metrics::pixels>()); ref->get_surface_width<rsx::surface_metrics::pixels>(), ref->get_surface_height<rsx::surface_metrics::pixels>());
auto& dev = cmd.get_command_pool().get_owner(); auto& dev = cmd.get_command_pool().get_owner();
@ -355,6 +361,10 @@ namespace vk
ref->format_class()); ref->format_class());
sink->add_ref(); sink->add_ref();
sink->sample_layout = ref->sample_layout;
sink->resolution_scaling_config = ref->resolution_scaling_config;
sink->set_spp(ref->get_spp()); sink->set_spp(ref->get_spp());
sink->format_info = ref->format_info; sink->format_info = ref->format_info;
sink->memory_usage_flags = rsx::surface_usage_flags::storage; sink->memory_usage_flags = rsx::surface_usage_flags::storage;

View File

@ -214,7 +214,7 @@ namespace vk
const auto local_memory_usage = vmm_get_application_memory_usage(mem_info.device_local); const auto local_memory_usage = vmm_get_application_memory_usage(mem_info.device_local);
constexpr u64 _1M = 0x100000; 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<u64>(256 * res_scale * res_scale) * _1M; const auto mem_threshold_1 = static_cast<u64>(256 * res_scale * res_scale) * _1M;
const auto mem_threshold_2 = static_cast<u64>(64 * res_scale * res_scale) * _1M; const auto mem_threshold_2 = static_cast<u64>(64 * res_scale * res_scale) * _1M;

View File

@ -37,7 +37,38 @@ namespace rsx
fatal 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<const char*, 16> fragment_texture_names =
{
"tex0", "tex1", "tex2", "tex3", "tex4", "tex5", "tex6", "tex7",
"tex8", "tex9", "tex10", "tex11", "tex12", "tex13", "tex14", "tex15",
};
constexpr std::array<const char*, 4> 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 class ref_counted
{ {
protected: 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<const char*, 16> fragment_texture_names =
{
"tex0", "tex1", "tex2", "tex3", "tex4", "tex5", "tex6", "tex7",
"tex8", "tex9", "tex10", "tex11", "tex12", "tex13", "tex14", "tex15",
};
constexpr std::array<const char*, 4> 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 * Holds information about a framebuffer
*/ */
@ -214,6 +214,14 @@ namespace rsx
bool swizzled; 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 <typename T> template <typename T>
void pad_texture(const void* input_pixels, void* output_pixels, u16 input_width, u16 input_height, u16 output_width, u16 /*output_height*/) 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 <bool clamp = false> template <bool clamp = false>
static inline const std::pair<u16, u16> apply_resolution_scale(u16 width, u16 height, u16 ref_width = 0, u16 ref_height = 0) static inline const std::pair<u16, u16> 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_width = (ref_width) ? ref_width : width;
ref_height = (ref_height) ? ref_height : height; ref_height = (ref_height) ? ref_height : height;
const u16 ref = std::max(ref_width, ref_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 // Upscale both width and height
width = (get_resolution_scale_percent() * width) / 100; width = (config.scale_percent * width) / 100;
height = (get_resolution_scale_percent() * height) / 100; height = (config.scale_percent * height) / 100;
if constexpr (clamp) if constexpr (clamp)
{ {
@ -609,11 +612,14 @@ namespace rsx
} }
template <bool clamp = false> template <bool clamp = false>
static inline const std::pair<u16, u16> apply_inverse_resolution_scale(u16 width, u16 height) static inline const std::pair<u16, u16> apply_inverse_resolution_scale(
const surface_scaling_config_t& config,
u16 width,
u16 height)
{ {
// Inverse scale // Inverse scale
auto width_ = (width * 100) / get_resolution_scale_percent(); auto width_ = (width * 100) / config.scale_percent;
auto height_ = (height * 100) / get_resolution_scale_percent(); auto height_ = (height * 100) / config.scale_percent;
if constexpr (clamp) if constexpr (clamp)
{ {
@ -621,7 +627,7 @@ namespace rsx
height_ = std::max<u16>(height_, 1); height_ = std::max<u16>(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_ }; return { width_, height_ };
} }

View File

@ -15,6 +15,7 @@
#include "Emu/Cell/Modules/cellScreenshot.h" #include "Emu/Cell/Modules/cellScreenshot.h"
#include "Emu/Cell/Modules/cellAudio.h" #include "Emu/Cell/Modules/cellAudio.h"
#include "Emu/Cell/lv2/sys_rsxaudio.h" #include "Emu/Cell/lv2/sys_rsxaudio.h"
#include "Emu/RSX/RSXThread.h"
#include "Emu/RSX/rsx_utils.h" #include "Emu/RSX/rsx_utils.h"
#include "Emu/RSX/Overlays/overlay_message.h" #include "Emu/RSX/Overlays/overlay_message.h"
#include "Emu/Io/interception.h" #include "Emu/Io/interception.h"
@ -1040,7 +1041,7 @@ void gs_frame::take_screenshot(std::vector<u8>&& data, u32 sshot_width, u32 ssho
if (new_size.width != static_cast<u32>(img.width()) || new_size.height != static_cast<u32>(img.height())) if (new_size.width != static_cast<u32>(img.width()) || new_size.height != static_cast<u32>(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 x = (scale * manager.overlay_offset_x) / 100;
const int y = (scale * manager.overlay_offset_y) / 100; const int y = (scale * manager.overlay_offset_y) / 100;
const int width = (scale * overlay_img.width()) / 100; const int width = (scale * overlay_img.width()) / 100;