From 400f6abf9a441332551b123c7ac8aa3b6ce88494 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 6 Dec 2022 19:16:19 -0800 Subject: [PATCH] softgpu: Optimize lookup of last jit func. This is common (for example, maybe a pixel state is updated but sampler is not), and reduces time spent in ComputeRasterizerState() quite a bit in Darkstalkers, where jits are available (i.e. Intel currently.) --- GPU/Software/DrawPixel.cpp | 10 +++++++-- GPU/Software/DrawPixel.h | 7 +++++++ GPU/Software/Sampler.cpp | 43 ++++++++++++++++++++++++++++++-------- GPU/Software/Sampler.h | 11 +++++++++- 4 files changed, 59 insertions(+), 12 deletions(-) diff --git a/GPU/Software/DrawPixel.cpp b/GPU/Software/DrawPixel.cpp index 341ba80f7b..60a96b8450 100644 --- a/GPU/Software/DrawPixel.cpp +++ b/GPU/Software/DrawPixel.cpp @@ -791,11 +791,15 @@ SingleFunc PixelJitCache::GetSingle(const PixelFuncID &id, BinManager *binner) { if (!g_Config.bSoftwareRenderingJit) return nullptr; - std::unique_lock guard(jitCacheLock); const size_t key = std::hash()(id); + auto last = lastSingle_.load(); + if (last.key == key) + return last.func; + std::unique_lock guard(jitCacheLock); auto it = cache_.Get(key); if (it != nullptr) { + lastSingle_ = { key, it }; return it; } @@ -821,7 +825,9 @@ SingleFunc PixelJitCache::GetSingle(const PixelFuncID &id, BinManager *binner) { if (!cache_.Get(key)) Compile(id); - return cache_.Get(key); + it = cache_.Get(key); + lastSingle_ = { key, it }; + return it; } void PixelJitCache::Compile(const PixelFuncID &id) { diff --git a/GPU/Software/DrawPixel.h b/GPU/Software/DrawPixel.h index 1e100c81be..bafde030aa 100644 --- a/GPU/Software/DrawPixel.h +++ b/GPU/Software/DrawPixel.h @@ -19,6 +19,7 @@ #include "ppsspp_config.h" +#include #include #include #include @@ -109,9 +110,15 @@ private: bool Jit_ConvertFrom5551(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg temp1Reg, RegCache::Reg temp2Reg, bool keepAlpha); bool Jit_ConvertFrom4444(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg temp1Reg, RegCache::Reg temp2Reg, bool keepAlpha); + struct LastEntry { + size_t key; + SingleFunc func; + }; + DenseHashMap cache_; std::unordered_map addresses_; std::unordered_set compileQueue_; + std::atomic lastSingle_; const u8 *constBlendHalf_11_4s_ = nullptr; const u8 *constBlendInvert_11_4s_ = nullptr; diff --git a/GPU/Software/Sampler.cpp b/GPU/Software/Sampler.cpp index 97a47933cc..f2a80fddc6 100644 --- a/GPU/Software/Sampler.cpp +++ b/GPU/Software/Sampler.cpp @@ -154,13 +154,8 @@ void SamplerJitCache::Flush() { compileQueue_.clear(); } -NearestFunc SamplerJitCache::GetByID(const SamplerID &id, BinManager *binner) { - if (!g_Config.bSoftwareRenderingJit) - return nullptr; - +NearestFunc SamplerJitCache::GetByID(const SamplerID &id, size_t key, BinManager *binner) { std::unique_lock guard(jitCacheLock); - const size_t key = std::hash()(id); - auto it = cache_.Get(key); if (it != nullptr) return it; @@ -191,15 +186,45 @@ NearestFunc SamplerJitCache::GetByID(const SamplerID &id, BinManager *binner) { } NearestFunc SamplerJitCache::GetNearest(const SamplerID &id, BinManager *binner) { - return (NearestFunc)GetByID(id, binner); + if (!g_Config.bSoftwareRenderingJit) + return nullptr; + + const size_t key = std::hash()(id); + auto last = lastNearest_.load(); + if (last.key == key) + return (NearestFunc)last.func; + + auto func = GetByID(id, key, binner); + lastNearest_ = { key, func }; + return (NearestFunc)func; } LinearFunc SamplerJitCache::GetLinear(const SamplerID &id, BinManager *binner) { - return (LinearFunc)GetByID(id, binner); + if (!g_Config.bSoftwareRenderingJit) + return nullptr; + + const size_t key = std::hash()(id); + auto last = lastLinear_.load(); + if (last.key == key) + return (LinearFunc)last.func; + + auto func = GetByID(id, key, binner); + lastLinear_ = { key, func }; + return (LinearFunc)func; } FetchFunc SamplerJitCache::GetFetch(const SamplerID &id, BinManager *binner) { - return (FetchFunc)GetByID(id, binner); + if (!g_Config.bSoftwareRenderingJit) + return nullptr; + + const size_t key = std::hash()(id); + auto last = lastFetch_.load(); + if (last.key == key) + return (FetchFunc)last.func; + + auto func = GetByID(id, key, binner); + lastFetch_ = { key, func }; + return (FetchFunc)func; } void SamplerJitCache::Compile(const SamplerID &id) { diff --git a/GPU/Software/Sampler.h b/GPU/Software/Sampler.h index 0f8f413453..96e9d4c4a8 100644 --- a/GPU/Software/Sampler.h +++ b/GPU/Software/Sampler.h @@ -19,6 +19,7 @@ #include "ppsspp_config.h" +#include #include #include #include "Common/Data/Collections/Hashmaps.h" @@ -67,7 +68,7 @@ public: private: void Compile(const SamplerID &id); - NearestFunc GetByID(const SamplerID &id, BinManager *binner); + NearestFunc GetByID(const SamplerID &id, size_t key, BinManager *binner); FetchFunc CompileFetch(const SamplerID &id); NearestFunc CompileNearest(const SamplerID &id); LinearFunc CompileLinear(const SamplerID &id); @@ -128,9 +129,17 @@ private: const u8 *const5551Swizzle_ = nullptr; const u8 *const5650Swizzle_ = nullptr; + struct LastEntry { + size_t key; + NearestFunc func; + }; + DenseHashMap cache_; std::unordered_map addresses_; std::unordered_set compileQueue_; + std::atomic lastFetch_; + std::atomic lastNearest_; + std::atomic lastLinear_; }; #if defined(__clang__) || defined(__GNUC__)