mirror of
https://github.com/RPCS3/rpcs3.git
synced 2026-06-04 05:45:03 -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));
|
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));
|
allocate_rsx_memory(Traits::get(sink));
|
||||||
|
|
||||||
if (invalidated) [[unlikely]]
|
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)
|
if (!pitch_compatible)
|
||||||
{
|
{
|
||||||
@ -496,7 +496,7 @@ namespace rsx
|
|||||||
for (auto It = invalidated_resources.begin(); It != invalidated_resources.end(); It++)
|
for (auto It = invalidated_resources.begin(); It != invalidated_resources.end(); It++)
|
||||||
{
|
{
|
||||||
auto &surface = *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);
|
new_surface_storage = std::move(surface);
|
||||||
Traits::notify_surface_reused(new_surface_storage);
|
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
|
// 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());
|
const auto& src_res_scale = region.source->resolution_scaling_config;
|
||||||
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& 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_x *= f32(dst_width) / src_width;
|
||||||
slice.transfer_scale_y *= f32(dst_height) / src_height;
|
slice.transfer_scale_y *= f32(dst_height) / src_height;
|
||||||
@ -565,8 +569,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>(resolution_scaling_config, 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>(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>(resolution_scaling_config, 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>(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);
|
m_frame->flip(m_context);
|
||||||
rsx::thread::flip(info);
|
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
|
// Cleanup
|
||||||
m_gl_texture_cache.on_frame_end();
|
m_gl_texture_cache.on_frame_end();
|
||||||
m_vertex_cache->purge();
|
m_vertex_cache->purge();
|
||||||
|
|||||||
@ -229,13 +229,14 @@ struct gl_render_target_traits
|
|||||||
void clone_surface(
|
void clone_surface(
|
||||||
gl::command_context& cmd,
|
gl::command_context& cmd,
|
||||||
std::unique_ptr<gl::render_target>& sink, gl::render_target* ref,
|
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)
|
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>(
|
const auto [new_w, new_h] = rsx::apply_resolution_scale<true>(
|
||||||
ref->resolution_scaling_config,
|
scaling_config,
|
||||||
prev.width, prev.height,
|
prev.width, prev.height,
|
||||||
ref->get_surface_width<rsx::surface_metrics::pixels>(),
|
ref->get_surface_width<rsx::surface_metrics::pixels>(),
|
||||||
ref->get_surface_height<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->format_info = ref->format_info;
|
||||||
|
|
||||||
sink->sample_layout = ref->sample_layout;
|
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_name(fmt::format("SINK_%u@0x%x", sink->id(), address));
|
||||||
sink->set_spp(ref->get_spp());
|
sink->set_spp(ref->get_spp());
|
||||||
@ -385,6 +386,7 @@ struct gl_render_target_traits
|
|||||||
gl::texture::internal_format format,
|
gl::texture::internal_format format,
|
||||||
usz width, usz height,
|
usz width, usz height,
|
||||||
rsx::surface_antialiasing antialias,
|
rsx::surface_antialiasing antialias,
|
||||||
|
const rsx::surface_scaling_config_t& scaling_config,
|
||||||
bool check_refs = false)
|
bool check_refs = false)
|
||||||
{
|
{
|
||||||
if (check_refs && surface->has_refs())
|
if (check_refs && surface->has_refs())
|
||||||
@ -392,7 +394,8 @@ struct gl_render_target_traits
|
|||||||
|
|
||||||
return surface->get_internal_format() == format &&
|
return surface->get_internal_format() == format &&
|
||||||
surface->get_spp() == get_format_sample_count(antialias) &&
|
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
|
static
|
||||||
@ -401,10 +404,11 @@ struct gl_render_target_traits
|
|||||||
rsx::surface_color_format format,
|
rsx::surface_color_format format,
|
||||||
usz width, usz height,
|
usz width, usz height,
|
||||||
rsx::surface_antialiasing antialias,
|
rsx::surface_antialiasing antialias,
|
||||||
|
const rsx::surface_scaling_config_t& scaling_config,
|
||||||
bool check_refs=false)
|
bool check_refs=false)
|
||||||
{
|
{
|
||||||
const auto internal_fmt = rsx::internals::surface_color_format_to_gl(format).internal_format;
|
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
|
static
|
||||||
@ -413,10 +417,11 @@ struct gl_render_target_traits
|
|||||||
rsx::surface_depth_format2 format,
|
rsx::surface_depth_format2 format,
|
||||||
usz width, usz height,
|
usz width, usz height,
|
||||||
rsx::surface_antialiasing antialias,
|
rsx::surface_antialiasing antialias,
|
||||||
|
const rsx::surface_scaling_config_t& scaling_config,
|
||||||
bool check_refs = false)
|
bool check_refs = false)
|
||||||
{
|
{
|
||||||
const auto internal_fmt = rsx::internals::surface_depth_format_to_gl(format).internal_format;
|
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
|
static
|
||||||
|
|||||||
@ -963,4 +963,17 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info)
|
|||||||
|
|
||||||
m_frame->flip(m_context);
|
m_frame->flip(m_context);
|
||||||
rsx::thread::flip(info);
|
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(
|
static void clone_surface(
|
||||||
vk::command_buffer& cmd,
|
vk::command_buffer& cmd,
|
||||||
std::unique_ptr<vk::render_target>& sink, vk::render_target* ref,
|
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)
|
if (!sink)
|
||||||
{
|
{
|
||||||
const auto [new_w, new_h] = rsx::apply_resolution_scale<true>(
|
const auto [new_w, new_h] = rsx::apply_resolution_scale<true>(
|
||||||
ref->resolution_scaling_config,
|
scaling_config,
|
||||||
prev.width, prev.height,
|
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>());
|
||||||
|
|
||||||
@ -363,7 +364,7 @@ namespace vk
|
|||||||
sink->add_ref();
|
sink->add_ref();
|
||||||
|
|
||||||
sink->sample_layout = ref->sample_layout;
|
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->set_spp(ref->get_spp());
|
||||||
sink->format_info = ref->format_info;
|
sink->format_info = ref->format_info;
|
||||||
@ -521,6 +522,7 @@ namespace vk
|
|||||||
VkFormat format,
|
VkFormat format,
|
||||||
usz width, usz height,
|
usz width, usz height,
|
||||||
rsx::surface_antialiasing antialias,
|
rsx::surface_antialiasing antialias,
|
||||||
|
const rsx::surface_scaling_config_t& scaling_config,
|
||||||
bool check_refs)
|
bool check_refs)
|
||||||
{
|
{
|
||||||
if (check_refs && surface->has_refs())
|
if (check_refs && surface->has_refs())
|
||||||
@ -531,7 +533,8 @@ namespace vk
|
|||||||
|
|
||||||
return (surface->info.format == format &&
|
return (surface->info.format == format &&
|
||||||
surface->get_spp() == get_format_sample_count(antialias) &&
|
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(
|
static bool surface_matches_properties(
|
||||||
@ -539,10 +542,11 @@ namespace vk
|
|||||||
rsx::surface_color_format format,
|
rsx::surface_color_format format,
|
||||||
usz width, usz height,
|
usz width, usz height,
|
||||||
rsx::surface_antialiasing antialias,
|
rsx::surface_antialiasing antialias,
|
||||||
|
const rsx::surface_scaling_config_t& scaling_config,
|
||||||
bool check_refs = false)
|
bool check_refs = false)
|
||||||
{
|
{
|
||||||
VkFormat vk_format = vk::get_compatible_surface_format(format).first;
|
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(
|
static bool surface_matches_properties(
|
||||||
@ -550,11 +554,12 @@ namespace vk
|
|||||||
rsx::surface_depth_format2 format,
|
rsx::surface_depth_format2 format,
|
||||||
usz width, usz height,
|
usz width, usz height,
|
||||||
rsx::surface_antialiasing antialias,
|
rsx::surface_antialiasing antialias,
|
||||||
|
const rsx::surface_scaling_config_t& scaling_config,
|
||||||
bool check_refs = false)
|
bool check_refs = false)
|
||||||
{
|
{
|
||||||
auto device = vk::get_current_renderer();
|
auto device = vk::get_current_renderer();
|
||||||
VkFormat vk_format = vk::get_compatible_depth_surface_format(device->get_formats_support(), format);
|
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*/)
|
static void spill_buffer(std::unique_ptr<vk::buffer>& /*bo*/)
|
||||||
|
|||||||
@ -220,6 +220,12 @@ namespace rsx
|
|||||||
u16 min_scalable_dimension = 0;
|
u16 min_scalable_dimension = 0;
|
||||||
|
|
||||||
f32 scale_factor() const { return scale_percent * 0.01f; }
|
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>
|
template <typename T>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user