mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-04-03 03:17:54 -06:00
rsx: Implement resolution scale change handling in surface cache
This commit is contained in:
parent
976cd1ce66
commit
e2dff6bbf8
@ -132,7 +132,7 @@ namespace rsx
|
||||
free_rsx_memory(Traits::get(sink));
|
||||
}
|
||||
|
||||
Traits::clone_surface(cmd, sink, region.source, new_address, region);
|
||||
Traits::clone_surface(cmd, sink, region.source, new_address, region, region.source->resolution_scaling_config);
|
||||
allocate_rsx_memory(Traits::get(sink));
|
||||
|
||||
if (invalidated) [[unlikely]]
|
||||
@ -449,7 +449,7 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
|
||||
if (Traits::surface_matches_properties(surface, format, width, height, antialias))
|
||||
if (Traits::surface_matches_properties(surface, format, width, height, antialias, scaling_config))
|
||||
{
|
||||
if (!pitch_compatible)
|
||||
{
|
||||
@ -496,7 +496,7 @@ namespace rsx
|
||||
for (auto It = invalidated_resources.begin(); It != invalidated_resources.end(); It++)
|
||||
{
|
||||
auto &surface = *It;
|
||||
if (Traits::surface_matches_properties(surface, format, width, height, antialias, true))
|
||||
if (Traits::surface_matches_properties(surface, format, width, height, antialias, scaling_config, true))
|
||||
{
|
||||
new_surface_storage = std::move(surface);
|
||||
Traits::notify_surface_reused(new_surface_storage);
|
||||
@ -1469,5 +1469,94 @@ namespace rsx
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void sync_scaling_config(command_list_type cmd, const rsx::surface_scaling_config_t& active_config)
|
||||
{
|
||||
auto process_list_function = [&](surface_ranged_map& data, const utils::address_range32& range)
|
||||
{
|
||||
std::vector<Traits::surface_type> surfaces_to_clone;
|
||||
|
||||
for (auto It = data.begin_range(range); It != data.end();)
|
||||
{
|
||||
auto surface = Traits::get(It->second);
|
||||
if (surface->get_resolution_scaling_config() == active_config)
|
||||
{
|
||||
++It;
|
||||
continue;
|
||||
}
|
||||
|
||||
surfaces_to_clone.push_back(surface);
|
||||
|
||||
// Invalidate the previous surface
|
||||
invalidate(It->second);
|
||||
It = data.erase(It);
|
||||
}
|
||||
|
||||
for (auto& surface : surfaces_to_clone)
|
||||
{
|
||||
// Enqueue the memory transfer
|
||||
surface_storage_type sink{};
|
||||
deferred_clipped_region<surface_type> copy{};
|
||||
copy.width = surface->template get_surface_width<>();
|
||||
copy.height = surface->template get_surface_height<>();
|
||||
copy.transfer_scale_x = 1.f;
|
||||
copy.transfer_scale_y = 1.f;
|
||||
copy.target = nullptr;
|
||||
copy.source = surface;
|
||||
|
||||
Traits::clone_surface(cmd, sink, surface, surface->base_addr, copy, active_config);
|
||||
allocate_rsx_memory(Traits::get(sink));
|
||||
|
||||
// Replace with the new one
|
||||
ensure(copy.target == Traits::get(sink));
|
||||
data.emplace(surface->get_memory_range(), std::move(sink));
|
||||
}
|
||||
};
|
||||
|
||||
const auto rtt_bind_backup = m_bound_render_targets;
|
||||
const auto dsv_bind_backup = m_bound_depth_stencil;
|
||||
|
||||
// Unbind everything. We'll restore it later
|
||||
for (auto& rtt_bind : m_bound_render_targets)
|
||||
{
|
||||
rtt_bind = {};
|
||||
}
|
||||
|
||||
m_bound_depth_stencil = {};
|
||||
|
||||
process_list_function(m_render_targets_storage, m_render_targets_memory_range);
|
||||
process_list_function(m_depth_stencil_storage, m_depth_stencil_memory_range);
|
||||
|
||||
// Restore bindings.
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
const auto address = rtt_bind_backup[i].first;
|
||||
if (!address)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto rtt = m_render_targets_storage.find(address);
|
||||
ensure(rtt != m_render_targets_storage.end());
|
||||
|
||||
m_bound_render_targets[i] =
|
||||
{
|
||||
address,
|
||||
Traits::get(rtt->second)
|
||||
};
|
||||
}
|
||||
|
||||
if (const auto ds_address = dsv_bind_backup.first)
|
||||
{
|
||||
auto ds = m_depth_stencil_storage.find(ds_address);
|
||||
ensure(ds != m_depth_stencil_storage.end());
|
||||
|
||||
m_bound_depth_stencil =
|
||||
{
|
||||
ds_address,
|
||||
Traits::get(ds->second)
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -554,10 +554,14 @@ namespace rsx
|
||||
}
|
||||
|
||||
// Apply resolution scale if needed
|
||||
if (resolution_scaling_config.scale_percent != 100)
|
||||
if (resolution_scaling_config.scale_percent != 100 ||
|
||||
region.source->resolution_scaling_config.scale_percent != 100)
|
||||
{
|
||||
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>(resolution_scaling_config, slice.width, slice.height, slice.target->width(), slice.target->height());
|
||||
const auto& src_res_scale = region.source->resolution_scaling_config;
|
||||
const auto& dst_res_scale = resolution_scaling_config;
|
||||
|
||||
auto [src_width, src_height] = rsx::apply_resolution_scale<true>(src_res_scale, slice.width, slice.height, slice.source->width(), slice.source->height());
|
||||
auto [dst_width, dst_height] = rsx::apply_resolution_scale<true>(dst_res_scale, slice.width, slice.height, slice.target->width(), slice.target->height());
|
||||
|
||||
slice.transfer_scale_x *= f32(dst_width) / src_width;
|
||||
slice.transfer_scale_y *= f32(dst_height) / src_height;
|
||||
@ -565,8 +569,8 @@ namespace rsx
|
||||
slice.width = src_width;
|
||||
slice.height = src_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>(resolution_scaling_config, slice.dst_x, slice.dst_y, slice.target->width(), slice.target->height());
|
||||
std::tie(slice.src_x, slice.src_y) = rsx::apply_resolution_scale<false>(src_res_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<false>(dst_res_scale, slice.dst_x, slice.dst_y, slice.target->width(), slice.target->height());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -517,6 +517,19 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info)
|
||||
m_frame->flip(m_context);
|
||||
rsx::thread::flip(info);
|
||||
|
||||
// Data sync
|
||||
const rsx::surface_scaling_config_t active_res_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),
|
||||
};
|
||||
|
||||
if (active_res_scaling_config != this->resolution_scaling_config)
|
||||
{
|
||||
m_rtts.sync_scaling_config(cmd, active_res_scaling_config);
|
||||
this->resolution_scaling_config = active_res_scaling_config;
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
m_gl_texture_cache.on_frame_end();
|
||||
m_vertex_cache->purge();
|
||||
|
||||
@ -229,13 +229,14 @@ struct gl_render_target_traits
|
||||
void clone_surface(
|
||||
gl::command_context& cmd,
|
||||
std::unique_ptr<gl::render_target>& sink, gl::render_target* ref,
|
||||
u32 address, barrier_descriptor_t& prev)
|
||||
u32 address, barrier_descriptor_t& prev,
|
||||
const rsx::surface_scaling_config_t& scaling_config)
|
||||
{
|
||||
if (!sink)
|
||||
{
|
||||
auto internal_format = static_cast<GLenum>(ref->get_internal_format());
|
||||
const auto [new_w, new_h] = rsx::apply_resolution_scale<true>(
|
||||
ref->resolution_scaling_config,
|
||||
scaling_config,
|
||||
prev.width, prev.height,
|
||||
ref->get_surface_width<rsx::surface_metrics::pixels>(),
|
||||
ref->get_surface_height<rsx::surface_metrics::pixels>());
|
||||
@ -248,7 +249,7 @@ struct gl_render_target_traits
|
||||
sink->format_info = ref->format_info;
|
||||
|
||||
sink->sample_layout = ref->sample_layout;
|
||||
sink->resolution_scaling_config = ref->resolution_scaling_config;
|
||||
sink->resolution_scaling_config = scaling_config;
|
||||
|
||||
sink->set_name(fmt::format("SINK_%u@0x%x", sink->id(), address));
|
||||
sink->set_spp(ref->get_spp());
|
||||
@ -385,6 +386,7 @@ struct gl_render_target_traits
|
||||
gl::texture::internal_format format,
|
||||
usz width, usz height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
const rsx::surface_scaling_config_t& scaling_config,
|
||||
bool check_refs = false)
|
||||
{
|
||||
if (check_refs && surface->has_refs())
|
||||
@ -392,7 +394,8 @@ struct gl_render_target_traits
|
||||
|
||||
return surface->get_internal_format() == format &&
|
||||
surface->get_spp() == get_format_sample_count(antialias) &&
|
||||
surface->matches_dimensions(static_cast<u16>(width), static_cast<u16>(height));
|
||||
surface->matches_dimensions(static_cast<u16>(width), static_cast<u16>(height)) &&
|
||||
surface->resolution_scaling_config == scaling_config;
|
||||
}
|
||||
|
||||
static
|
||||
@ -401,10 +404,11 @@ struct gl_render_target_traits
|
||||
rsx::surface_color_format format,
|
||||
usz width, usz height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
const rsx::surface_scaling_config_t& scaling_config,
|
||||
bool check_refs=false)
|
||||
{
|
||||
const auto internal_fmt = rsx::internals::surface_color_format_to_gl(format).internal_format;
|
||||
return int_surface_matches_properties(surface, internal_fmt, width, height, antialias, check_refs);
|
||||
return int_surface_matches_properties(surface, internal_fmt, width, height, antialias, scaling_config, check_refs);
|
||||
}
|
||||
|
||||
static
|
||||
@ -413,10 +417,11 @@ struct gl_render_target_traits
|
||||
rsx::surface_depth_format2 format,
|
||||
usz width, usz height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
const rsx::surface_scaling_config_t& scaling_config,
|
||||
bool check_refs = false)
|
||||
{
|
||||
const auto internal_fmt = rsx::internals::surface_depth_format_to_gl(format).internal_format;
|
||||
return int_surface_matches_properties(surface, internal_fmt, width, height, antialias, check_refs);
|
||||
return int_surface_matches_properties(surface, internal_fmt, width, height, antialias, scaling_config, check_refs);
|
||||
}
|
||||
|
||||
static
|
||||
|
||||
@ -963,4 +963,17 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
||||
|
||||
m_frame->flip(m_context);
|
||||
rsx::thread::flip(info);
|
||||
|
||||
// Data sync
|
||||
const rsx::surface_scaling_config_t active_res_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),
|
||||
};
|
||||
|
||||
if (active_res_scaling_config != this->resolution_scaling_config)
|
||||
{
|
||||
m_rtts.sync_scaling_config(*m_current_command_buffer, active_res_scaling_config);
|
||||
this->resolution_scaling_config = active_res_scaling_config;
|
||||
}
|
||||
}
|
||||
|
||||
@ -337,12 +337,13 @@ namespace vk
|
||||
static void clone_surface(
|
||||
vk::command_buffer& cmd,
|
||||
std::unique_ptr<vk::render_target>& sink, vk::render_target* ref,
|
||||
u32 address, barrier_descriptor_t& prev)
|
||||
u32 address, barrier_descriptor_t& prev,
|
||||
const rsx::surface_scaling_config_t& scaling_config)
|
||||
{
|
||||
if (!sink)
|
||||
{
|
||||
const auto [new_w, new_h] = rsx::apply_resolution_scale<true>(
|
||||
ref->resolution_scaling_config,
|
||||
scaling_config,
|
||||
prev.width, prev.height,
|
||||
ref->get_surface_width<rsx::surface_metrics::pixels>(), ref->get_surface_height<rsx::surface_metrics::pixels>());
|
||||
|
||||
@ -363,7 +364,7 @@ namespace vk
|
||||
sink->add_ref();
|
||||
|
||||
sink->sample_layout = ref->sample_layout;
|
||||
sink->resolution_scaling_config = ref->resolution_scaling_config;
|
||||
sink->resolution_scaling_config = scaling_config;
|
||||
|
||||
sink->set_spp(ref->get_spp());
|
||||
sink->format_info = ref->format_info;
|
||||
@ -521,6 +522,7 @@ namespace vk
|
||||
VkFormat format,
|
||||
usz width, usz height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
const rsx::surface_scaling_config_t& scaling_config,
|
||||
bool check_refs)
|
||||
{
|
||||
if (check_refs && surface->has_refs())
|
||||
@ -531,7 +533,8 @@ namespace vk
|
||||
|
||||
return (surface->info.format == format &&
|
||||
surface->get_spp() == get_format_sample_count(antialias) &&
|
||||
surface->matches_dimensions(static_cast<u16>(width), static_cast<u16>(height)));
|
||||
surface->matches_dimensions(static_cast<u16>(width), static_cast<u16>(height))) &&
|
||||
surface->resolution_scaling_config == scaling_config;
|
||||
}
|
||||
|
||||
static bool surface_matches_properties(
|
||||
@ -539,10 +542,11 @@ namespace vk
|
||||
rsx::surface_color_format format,
|
||||
usz width, usz height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
const rsx::surface_scaling_config_t& scaling_config,
|
||||
bool check_refs = false)
|
||||
{
|
||||
VkFormat vk_format = vk::get_compatible_surface_format(format).first;
|
||||
return int_surface_matches_properties(surface, vk_format, width, height, antialias, check_refs);
|
||||
return int_surface_matches_properties(surface, vk_format, width, height, antialias, scaling_config, check_refs);
|
||||
}
|
||||
|
||||
static bool surface_matches_properties(
|
||||
@ -550,11 +554,12 @@ namespace vk
|
||||
rsx::surface_depth_format2 format,
|
||||
usz width, usz height,
|
||||
rsx::surface_antialiasing antialias,
|
||||
const rsx::surface_scaling_config_t& scaling_config,
|
||||
bool check_refs = false)
|
||||
{
|
||||
auto device = vk::get_current_renderer();
|
||||
VkFormat vk_format = vk::get_compatible_depth_surface_format(device->get_formats_support(), format);
|
||||
return int_surface_matches_properties(surface, vk_format, width, height, antialias, check_refs);
|
||||
return int_surface_matches_properties(surface, vk_format, width, height, antialias, scaling_config, check_refs);
|
||||
}
|
||||
|
||||
static void spill_buffer(std::unique_ptr<vk::buffer>& /*bo*/)
|
||||
|
||||
@ -220,6 +220,12 @@ namespace rsx
|
||||
u16 min_scalable_dimension = 0;
|
||||
|
||||
f32 scale_factor() const { return scale_percent * 0.01f; }
|
||||
|
||||
bool operator == (const surface_scaling_config_t& that) const
|
||||
{
|
||||
return this->scale_percent == that.scale_percent &&
|
||||
this->min_scalable_dimension == that.min_scalable_dimension;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user