rsx: Resolution scaling overhaul

- Enforce square pixels instead of per-axis scaling
This commit is contained in:
kd-11 2020-11-17 23:56:33 +03:00 committed by kd-11
parent 68931b4c43
commit 0e7a705254
10 changed files with 121 additions and 89 deletions

View File

@ -85,10 +85,14 @@ namespace rsx
if (g_cfg.video.resolution_scale_percent != 100) if (g_cfg.video.resolution_scale_percent != 100)
{ {
auto src = static_cast<T>(source); auto src = static_cast<T>(source);
src_w = rsx::apply_resolution_scale(src_w, true, src->get_surface_width(rsx::surface_metrics::pixels));
src_h = rsx::apply_resolution_scale(src_h, true, src->get_surface_height(rsx::surface_metrics::pixels)); std::tie(src_w, src_h) = rsx::apply_resolution_scale<true>(src_w, src_h,
dst_w = rsx::apply_resolution_scale(dst_w, true, target_surface->get_surface_width(rsx::surface_metrics::pixels)); src->get_surface_width(rsx::surface_metrics::pixels),
dst_h = rsx::apply_resolution_scale(dst_h, true, target_surface->get_surface_height(rsx::surface_metrics::pixels)); src->get_surface_height(rsx::surface_metrics::pixels));
std::tie(dst_w, dst_h) = rsx::apply_resolution_scale<true>(dst_w, dst_h,
target_surface->get_surface_width(rsx::surface_metrics::pixels),
target_surface->get_surface_height(rsx::surface_metrics::pixels));
} }
width = src_w; width = src_w;
@ -484,11 +488,8 @@ namespace rsx
// Apply resolution scale if needed // Apply resolution scale if needed
if (g_cfg.video.resolution_scale_percent != 100) if (g_cfg.video.resolution_scale_percent != 100)
{ {
auto src_width = rsx::apply_resolution_scale(slice.width, true, slice.source->width()); auto [src_width, src_height] = rsx::apply_resolution_scale<true>(slice.width, slice.height, slice.source->width(), slice.source->height());
auto src_height = rsx::apply_resolution_scale(slice.height, true, 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 = rsx::apply_resolution_scale(slice.width, true, slice.target->width());
auto dst_height = rsx::apply_resolution_scale(slice.height, true, 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;
@ -496,10 +497,8 @@ namespace rsx
slice.width = src_width; slice.width = src_width;
slice.height = src_height; slice.height = src_height;
slice.src_x = rsx::apply_resolution_scale(slice.src_x, false, slice.source->width()); 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());
slice.src_y = rsx::apply_resolution_scale(slice.src_y, false, 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());
slice.dst_x = rsx::apply_resolution_scale(slice.dst_x, false, slice.target->width());
slice.dst_y = rsx::apply_resolution_scale(slice.dst_y, false, slice.target->height());
} }
} }

View File

@ -287,8 +287,8 @@ namespace rsx
// How much of this slice to read? // How much of this slice to read?
int rebased = int(section.dst_area.y) - slice_begin; int rebased = int(section.dst_area.y) - slice_begin;
const auto src_x = section.src_area.x; auto src_x = section.src_area.x;
const auto dst_x = section.dst_area.x; auto dst_x = section.dst_area.x;
auto src_y = section.src_area.y; auto src_y = section.src_area.y;
auto dst_y = section.dst_area.y; auto dst_y = section.dst_area.y;
@ -306,20 +306,22 @@ namespace rsx
const auto h = std::min(section_end, slice_end) - dst_y; const auto h = std::min(section_end, slice_end) - dst_y;
dst_y = (dst_y - slice_begin); dst_y = (dst_y - slice_begin);
const auto src_width = rsx::apply_resolution_scale(section.src_area.width, true); const auto [src_width, src_height] = rsx::apply_resolution_scale<true>(section.src_area.width, h, attr.width, attr.height);
const auto src_height = rsx::apply_resolution_scale(h, true); const auto [dst_width, unused] = rsx::apply_resolution_scale<true>(section.dst_area.width, RSX_SURFACE_DIMENSION_IGNORED, attr.width, RSX_SURFACE_DIMENSION_IGNORED);
const auto dst_width = rsx::apply_resolution_scale(section.dst_area.width, true);
const auto dst_height = src_height; const auto dst_height = src_height;
std::tie(src_x, src_y) = rsx::apply_resolution_scale<false>(src_x, src_y, attr.width, attr.height);
std::tie(dst_x, dst_y) = rsx::apply_resolution_scale<false>(dst_x, dst_y, attr.width, attr.height);
out.push_back out.push_back
({ ({
section.surface->get_surface(rsx::surface_access::read), section.surface->get_surface(rsx::surface_access::read),
surface_transform::identity, surface_transform::identity,
0, 0,
rsx::apply_resolution_scale(src_x, true), static_cast<u16>(src_x),
rsx::apply_resolution_scale(src_y, true), static_cast<u16>(src_y),
rsx::apply_resolution_scale(dst_x, true), static_cast<u16>(dst_x),
rsx::apply_resolution_scale(dst_y, true), static_cast<u16>(dst_y),
slice, slice,
src_width, src_height, src_width, src_height,
dst_width, dst_height dst_width, dst_height
@ -365,20 +367,23 @@ 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>(std::get<1>(clipped).x), static_cast<u16>(dst_y - slice_begin), attr.width, attr.height);
const auto [_dst_w, _dst_h] = rsx::apply_resolution_scale<true>(dst_w, height, attr.width, attr.height);
out.push_back out.push_back
({ ({
section->get_raw_texture(), section->get_raw_texture(),
surface_transform::identity, surface_transform::identity,
0, 0,
static_cast<u16>(std::get<0>(clipped).x), // src.x static_cast<u16>(std::get<0>(clipped).x), // src.x
static_cast<u16>(std::get<0>(clipped).y), // src.y static_cast<u16>(std::get<0>(clipped).y), // src.y
rsx::apply_resolution_scale(static_cast<u16>(std::get<1>(clipped).x), true), // dst.x _dst_x, // dst.x
rsx::apply_resolution_scale(static_cast<u16>(dst_y - slice_begin), true), // dst.y _dst_y, // dst.y
slice, slice,
src_w, src_w,
height, height,
rsx::apply_resolution_scale(dst_w, true), _dst_w,
rsx::apply_resolution_scale(height, true), _dst_h,
}); });
} }
else else
@ -539,8 +544,7 @@ namespace rsx
attr2.height < surface_height || attr2.height < surface_height ||
force_convert) force_convert)
{ {
const auto scaled_w = rsx::apply_resolution_scale(attr2.width, true); const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale<true>(attr2.width, attr2.height);
const auto scaled_h = rsx::apply_resolution_scale(attr2.height, true);
const auto format_class = (force_convert) ? classify_format(attr2.gcm_format) : texptr->format_class(); const auto format_class = (force_convert) ? classify_format(attr2.gcm_format) : texptr->format_class();
const auto command = surface_is_rop_target ? deferred_request_command::copy_image_dynamic : deferred_request_command::copy_image_static; const auto command = surface_is_rop_target ? deferred_request_command::copy_image_dynamic : deferred_request_command::copy_image_static;
@ -557,8 +561,7 @@ namespace rsx
texptr->format_class(), scale, rsx::texture_dimension_extended::texture_dimension_2d, surface_is_rop_target }; texptr->format_class(), scale, rsx::texture_dimension_extended::texture_dimension_2d, surface_is_rop_target };
} }
const auto scaled_w = rsx::apply_resolution_scale(attr2.width, true); const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale<true>(attr2.width, attr2.height);
const auto scaled_h = rsx::apply_resolution_scale(attr2.height, true);
if (extended_dimension == rsx::texture_dimension_extended::texture_dimension_3d) if (extended_dimension == rsx::texture_dimension_extended::texture_dimension_3d)
{ {
@ -643,8 +646,7 @@ namespace rsx
} }
// If this method was called, there is no easy solution, likely means atlas gather is needed // If this method was called, there is no easy solution, likely means atlas gather is needed
auto scaled_w = rsx::apply_resolution_scale(attr2.width, true); const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale(attr2.width, attr2.height);
auto scaled_h = rsx::apply_resolution_scale(attr2.height, true);
const auto format_class = classify_format(attr2.gcm_format); const auto format_class = classify_format(attr2.gcm_format);
if (extended_dimension == rsx::texture_dimension_extended::texture_dimension_cubemap) if (extended_dimension == rsx::texture_dimension_extended::texture_dimension_cubemap)
@ -717,8 +719,7 @@ 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]]
{ {
mip.src_w = rsx::apply_resolution_scale(attr.width, true); std::tie(mip.src_w, mip.src_h) = rsx::apply_resolution_scale<true>(attr.width, attr.height);
mip.src_h = rsx::apply_resolution_scale(attr.height, true);
} }
else else
{ {
@ -763,8 +764,7 @@ namespace rsx
if (apply_upscaling) if (apply_upscaling)
{ {
auto& mip = sections.back(); auto& mip = sections.back();
mip.dst_w = rsx::apply_resolution_scale(mip.dst_w, true, level0_attr.width); 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);
mip.dst_h = rsx::apply_resolution_scale(mip.dst_h, true, level0_attr.height);
} }
return true; return true;

View File

@ -32,8 +32,9 @@ extern CellGcmContextData current_context;
void GLGSRender::set_viewport() 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 = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_width(), true); const auto [clip_width, clip_height] = rsx::apply_resolution_scale<true>(
const auto clip_height = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_height(), true); 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);
} }

View File

@ -48,8 +48,9 @@ gl::texture* GLGSRender::get_present_source(gl::present_surface_info* info, cons
surface->read_barrier(cmd); surface->read_barrier(cmd);
image = section.surface->get_surface(rsx::surface_access::read); image = section.surface->get_surface(rsx::surface_access::read);
info->width = rsx::apply_resolution_scale(std::min(surface_width, static_cast<u16>(info->width)), true); std::tie(info->width, info->height) = rsx::apply_resolution_scale<true>(
info->height = rsx::apply_resolution_scale(std::min(surface_height, static_cast<u16>(info->height)), true); std::min(surface_width, static_cast<u16>(info->width)),
std::min(surface_height, static_cast<u16>(info->height)));
} }
} }
} }
@ -154,7 +155,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
if (avconfig->_3d) [[unlikely]] if (avconfig->_3d) [[unlikely]]
{ {
const auto min_expected_height = rsx::apply_resolution_scale(buffer_height + 30, true); const auto [unused, min_expected_height] = rsx::apply_resolution_scale<true>(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
@ -168,7 +169,8 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
else else
{ {
// Account for possible insets // Account for possible insets
buffer_height = std::min<u32>(image_to_flip_->height() - min_expected_height, rsx::apply_resolution_scale(buffer_height, true)); const auto [unused2, scaled_buffer_height] = rsx::apply_resolution_scale<true>(RSX_SURFACE_DIMENSION_IGNORED, buffer_height);
buffer_height = std::min<u32>(image_to_flip_->height() - min_expected_height, scaled_buffer_height);
} }
} }

View File

@ -108,7 +108,8 @@ 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
return (rsx::apply_resolution_scale(_width, true) == width()) && (rsx::apply_resolution_scale(_height, true) == height()); const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale<true>(_width, _height);
return (scaled_w == width()) && (scaled_h == height());
} }
void memory_barrier(gl::command_context& cmd, rsx::surface_access access); void memory_barrier(gl::command_context& cmd, rsx::surface_access access);
@ -144,10 +145,10 @@ struct gl_render_target_traits
) )
{ {
auto format = rsx::internals::surface_color_format_to_gl(surface_color_format); 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));
std::unique_ptr<gl::render_target> result(new gl::render_target(rsx::apply_resolution_scale(static_cast<u16>(width), true), std::unique_ptr<gl::render_target> result(new gl::render_target(width_, height_,
rsx::apply_resolution_scale(static_cast<u16>(height), true), static_cast<GLenum>(format.internal_format), static_cast<GLenum>(format.internal_format), RSX_FORMAT_CLASS_COLOR));
RSX_FORMAT_CLASS_COLOR));
result->set_aa_mode(antialias); result->set_aa_mode(antialias);
result->set_native_pitch(static_cast<u16>(width) * get_format_block_size_in_bytes(surface_color_format) * result->samples_x); result->set_native_pitch(static_cast<u16>(width) * get_format_block_size_in_bytes(surface_color_format) * result->samples_x);
@ -173,9 +174,10 @@ struct gl_render_target_traits
) )
{ {
auto format = rsx::internals::surface_depth_format_to_gl(surface_depth_format); auto format = rsx::internals::surface_depth_format_to_gl(surface_depth_format);
std::unique_ptr<gl::render_target> result(new gl::render_target(rsx::apply_resolution_scale(static_cast<u16>(width), true), const auto [width_, height_] = rsx::apply_resolution_scale<true>(static_cast<u16>(width), static_cast<u16>(height));
rsx::apply_resolution_scale(static_cast<u16>(height), true), static_cast<GLenum>(format.internal_format),
rsx::classify_format(surface_depth_format))); std::unique_ptr<gl::render_target> result(new gl::render_target(width_, height_,
static_cast<GLenum>(format.internal_format), rsx::classify_format(surface_depth_format)));
result->set_aa_mode(antialias); result->set_aa_mode(antialias);
result->set_surface_dimensions(static_cast<u16>(width), static_cast<u16>(height), static_cast<u16>(pitch)); result->set_surface_dimensions(static_cast<u16>(width), static_cast<u16>(height), static_cast<u16>(pitch));
@ -201,8 +203,8 @@ 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 = rsx::apply_resolution_scale(prev.width, true, ref->get_surface_width(rsx::surface_metrics::pixels)); const auto [new_w, new_h] = rsx::apply_resolution_scale<true>(prev.width, prev.height,
const auto new_h = rsx::apply_resolution_scale(prev.height, true, ref->get_surface_height(rsx::surface_metrics::pixels)); 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, internal_format, ref->format_class()); sink = std::make_unique<gl::render_target>(new_w, new_h, internal_format, ref->format_class());
sink->add_ref(); sink->add_ref();

View File

@ -1518,10 +1518,8 @@ namespace rsx
framebuffer_status_valid = true; framebuffer_status_valid = true;
} }
region.x1 = rsx::apply_resolution_scale(x1, false); std::tie(region.x1, region.y1) = rsx::apply_resolution_scale<false>(x1, y1);
region.x2 = rsx::apply_resolution_scale(x2, true); std::tie(region.x2, region.y2) = rsx::apply_resolution_scale<true>(x2, y2);
region.y1 = rsx::apply_resolution_scale(y1, false);
region.y2 = rsx::apply_resolution_scale(y2, true);
return true; return true;
} }

View File

@ -952,8 +952,9 @@ VkDescriptorSet VKGSRender::allocate_descriptor_set()
void VKGSRender::set_viewport() void VKGSRender::set_viewport()
{ {
const auto clip_width = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_width(), true); const auto [clip_width, clip_height] = rsx::apply_resolution_scale<true>(
const auto clip_height = rsx::apply_resolution_scale(rsx::method_registers.surface_clip_height(), true); 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();
const auto zclip_far = rsx::method_registers.clip_max(); const auto zclip_far = rsx::method_registers.clip_max();
@ -2187,8 +2188,7 @@ void VKGSRender::prepare_rtts(rsx::framebuffer_creation_context context)
m_cached_renderpass = vk::get_renderpass(*m_device, m_current_renderpass_key); 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 = rsx::apply_resolution_scale(m_framebuffer_layout.width, true); const auto [fbo_width, fbo_height] = rsx::apply_resolution_scale<true>(m_framebuffer_layout.width, m_framebuffer_layout.height);
const auto fbo_height = rsx::apply_resolution_scale(m_framebuffer_layout.height, true);
if (m_draw_fbo) if (m_draw_fbo)
{ {

View File

@ -313,8 +313,9 @@ vk::image* VKGSRender::get_present_source(vk::present_surface_info* info, const
surface->read_barrier(*m_current_command_buffer); surface->read_barrier(*m_current_command_buffer);
image_to_flip = section.surface->get_surface(rsx::surface_access::read); image_to_flip = section.surface->get_surface(rsx::surface_access::read);
info->width = rsx::apply_resolution_scale(std::min(surface_width, static_cast<u16>(info->width)), true); std::tie(info->width, info->height) = rsx::apply_resolution_scale<true>(
info->height = rsx::apply_resolution_scale(std::min(surface_height, static_cast<u16>(info->height)), true); std::min(surface_width, static_cast<u16>(info->width)),
std::min(surface_height, static_cast<u16>(info->height)));
} }
} }
} }
@ -469,7 +470,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
if (avconfig->_3d) [[unlikely]] if (avconfig->_3d) [[unlikely]]
{ {
const auto min_expected_height = rsx::apply_resolution_scale(buffer_height + 30, true); const auto [unused, min_expected_height] = rsx::apply_resolution_scale<true>(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
@ -483,7 +484,8 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
else else
{ {
// Account for possible insets // Account for possible insets
buffer_height = std::min<u32>(image_to_flip->height() - min_expected_height, rsx::apply_resolution_scale(buffer_height, true)); const auto [unused2, scaled_buffer_height] = rsx::apply_resolution_scale<true>(RSX_SURFACE_DIMENSION_IGNORED, buffer_height);
buffer_height = std::min<u32>(image_to_flip->height() - min_expected_height, scaled_buffer_height);
} }
} }

View File

@ -345,8 +345,9 @@ namespace vk
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
return (rsx::apply_resolution_scale(_width, true) == width()) && (rsx::apply_resolution_scale(_height, true) == height()); const auto [scaled_w, scaled_h] = rsx::apply_resolution_scale<true>(_width, _height);
return (scaled_w == width()) && (scaled_h == height());
} }
void texture_barrier(vk::command_buffer& cmd) void texture_barrier(vk::command_buffer& cmd)
@ -644,11 +645,13 @@ namespace rsx
} }
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));
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,
VK_IMAGE_TYPE_2D, VK_IMAGE_TYPE_2D,
requested_format, requested_format,
static_cast<uint32_t>(rsx::apply_resolution_scale(static_cast<u16>(width), true)), static_cast<uint32_t>(rsx::apply_resolution_scale(static_cast<u16>(height), true)), 1, 1, 1, static_cast<uint32_t>(width_), static_cast<uint32_t>(height_), 1, 1, 1,
static_cast<VkSampleCountFlagBits>(samples), static_cast<VkSampleCountFlagBits>(samples),
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_TILING_OPTIMAL,
@ -702,11 +705,13 @@ namespace rsx
} }
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));
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,
VK_IMAGE_TYPE_2D, VK_IMAGE_TYPE_2D,
requested_format, requested_format,
static_cast<uint32_t>(rsx::apply_resolution_scale(static_cast<u16>(width), true)), static_cast<uint32_t>(rsx::apply_resolution_scale(static_cast<u16>(height), true)), 1, 1, 1, static_cast<uint32_t>(width_), static_cast<uint32_t>(height_), 1, 1, 1,
static_cast<VkSampleCountFlagBits>(samples), static_cast<VkSampleCountFlagBits>(samples),
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_TILING_OPTIMAL,
@ -738,8 +743,8 @@ namespace rsx
{ {
if (!sink) if (!sink)
{ {
const auto new_w = rsx::apply_resolution_scale(prev.width, true, ref->get_surface_width(rsx::surface_metrics::pixels)); const auto [new_w, new_h] = rsx::apply_resolution_scale<true>(prev.width, prev.height,
const auto new_h = rsx::apply_resolution_scale(prev.height, true, 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();
sink = std::make_unique<vk::render_target>(dev, dev.get_memory_mapping().device_local, sink = std::make_unique<vk::render_target>(dev, dev.get_memory_mapping().device_local,

View File

@ -14,6 +14,8 @@ extern "C"
#include <libavutil/pixfmt.h> #include <libavutil/pixfmt.h>
} }
#define RSX_SURFACE_DIMENSION_IGNORED 1
namespace rsx namespace rsx
{ {
// Import address_range utilities // Import address_range utilities
@ -586,33 +588,54 @@ namespace rsx
return g_cfg.video.strict_rendering_mode ? 100 : g_cfg.video.resolution_scale_percent; return g_cfg.video.strict_rendering_mode ? 100 : g_cfg.video.resolution_scale_percent;
} }
static inline const u16 apply_resolution_scale(u16 value, bool clamp, u16 ref = 0) template <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)
{ {
if (ref == 0) u16 ref;
ref = value; if (width > height) [[likely]]
{
if (ref <= g_cfg.video.min_scalable_dimension) ref = (ref_width) ? ref_width : width;
return value; }
else if (clamp)
return static_cast<u16>(std::max((get_resolution_scale_percent() * value) / 100, 1));
else else
return static_cast<u16>((get_resolution_scale_percent() * value) / 100); {
ref = (ref_height) ? ref_height : height;
}
if (ref > g_cfg.video.min_scalable_dimension)
{
// Upscale both width and height
width = (get_resolution_scale_percent() * width) / 100;
height = (get_resolution_scale_percent() * height) / 100;
if constexpr (clamp)
{
width = std::max<u16>(width, 1);
height = std::max<u16>(height, 1);
}
}
return { width, height };
} }
static inline const u16 apply_inverse_resolution_scale(u16 value, bool clamp) template <bool clamp = false>
static inline const std::pair<u16, u16> apply_inverse_resolution_scale(u16 width, u16 height)
{ {
u16 result = value; // Inverse scale
auto width_ = (width * 100) / get_resolution_scale_percent();
auto height_ = (height * 100) / get_resolution_scale_percent();
if (clamp) if (clamp)
result = static_cast<u16>(std::max((value * 100) / get_resolution_scale_percent(), 1)); {
else width_ = std::max<u16>(width_, 1);
result = static_cast<u16>((value * 100) / get_resolution_scale_percent()); height_ = std::max<u16>(height_, 1);
}
if (result <= g_cfg.video.min_scalable_dimension) if (std::max(width_, height_) > g_cfg.video.min_scalable_dimension)
return value; {
return { width_, height_ };
}
return result; return { width, height };
} }
/** /**