Skip to content

Commit

Permalink
GS/HW: Prioritize loading required replacement textures over precache
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Apr 3, 2024
1 parent 8e00828 commit 2693bbf
Showing 1 changed file with 49 additions and 12 deletions.
61 changes: 49 additions & 12 deletions pcsx2/GS/Renderers/HW/GSTextureReplacements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@
#include <cinttypes>
#include <condition_variable>
#include <cstring>
#include <deque>
#include <functional>
#include <mutex>
#include <unordered_map>
#include <unordered_set>
#include <queue>
#include <tuple>
#include <thread>

Expand Down Expand Up @@ -115,7 +115,7 @@ namespace GSTextureReplacements

static void StartWorkerThread();
static void StopWorkerThread();
static void QueueWorkerThreadItem(std::function<void()> fn);
static void QueueWorkerThreadItem(std::function<void()> fn, bool high_priority);
static void WorkerThreadEntryPoint();
static void SyncWorkerThread();
static void CancelPendingLoadsAndDumps();
Expand Down Expand Up @@ -146,7 +146,7 @@ namespace GSTextureReplacements
static std::thread s_worker_thread;
static std::mutex s_worker_thread_mutex;
static std::condition_variable s_worker_thread_cv;
static std::queue<std::function<void()>> s_worker_thread_queue;
static std::deque<std::pair<std::function<void()>, bool>> s_worker_thread_queue;
static bool s_worker_thread_running = false;
}; // namespace GSTextureReplacements

Expand Down Expand Up @@ -611,8 +611,16 @@ void GSTextureReplacements::QueueAsyncReplacementTextureLoad(const TextureName&
auto it = s_pending_async_load_textures.find(name);
if (it != s_pending_async_load_textures.end())
{
it->second &= cache_only;
return;
// remove from queue if it's cache-only, so we bump it to the front of the work items
if (!cache_only && it->second)
{
s_pending_async_load_textures.erase(it);
}
else
{
it->second &= cache_only;
return;
}
}

s_pending_async_load_textures.emplace(name, cache_only);
Expand Down Expand Up @@ -644,7 +652,7 @@ void GSTextureReplacements::QueueAsyncReplacementTextureLoad(const TextureName&
// loading failed, so clear it from the pending list
s_pending_async_load_textures.erase(name);
}
});
}, !cache_only);
}

void GSTextureReplacements::PrecacheReplacementTextures()
Expand Down Expand Up @@ -789,7 +797,7 @@ void GSTextureReplacements::DumpTexture(const GSTextureCache::HashCacheKey& hash
if (!SavePNGImage(filename.c_str(), tw, th, buffer + buffer_offset, pitch))
Console.Error(fmt::format("Failed to dump texture to '{}'.", filename));
_aligned_free(buffer);
});
}, false);
}

void GSTextureReplacements::ClearDumpedTextureList()
Expand Down Expand Up @@ -829,12 +837,41 @@ void GSTextureReplacements::StopWorkerThread()
CancelPendingLoadsAndDumps();
}

void GSTextureReplacements::QueueWorkerThreadItem(std::function<void()> fn)
void GSTextureReplacements::QueueWorkerThreadItem(std::function<void()> fn, bool high_priority)
{
pxAssert(s_worker_thread.joinable());

std::unique_lock<std::mutex> lock(s_worker_thread_mutex);
s_worker_thread_queue.push(std::move(fn));
if (!high_priority)
{
// Low priority => throw on end.
s_worker_thread_queue.emplace_back(std::move(fn), false);
}
else
{
auto iter = s_worker_thread_queue.rbegin();
for (; iter != s_worker_thread_queue.rend(); ++iter)
{
// Found our first high priority item?
if (iter->second)
{
// Insert after here!
break;
}
}

if (iter != s_worker_thread_queue.rend())
{
// Insert after the last high priority item. Remember base() points to the next element.
s_worker_thread_queue.insert(iter.base(), std::make_pair(std::move(fn), true));
}
else
{
// All low-priority => insert at beginning.
s_worker_thread_queue.emplace_front(std::move(fn), true);
}
}

s_worker_thread_cv.notify_one();
}

Expand All @@ -849,8 +886,8 @@ void GSTextureReplacements::WorkerThreadEntryPoint()
continue;
}

std::function<void()> fn = std::move(s_worker_thread_queue.front());
s_worker_thread_queue.pop();
std::function<void()> fn = std::move(s_worker_thread_queue.front().first);
s_worker_thread_queue.pop_front();
lock.unlock();
fn();
lock.lock();
Expand Down Expand Up @@ -879,7 +916,7 @@ void GSTextureReplacements::CancelPendingLoadsAndDumps()
{
std::unique_lock<std::mutex> lock(s_worker_thread_mutex);
while (!s_worker_thread_queue.empty())
s_worker_thread_queue.pop();
s_worker_thread_queue.pop_back();
s_async_loaded_textures.clear();
s_pending_async_load_textures.clear();
}

0 comments on commit 2693bbf

Please sign in to comment.