big picture mode: Create tiles multithreaded

This commit is contained in:
Megamouse
2026-09-01 23:20:37 +02:00
parent 83a522a8e1
commit 4048b7aaef
6 changed files with 101 additions and 70 deletions
+78
View File
@@ -4033,3 +4033,81 @@ bool thread_ctrl::is_main()
{ {
return get_tid() == utils::main_tid; return get_tid() == utils::main_tid;
} }
usz map_workload(std::string_view thread_name, usz thread_count, usz count, std::function<void(usz)>&& func)
{
ensure(!!func);
if (thread_count <= 1)
{
for (usz i = 0; i < count; i++)
{
func(i);
}
return 1;
}
atomic_t<u32> num_threads_succeeded {0}; // Check if any thread didn't finish. For example when hitting an exception.
atomic_t<usz> indexer = 0;
const auto iterate = [count, &func, &indexer]()
{
while (thread_ctrl::state() != thread_state::aborting)
{
// Make sure indexer does not exceed count
const usz index = indexer.fetch_op([count](usz& v)
{
if (v < count)
{
v++;
return true;
}
return false;
}).first;
if (index >= count)
{
break;
}
func(index);
}
};
named_thread_group workers(thread_name, ::narrow<u32>(thread_count) - 1, [&iterate, &num_threads_succeeded]()
{
iterate();
num_threads_succeeded++;
});
iterate();
workers.join();
return num_threads_succeeded + 1;
}
usz map_workload(std::string_view thread_name, usz thread_count, std::function<void()>&& func)
{
ensure(!!func);
if (thread_count <= 1)
{
func();
return 1;
}
atomic_t<u32> num_threads_succeeded {0}; // Check if any thread didn't finish. For example when hitting an exception.
named_thread_group workers(thread_name, ::narrow<u32>(thread_count) - 1, [&func, &num_threads_succeeded]()
{
func();
num_threads_succeeded++;
});
func();
workers.join();
return num_threads_succeeded + 1;
}
+3
View File
@@ -905,3 +905,6 @@ public:
::operator delete(static_cast<void*>(m_threads), std::align_val_t{alignof(Thread)}); ::operator delete(static_cast<void*>(m_threads), std::align_val_t{alignof(Thread)});
} }
}; };
usz map_workload(std::string_view thread_name, usz thread_count, usz count, std::function<void(usz)>&& func);
usz map_workload(std::string_view thread_name, usz thread_count, std::function<void()>&& func);
+2 -18
View File
@@ -1364,26 +1364,10 @@ package_install_result package_reader::extract_data(std::deque<package_reader>&
{ {
// Disc archives don't like multithreaded file reads, so let's just use a single thread here // Disc archives don't like multithreaded file reads, so let's just use a single thread here
const usz thread_count = from_optical_drive ? 1 : std::min<usz>(utils::get_thread_count(), reader.m_install_entries.size()); const usz thread_count = from_optical_drive ? 1 : std::min<usz>(utils::get_thread_count(), reader.m_install_entries.size());
atomic_t<u32> num_threads_succeeded {0}; // Check if any thread didn't finish. For example when hitting an exception. const usz num_threads_succeeded = map_workload("PKG Installer "sv, thread_count, [&reader]()
if (thread_count > 1)
{
named_thread_group workers("PKG Installer "sv, ::narrow<u32>(thread_count) - 1, [&]()
{
reader.extract_worker();
num_threads_succeeded++;
});
reader.extract_worker();
num_threads_succeeded++;
workers.join();
}
else
{ {
reader.extract_worker(); reader.extract_worker();
num_threads_succeeded++; });
}
if (thread_count != num_threads_succeeded) if (thread_count != num_threads_succeeded)
{ {
@@ -120,50 +120,11 @@ namespace rsx
// Parse entries (multithreaded) // Parse entries (multithreaded)
const std::vector<game_enumeration<big_picture_game_entry>::path_entry>& entries = m_game_enumeration.path_entries(); const std::vector<game_enumeration<big_picture_game_entry>::path_entry>& entries = m_game_enumeration.path_entries();
const usz thread_count = std::min<usz>(utils::get_thread_count(), entries.size()); usz thread_count = std::min<usz>(utils::get_thread_count(), entries.size());
if (thread_count > 1) map_workload("BPM Parser "sv, thread_count, entries.size(), [this, &entries](usz index)
{ {
atomic_t<usz> entry_indexer = 0; m_game_enumeration.parse_entry(entries[index]);
const auto parse_entries = [this, &entry_indexer, &entries]() });
{
while (thread_ctrl::state() != thread_state::aborting)
{
// Make sure entry_indexer does not exceed m_install_entries
const usz index = entry_indexer.fetch_op([&entries](usz& v)
{
if (v < entries.size())
{
v++;
return true;
}
return false;
}).first;
if (index >= entries.size())
{
break;
}
m_game_enumeration.parse_entry(entries[index]);
}
};
named_thread_group workers("BPM Parser "sv, ::narrow<u32>(thread_count) - 1, [&parse_entries]()
{
parse_entries();
});
parse_entries();
workers.join();
}
else
{
for (const game_enumeration<big_picture_game_entry>::path_entry& entry : entries)
{
m_game_enumeration.parse_entry(entry);
}
}
// Try to update the app version for disc games if there is a patch // Try to update the app version for disc games if there is a patch
// Also try to find updated game icons and movies // Also try to find updated game icons and movies
@@ -186,11 +147,19 @@ namespace rsx
return a.name < b.name; return a.name < b.name;
}); });
finish_reload(); // Create tiles (multithreaded)
std::vector<std::unique_ptr<big_picture_game_tile>> tiles(m_games.size());
thread_count = std::min<usz>(utils::get_thread_count(), tiles.size());
map_workload("BPM Tiles "sv, thread_count, tiles.size(), [this, &tiles](usz index)
{
tiles[index] = std::make_unique<big_picture_game_tile>(m_games[index], m_tile_size);
});
finish_reload(std::move(tiles));
}); });
} }
void big_picture_game_grid::finish_reload() void big_picture_game_grid::finish_reload(std::vector<std::unique_ptr<big_picture_game_tile>>&& tiles)
{ {
std::lock_guard lock(m_reload_mutex); std::lock_guard lock(m_reload_mutex);
@@ -206,7 +175,7 @@ namespace rsx
std::unique_ptr<horizontal_layout> row; std::unique_ptr<horizontal_layout> row;
for (usz i = 0; i < m_games.size(); i++) for (usz i = 0; i < tiles.size(); i++)
{ {
if (i % m_columns == 0) if (i % m_columns == 0)
{ {
@@ -219,8 +188,7 @@ namespace rsx
row->pack_padding = 20; row->pack_padding = 20;
} }
auto tile = std::make_unique<big_picture_game_tile>(m_games[i], m_tile_size); m_tiles.push_back(row->add_element(tiles[i]));
m_tiles.push_back(row->add_element(tile));
} }
if (row) if (row)
@@ -47,7 +47,7 @@ namespace rsx
private: private:
void start_reload(); void start_reload();
void finish_reload(); void finish_reload(std::vector<std::unique_ptr<big_picture_game_tile>>&& tiles);
void select_tile(s32 index); void select_tile(s32 index);
static constexpr u16 m_columns = 5; static constexpr u16 m_columns = 5;
+1 -3
View File
@@ -185,7 +185,7 @@ u64 memory_viewer_panel::OnSearch(std::string wstr, u32 mode)
vm::writer_lock rlock; vm::writer_lock rlock;
const named_thread_group workers("Memory Searcher "sv, max_threads, [&]() map_workload("Memory Searcher "sv, max_threads, [&]()
{ {
if (mode == as_inst || mode == as_fake_spu_inst || mode == as_regex_inst || mode == as_regex_fake_spu_inst) if (mode == as_inst || mode == as_fake_spu_inst || mode == as_regex_inst || mode == as_regex_fake_spu_inst)
{ {
@@ -448,7 +448,5 @@ u64 memory_viewer_panel::OnSearch(std::string wstr, u32 mode)
found += local_found; found += local_found;
}); });
workers.join();
return found; return found;
} }