diff --git a/src/shader_recompiler/environment.h b/src/shader_recompiler/environment.h index 0a6e4bfcaa..20381cf467 100644 --- a/src/shader_recompiler/environment.h +++ b/src/shader_recompiler/environment.h @@ -38,10 +38,11 @@ struct CbufWordKeyHash { struct HandleKey { u32 index, offset, shift_left; u32 sec_index, sec_offset, sec_shift_left; + u32 count; bool has_secondary; constexpr bool operator==(const HandleKey& o) const noexcept { - return std::tie(index, offset, shift_left, sec_index, sec_offset, sec_shift_left, has_secondary) - == std::tie(o.index, o.offset, o.shift_left, o.sec_index, o.sec_offset, o.sec_shift_left, o.has_secondary); + return std::tie(index, offset, shift_left, sec_index, sec_offset, sec_shift_left, count, has_secondary) + == std::tie(o.index, o.offset, o.shift_left, o.sec_index, o.sec_offset, o.sec_shift_left, o.count, o.has_secondary); } }; struct HandleKeyHash { @@ -50,8 +51,8 @@ struct HandleKeyHash { h ^= (size_t(k.shift_left) << 1); h ^= (size_t(k.sec_index) << 33) ^ (size_t(k.sec_offset) << 2); h ^= (size_t(k.sec_shift_left) << 3); - h ^= k.has_secondary ? 0x9e3779b97f4a7c15ULL : 0ULL; - return h; + h ^= (size_t(k.count) << 7); + return h ^ (k.has_secondary ? 0x9e3779b97f4a7c15ULL : 0ULL); } }; diff --git a/src/shader_recompiler/ir_opt/texture_pass.cpp b/src/shader_recompiler/ir_opt/texture_pass.cpp index c500b53ff7..d72fbf38c8 100644 --- a/src/shader_recompiler/ir_opt/texture_pass.cpp +++ b/src/shader_recompiler/ir_opt/texture_pass.cpp @@ -270,21 +270,25 @@ bool IsTextureInstruction(const IR::Inst& inst) { static inline u32 ReadCbufCached(Environment& env, u32 index, u32 offset) { const CbufWordKey k{index, offset}; - if (auto it = env.cbuf_word_cache.find(k); it != env.cbuf_word_cache.end()) return it->second; + if (auto it = env.cbuf_word_cache.find(k); it != env.cbuf_word_cache.end()) + return it->second; const u32 v = env.ReadCbufValue(index, offset); env.cbuf_word_cache.emplace(k, v); return v; } static inline u32 GetTextureHandleCached(Environment& env, const ConstBufferAddr& cbuf) { - const u32 sec_idx = cbuf.has_secondary ? cbuf.secondary_index : cbuf.index; - const u32 sec_off = cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset; - const HandleKey hk{cbuf.index, cbuf.offset, cbuf.shift_left, - sec_idx, sec_off, cbuf.secondary_shift_left, cbuf.has_secondary}; - if (auto it = env.handle_cache.find(hk); it != env.handle_cache.end()) return it->second; - + // Must all be uniquely different variables + // If has secondary, then it will be cbuf.secondary_{index|offset}, else its 0. + // So we can just hand it out the raw variable without using sec_idx or sec_off + // because comparing 0 against 0 will yield true. + const HandleKey hk{cbuf.index, cbuf.offset, cbuf.shift_left, cbuf.secondary_index, cbuf.secondary_offset, cbuf.secondary_shift_left, cbuf.count, cbuf.has_secondary}; + if (auto it = env.handle_cache.find(hk); it != env.handle_cache.end()) + return it->second; + const u32 sec_idx = cbuf.has_secondary ? cbuf.secondary_index : cbuf.index; + const u32 sec_off = cbuf.has_secondary ? cbuf.secondary_offset : cbuf.offset; const u32 lhs = ReadCbufCached(env, cbuf.index, cbuf.offset) << cbuf.shift_left; - const u32 rhs = ReadCbufCached(env, sec_idx, sec_off) << cbuf.secondary_shift_left; + const u32 rhs = ReadCbufCached(env, sec_idx, sec_off) << cbuf.secondary_shift_left; const u32 handle = lhs | rhs; env.handle_cache.emplace(hk, handle); return handle;