Skip to content

Commit f95da6e

Browse files
authored
Merge branch 'master' into tessssst
2 parents 9fdc922 + c6e9672 commit f95da6e

16 files changed

Lines changed: 316 additions & 45 deletions

rpcs3/Crypto/unpkg.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -952,11 +952,11 @@ bool package_reader::fill_data(std::map<std::string, install_entry*>& all_instal
952952
default:
953953
{
954954
// TODO: check for valid utf8 characters
955-
const std::string true_path = std::filesystem::weakly_canonical(path).string();
955+
const std::string true_path = std::filesystem::path(path).lexically_normal().string();
956956
if (true_path.empty())
957957
{
958958
num_failures++;
959-
pkg_log.error("Failed to get weakly_canonical path for '%s'", path);
959+
pkg_log.error("Failed to normalize package path for '%s'", path);
960960
break;
961961
}
962962

rpcs3/Emu/RSX/Common/texture_cache.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1784,7 +1784,7 @@ namespace rsx
17841784
};
17851785

17861786
surface_scaling_config_t scaling_config{};
1787-
if (g_cfg.video.allow_blit_engine_upscaling)
1787+
if (!g_cfg.video.disable_blit_engine_upscaling)
17881788
{
17891789
scaling_config =
17901790
{
@@ -3740,6 +3740,13 @@ namespace rsx
37403740
}
37413741
}
37423742

3743+
// MM flush before commit below. For performance reasons, only flush when writing to CELL memory.
3744+
if (rsx::classify_location(dst.rsx_address) == CELL_GCM_LOCATION_MAIN)
3745+
{
3746+
const auto mm_flush_range = utils::address_range64::start_length(reinterpret_cast<u64>(dst.pixels), dst_payload_length);
3747+
rsx::mm_flush({ mm_flush_range });
3748+
}
3749+
37433750
// Commit any pending writes before we do the transfer. Writes will be done on super_ptr so locking beforehand is ok.
37443751
m_rtts.prepare_transfer_target(cmd, dst_subres.surface, rsx::surface_access::transfer_write, std::forward<Args>(extras)...);
37453752
}

rpcs3/Emu/RSX/Common/texture_cache_helpers.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,14 @@ namespace rsx
232232

233233
if (src_is_render_target)
234234
{
235-
// Attempt to optimize...
236-
if (dst_dimensions.width == 1280 || dst_dimensions.width == 2560) [[likely]]
235+
// Attempt to optimize for performance...
236+
if (get_location(dst_range.start) == CELL_GCM_LOCATION_MAIN)
237+
{
238+
// Don't guess when working with main memory
239+
const auto min_fitted_height = utils::aligned_div(dst_range.length(), dst_pitch);
240+
dst_dimensions.height = std::min(dst_dimensions.height, min_fitted_height);
241+
}
242+
else if (dst_dimensions.width == 1280 || dst_dimensions.width == 2560)
237243
{
238244
// Optimizations table based on common width/height pairings. If we guess wrong, the upload resolver will fix it anyway
239245
// TODO: Add more entries based on empirical data

rpcs3/Emu/RSX/Host/MM.cpp

Lines changed: 121 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,113 @@ namespace rsx
1414
rsx::simple_array<MM_block> g_deferred_mprotect_queue;
1515
shared_mutex g_mprotect_queue_lock;
1616

17-
void mm_flush_mprotect_queue_internal()
17+
void mm_sanitize_queue_internal()
1818
{
19-
for (const auto& block : g_deferred_mprotect_queue)
19+
u32 w = 0, r = 0;
20+
for (; r < g_deferred_mprotect_queue.size(); ++r)
2021
{
22+
auto& block = g_deferred_mprotect_queue[r];
23+
if (!block.range.valid())
24+
{
25+
continue;
26+
}
27+
g_deferred_mprotect_queue[w++] = block;
28+
}
29+
g_deferred_mprotect_queue.resize(w);
30+
}
31+
32+
void mm_flush_mprotect_queue_internal(u32 count)
33+
{
34+
AUDIT(count <= g_deferred_mprotect_queue.size());
35+
36+
for (u32 i = 0; i < count; ++i)
37+
{
38+
auto& block = g_deferred_mprotect_queue[i];
39+
ensure(block.range.valid());
40+
2141
utils::memory_protect(reinterpret_cast<void*>(block.range.start), block.range.length(), block.prot);
42+
block.range.invalidate();
43+
}
44+
45+
const u32 remaining = g_deferred_mprotect_queue.size() - count;
46+
if (!remaining)
47+
{
48+
g_deferred_mprotect_queue.clear();
49+
return;
50+
}
51+
52+
// Pop processed entries from the queue
53+
mm_sanitize_queue_internal();
54+
}
55+
56+
// Reverse scan to find the latest overlapping MM conflict. The result is a count of prefix blocks.
57+
template <typename F>
58+
u32 mm_find_conflict_internal(F&& predicate)
59+
{
60+
for (u32 i = g_deferred_mprotect_queue.size(); i > 0; --i)
61+
{
62+
if (std::invoke(predicate, g_deferred_mprotect_queue[i - 1]))
63+
{
64+
return i;
65+
}
2266
}
2367

24-
g_deferred_mprotect_queue.clear();
68+
return 0;
2569
}
2670

2771
void mm_defer_mprotect_internal(u64 start, u64 length, utils::protection prot)
2872
{
29-
// We could stack and merge requests here, but that is more trouble than it is truly worth.
30-
// A fresh call to memory_protect only takes a few nanoseconds of setup overhead, it is not worth the risk of hanging because of conflicts.
31-
g_deferred_mprotect_queue.push_back({ utils::address_range64::start_length(start, length), prot });
73+
const auto range = utils::address_range64::start_length(start, length);
74+
bool has_invalid = false;
75+
bool is_merged = false;
76+
77+
// Attempt a merge first. The queue length is short but the time taken to run mprotect is very high in comparison.
78+
for (auto it = g_deferred_mprotect_queue.rbegin();
79+
it != g_deferred_mprotect_queue.rend();
80+
++it)
81+
{
82+
auto& block = *it;
83+
if (!block.touches(range))
84+
{
85+
continue;
86+
}
87+
88+
if (block.prot != prot)
89+
{
90+
// Optimization. If our new range swallows the old one, replace it.
91+
if (block.range.inside(range))
92+
{
93+
block.range.invalidate();
94+
has_invalid = true;
95+
continue;
96+
}
97+
98+
if (!block.overlaps(range))
99+
{
100+
// Adjacent. Skip.
101+
continue;
102+
}
103+
104+
// Preserve ordering. Do not proceed with merge.
105+
break;
106+
}
107+
108+
block.merge(range);
109+
is_merged = true;
110+
break;
111+
}
112+
113+
if (has_invalid)
114+
{
115+
mm_sanitize_queue_internal();
116+
}
117+
118+
if (is_merged)
119+
{
120+
return;
121+
}
122+
123+
g_deferred_mprotect_queue.push_back({ range, prot });
32124
}
33125

34126
void mm_protect(void* ptr, u64 length, utils::protection prot)
@@ -47,13 +139,24 @@ namespace rsx
47139

48140
if (prot == utils::protection::rw || prot == utils::protection::wx)
49141
{
50-
// Basically an unlock op. Flush if any overlap is detected
51-
for (const auto& block : g_deferred_mprotect_queue)
142+
// Basically an unlock op. Flush the conflicting prefix block if any overlap is detected.
143+
if (u32 count = mm_find_conflict_internal(FN(x.overlaps(range))))
52144
{
53-
if (block.overlaps(range))
145+
// Check for degenerate ranges that we'll be crushing
146+
for (auto pblock = &g_deferred_mprotect_queue[count - 1];
147+
count > 0 && pblock->range.inside(range);
148+
count--, pblock--)
54149
{
55-
mm_flush_mprotect_queue_internal();
56-
break;
150+
pblock->range.invalidate();
151+
}
152+
153+
if (count)
154+
{
155+
mm_flush_mprotect_queue_internal(count);
156+
}
157+
else
158+
{
159+
mm_sanitize_queue_internal();
57160
}
58161
}
59162

@@ -68,7 +171,7 @@ namespace rsx
68171
void mm_flush()
69172
{
70173
std::lock_guard lock(g_mprotect_queue_lock);
71-
mm_flush_mprotect_queue_internal();
174+
mm_flush_mprotect_queue_internal(g_deferred_mprotect_queue.size());
72175
}
73176

74177
void mm_flush(u32 vm_address)
@@ -80,31 +183,24 @@ namespace rsx
80183
}
81184

82185
const auto addr = reinterpret_cast<u64>(vm::base(vm_address));
83-
for (const auto& block : g_deferred_mprotect_queue)
186+
if (const u32 count = mm_find_conflict_internal(FN(x.overlaps(addr))))
84187
{
85-
if (block.overlaps(addr))
86-
{
87-
mm_flush_mprotect_queue_internal();
88-
return;
89-
}
188+
mm_flush_mprotect_queue_internal(count);
90189
}
91190
}
92191

93192
void mm_flush(const rsx::simple_array<utils::address_range64>& ranges)
94193
{
95194
std::lock_guard lock(g_mprotect_queue_lock);
96-
if (g_deferred_mprotect_queue.empty())
195+
if (g_deferred_mprotect_queue.empty() || ranges.empty())
97196
{
98197
return;
99198
}
100199

101-
for (const auto& block : g_deferred_mprotect_queue)
200+
const auto block_overlaps_ranges = [&](const MM_block& block) { return ranges.any(FN(block.overlaps(x))); };
201+
if (const u32 count = mm_find_conflict_internal(block_overlaps_ranges))
102202
{
103-
if (ranges.any(FN(block.overlaps(x))))
104-
{
105-
mm_flush_mprotect_queue_internal();
106-
return;
107-
}
203+
mm_flush_mprotect_queue_internal(count);
108204
}
109205
}
110206

rpcs3/Emu/RSX/Host/MM.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ namespace rsx
1313
utils::address_range64 range;
1414
utils::protection prot;
1515

16+
inline void merge(const utils::address_range64& other)
17+
{
18+
AUDIT(other.valid());
19+
range = utils::address_range64::start_end(
20+
std::min(range.start, other.start),
21+
std::max(range.end, other.end)
22+
);
23+
}
24+
1625
inline bool overlaps(const utils::address_range64& test) const
1726
{
1827
return range.overlaps(test);
@@ -22,6 +31,11 @@ namespace rsx
2231
{
2332
return range.overlaps(addr);
2433
}
34+
35+
inline bool touches(const utils::address_range64& test) const
36+
{
37+
return range.touches(test);
38+
}
2539
};
2640

2741
enum mm_backend_ctrl : u32

rpcs3/Emu/RSX/Overlays/BigPicture/overlay_big_picture_game_grid.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,9 +380,9 @@ namespace rsx
380380
break;
381381
case pad_button::dpad_down:
382382
case pad_button::ls_down:
383-
if ((m_selected_index + m_columns) < static_cast<s32>(m_tiles.size()))
383+
if (!m_tiles.empty())
384384
{
385-
select_tile(m_selected_index + m_columns);
385+
select_tile(std::min(m_selected_index + m_columns, static_cast<s32>(m_tiles.size()) - 1));
386386
}
387387
break;
388388
case pad_button::cross:

rpcs3/Emu/RSX/Program/FragmentProgramDecompiler.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -792,8 +792,10 @@ template<typename T> std::string FragmentProgramDecompiler::GetSRC(T src)
792792
}
793793

794794
// Warning: Modifier order matters. e.g neg should be applied after precision clamping (tested with Naruto UNS)
795+
const bool precision_before_abs = precision_modifier == RSX_FP_PRECISION_SATURATE;
796+
if (precision_before_abs) ret = ClampValue(ret, precision_modifier);
795797
if (src.abs) ret = "abs(" + ret + ")";
796-
if (precision_modifier) ret = ClampValue(ret, precision_modifier);
798+
if (precision_modifier && !precision_before_abs) ret = ClampValue(ret, precision_modifier);
797799
if (src.neg) ret = "-" + ret;
798800

799801
return ret;

rpcs3/Emu/RSX/Program/GLSLInterpreter/FragmentInterpreter.glsl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ layout(location=0) in vec4 in_regs[16];
8383
#define RSX_FP_REGISTER_TYPE_CONSTANT 2
8484
#define RSX_FP_REGISTER_TYPE_UNKNOWN 3
8585

86+
#define RSX_FP_PRECISION_SATURATE 4
87+
8688
#define CELL_GCM_SHADER_CONTROL_DEPTH_EXPORT 0xe
8789
#define CELL_GCM_SHADER_CONTROL_32_BITS_EXPORTS 0x40
8890

@@ -242,6 +244,11 @@ vec4 read_src(const in int index)
242244
ur1 = GET_INST_BITS(index + 1, 9, 8);
243245
vr0 = shuffle(vr0, ur1);
244246

247+
if (GET_INST_BITS(2, 19 + index * 3, 3) == RSX_FP_PRECISION_SATURATE)
248+
{
249+
vr0 = clamp(select(vr0, vr_zero, isnan(vr0)), 0., 1.);
250+
}
251+
245252
// abs
246253
if (index == 0)
247254
{

rpcs3/Emu/system_config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ struct cfg_root : cfg::node
180180
cfg::_bool record_with_overlays{ this, "Record With Overlays", true, true };
181181
cfg::_bool disable_hardware_texel_remapping{ this, "Disable Hardware ColorSpace Remapping", false, true };
182182
cfg::uint<0, 100> rcas_sharpening_intensity{ this, "FidelityFX CAS Sharpening Intensity", 50, true };
183-
cfg::_bool allow_blit_engine_upscaling{ this, "Allow Blit Engine Upscaling", false, true };
183+
cfg::_bool disable_blit_engine_upscaling{ this, "Disable Blit Engine Upscaling", false, true };
184184

185185
struct node_vk : cfg::node
186186
{

rpcs3/rpcs3qt/emu_settings_type.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ const std::map<emu_settings_type, cfg_location> settings_location =
113113
{ emu_settings_type::RecordWithOverlays, get_cfg_location(local_cfg.video.record_with_overlays) },
114114
{ emu_settings_type::DisableHWTexelRemapping, get_cfg_location(local_cfg.video.disable_hardware_texel_remapping) },
115115
{ emu_settings_type::FsrSharpeningStrength, get_cfg_location(local_cfg.video.rcas_sharpening_intensity) },
116-
{ emu_settings_type::EnableBlitEngineScaling, get_cfg_location(local_cfg.video.allow_blit_engine_upscaling) },
116+
{ emu_settings_type::DisableBlitEngineScaling, get_cfg_location(local_cfg.video.disable_blit_engine_upscaling) },
117117

118118
// Vulkan
119119
{ emu_settings_type::VulkanAdapter, get_cfg_location(local_cfg.video.vk.adapter) },

0 commit comments

Comments
 (0)