From 3d5bced296a7bb3217e4050eedffe7e24f28607e Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 27 Nov 2021 16:36:14 -0800 Subject: [PATCH] softjit: Rename reg cache so it can be reused. Intentionally just the name changes in this commit. --- CMakeLists.txt | 2 + GPU/GPU.vcxproj | 2 + GPU/GPU.vcxproj.filters | 6 + GPU/Software/DrawPixel.cpp | 192 ---------- GPU/Software/DrawPixel.h | 125 ++----- GPU/Software/DrawPixelX86.cpp | 524 ++++++++++++++-------------- GPU/Software/RasterizerRegCache.cpp | 214 ++++++++++++ GPU/Software/RasterizerRegCache.h | 122 +++++++ UWP/GPU_UWP/GPU_UWP.vcxproj | 2 + UWP/GPU_UWP/GPU_UWP.vcxproj.filters | 2 + android/jni/Android.mk | 1 + libretro/Makefile.common | 1 + 12 files changed, 635 insertions(+), 558 deletions(-) create mode 100644 GPU/Software/RasterizerRegCache.cpp create mode 100644 GPU/Software/RasterizerRegCache.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b3b33d1f22..86ddf08cb1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1595,6 +1595,8 @@ set(GPU_SOURCES GPU/Software/Rasterizer.h GPU/Software/RasterizerRectangle.cpp GPU/Software/RasterizerRectangle.h + GPU/Software/RasterizerRegCache.cpp + GPU/Software/RasterizerRegCache.h GPU/Software/Sampler.cpp GPU/Software/Sampler.h GPU/Software/SoftGpu.cpp diff --git a/GPU/GPU.vcxproj b/GPU/GPU.vcxproj index 9ef8aa4f24..9bb00dde1b 100644 --- a/GPU/GPU.vcxproj +++ b/GPU/GPU.vcxproj @@ -458,6 +458,7 @@ + @@ -636,6 +637,7 @@ + diff --git a/GPU/GPU.vcxproj.filters b/GPU/GPU.vcxproj.filters index 0f3248dc0b..d747ccec4a 100644 --- a/GPU/GPU.vcxproj.filters +++ b/GPU/GPU.vcxproj.filters @@ -270,6 +270,9 @@ Software + + Software + @@ -545,5 +548,8 @@ Software + + Software + \ No newline at end of file diff --git a/GPU/Software/DrawPixel.cpp b/GPU/Software/DrawPixel.cpp index 651c8e8762..4cd9fc9c4a 100644 --- a/GPU/Software/DrawPixel.cpp +++ b/GPU/Software/DrawPixel.cpp @@ -635,196 +635,4 @@ void ComputePixelBlendState(PixelBlendState &state, const PixelFuncID &id) { } } -void PixelRegCache::Reset(bool validate) { - if (validate) { - for (auto ® : regs) { - _assert_msg_(reg.locked == 0, "softjit: Reset() with reg still locked (%04X)", reg.purpose); - _assert_msg_(!reg.forceRetained, "softjit: Reset() with reg force retained (%04X)", reg.purpose); - } - } - regs.clear(); -} - -void PixelRegCache::Add(Reg r, Purpose p) { - for (auto ® : regs) { - if (reg.reg == r && (reg.purpose & FLAG_GEN) == (p & FLAG_GEN)) { - _assert_msg_(false, "softjit Add() reg duplicate (%04X)", p); - } - } - _assert_msg_(r != REG_INVALID_VALUE, "softjit Add() invalid reg (%04X)", p); - - RegStatus newStatus; - newStatus.reg = r; - newStatus.purpose = p; - regs.push_back(newStatus); -} - -void PixelRegCache::Change(Purpose history, Purpose destiny) { - for (auto ® : regs) { - if (reg.purpose == history) { - reg.purpose = destiny; - return; - } - } - - _assert_msg_(false, "softjit Change() reg that isn't there (%04X)", history); -} - -void PixelRegCache::Release(Reg &r, Purpose p) { - RegStatus *status = FindReg(r, p); - _assert_msg_(status != nullptr, "softjit Release() reg that isn't there (%04X)", p); - _assert_msg_(status->locked > 0, "softjit Release() reg that isn't locked (%04X)", p); - _assert_msg_(!status->forceRetained, "softjit Release() reg that is force retained (%04X)", p); - - status->locked--; - if (status->locked == 0) { - if ((status->purpose & FLAG_GEN) != 0) - status->purpose = GEN_INVALID; - else - status->purpose = VEC_INVALID; - } - - r = REG_INVALID_VALUE; -} - -void PixelRegCache::Unlock(Reg &r, Purpose p) { - RegStatus *status = FindReg(r, p); - if (status) { - _assert_msg_(status->locked > 0, "softjit Unlock() reg that isn't locked (%04X)", p); - status->locked--; - r = REG_INVALID_VALUE; - return; - } - - _assert_msg_(false, "softjit Unlock() reg that isn't there (%04X)", p); -} - -bool PixelRegCache::Has(Purpose p) { - for (auto ® : regs) { - if (reg.purpose == p) { - return true; - } - } - return false; -} - -PixelRegCache::Reg PixelRegCache::Find(Purpose p) { - for (auto ® : regs) { - if (reg.purpose == p) { - _assert_msg_(reg.locked <= 255, "softjit Find() reg has lots of locks (%04X)", p); - reg.locked++; - return reg.reg; - } - } - _assert_msg_(false, "softjit Find() reg that isn't there (%04X)", p); - return REG_INVALID_VALUE; -} - -PixelRegCache::Reg PixelRegCache::Alloc(Purpose p) { - _assert_msg_(!Has(p), "softjit Alloc() reg duplicate (%04X)", p); - RegStatus *best = nullptr; - for (auto ® : regs) { - if (reg.locked != 0 || reg.forceRetained) - continue; - // Needs to be the same type. - if ((reg.purpose & FLAG_GEN) != (p & FLAG_GEN)) - continue; - - if (best == nullptr) - best = ® - // Prefer a free/purposeless reg (includes INVALID.) - if ((reg.purpose & FLAG_TEMP) != 0) { - best = ® - break; - } - // But also prefer a lower priority reg. - if (reg.purpose < best->purpose) - best = ® - } - - if (best) { - best->locked = 1; - best->purpose = p; - return best->reg; - } - - _assert_msg_(false, "softjit Alloc() reg with none free (%04X)", p); - return REG_INVALID_VALUE; -} - -void PixelRegCache::ForceRetain(Purpose p) { - for (auto ® : regs) { - if (reg.purpose == p) { - reg.forceRetained = true; - return; - } - } - - _assert_msg_(false, "softjit ForceRetain() reg that isn't there (%04X)", p); -} - -void PixelRegCache::ForceRelease(Purpose p) { - for (auto ® : regs) { - if (reg.purpose == p) { - _assert_msg_(reg.locked == 0, "softjit ForceRelease() while locked (%04X)", p); - reg.forceRetained = false; - if ((reg.purpose & FLAG_GEN) != 0) - reg.purpose = GEN_INVALID; - else - reg.purpose = VEC_INVALID; - return; - } - } - - _assert_msg_(false, "softjit ForceRelease() reg that isn't there (%04X)", p); -} - -void PixelRegCache::GrabReg(Reg r, Purpose p, bool &needsSwap, Reg swapReg, Purpose swapPurpose) { - for (auto ® : regs) { - if (reg.reg != r) - continue; - if ((reg.purpose & FLAG_GEN) != (p & FLAG_GEN)) - continue; - - // Easy version, it's free. - if (reg.locked == 0 && !reg.forceRetained) { - needsSwap = false; - reg.purpose = p; - reg.locked = 1; - return; - } - - // Okay, we need to swap. Find that reg. - needsSwap = true; - RegStatus *swap = FindReg(swapReg, swapPurpose); - if (swap) { - swap->purpose = reg.purpose; - swap->forceRetained = reg.forceRetained; - swap->locked = reg.locked; - } else { - _assert_msg_(!Has(swapPurpose), "softjit GrabReg() wrong purpose (%04X)", swapPurpose); - RegStatus newStatus = reg; - newStatus.reg = swapReg; - regs.push_back(newStatus); - } - - reg.purpose = p; - reg.locked = 1; - reg.forceRetained = false; - return; - } - - _assert_msg_(false, "softjit GrabReg() reg that isn't there"); -} - -PixelRegCache::RegStatus *PixelRegCache::FindReg(Reg r, Purpose p) { - for (auto ® : regs) { - if (reg.reg == r && reg.purpose == p) { - return ® - } - } - - return nullptr; -} - }; diff --git a/GPU/Software/DrawPixel.h b/GPU/Software/DrawPixel.h index dc6721eac2..2e0b3cd9d4 100644 --- a/GPU/Software/DrawPixel.h +++ b/GPU/Software/DrawPixel.h @@ -35,6 +35,7 @@ #endif #include "GPU/Math3D.h" #include "GPU/Software/FuncId.h" +#include "GPU/Software/RasterizerRegCache.h" namespace Rasterizer { @@ -60,90 +61,6 @@ void Shutdown(); bool DescribeCodePtr(const u8 *ptr, std::string &name); -struct PixelRegCache { - enum Purpose { - FLAG_GEN = 0x0100, - FLAG_TEMP = 0x1000, - - VEC_ZERO = 0x0000, - - GEN_SRC_ALPHA = 0x0100, - GEN_GSTATE = 0x0101, - GEN_CONST_BASE = 0x0102, - GEN_STENCIL = 0x0103, - GEN_COLOR_OFF = 0x0104, - GEN_DEPTH_OFF = 0x0105, - - GEN_ARG_X = 0x0180, - GEN_ARG_Y = 0x0181, - GEN_ARG_Z = 0x0182, - GEN_ARG_FOG = 0x0183, - VEC_ARG_COLOR = 0x0080, - VEC_ARG_MASK = 0x0081, - - VEC_TEMP0 = 0x1000, - VEC_TEMP1 = 0x1001, - VEC_TEMP2 = 0x1002, - VEC_TEMP3 = 0x1003, - VEC_TEMP4 = 0x1004, - VEC_TEMP5 = 0x1005, - - GEN_TEMP0 = 0x1100, - GEN_TEMP1 = 0x1101, - GEN_TEMP2 = 0x1102, - GEN_TEMP3 = 0x1103, - GEN_TEMP4 = 0x1104, - GEN_TEMP5 = 0x1105, - GEN_TEMP_HELPER = 0x1106, - - VEC_INVALID = 0xFEFF, - GEN_INVALID = 0xFFFF, - }; - -#if PPSSPP_ARCH(ARM) - typedef ArmGen::ARMReg Reg; - static constexpr Reg REG_INVALID_VALUE = ArmGen::INVALID_REG; -#elif PPSSPP_ARCH(ARM64) - typedef Arm64Gen::ARM64Reg Reg; - static constexpr Reg REG_INVALID_VALUE = Arm64Gen::INVALID_REG; -#elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) - typedef Gen::X64Reg Reg; - static constexpr Reg REG_INVALID_VALUE = Gen::INVALID_REG; -#elif PPSSPP_ARCH(MIPS) - typedef MIPSGen::MIPSReg Reg; - static constexpr Reg REG_INVALID_VALUE = MIPSGen::INVALID_REG; -#else - typedef int Reg; - static constexpr Reg REG_INVALID_VALUE = -1; -#endif - - struct RegStatus { - Reg reg; - Purpose purpose; - uint8_t locked = 0; - bool forceRetained = false; - }; - - void Reset(bool validate); - void Add(Reg r, Purpose p); - void Change(Purpose history, Purpose destiny); - void Release(Reg &r, Purpose p); - void Unlock(Reg &r, Purpose p); - bool Has(Purpose p); - Reg Find(Purpose p); - Reg Alloc(Purpose p); - void ForceRetain(Purpose p); - void ForceRelease(Purpose p); - - // For getting a specific reg. WARNING: May return a locked reg, so you have to check. - void GrabReg(Reg r, Purpose p, bool &needsSwap, Reg swapReg, Purpose swapPurpose); - -private: - RegStatus *FindReg(Reg r, Purpose p); - - std::vector regs; -}; - struct PixelBlendState { bool usesFactors = false; bool usesDstAlpha = false; @@ -179,41 +96,41 @@ private: Arm64Gen::ARM64FloatEmitter fp; #endif - PixelRegCache::Reg GetGState(); - PixelRegCache::Reg GetConstBase(); - PixelRegCache::Reg GetZeroVec(); + RegCache::Reg GetGState(); + RegCache::Reg GetConstBase(); + RegCache::Reg GetZeroVec(); // Note: these may require a temporary reg. - PixelRegCache::Reg GetColorOff(const PixelFuncID &id); - PixelRegCache::Reg GetDepthOff(const PixelFuncID &id); - PixelRegCache::Reg GetDestStencil(const PixelFuncID &id); + RegCache::Reg GetColorOff(const PixelFuncID &id); + RegCache::Reg GetDepthOff(const PixelFuncID &id); + RegCache::Reg GetDestStencil(const PixelFuncID &id); bool Jit_ApplyDepthRange(const PixelFuncID &id); bool Jit_AlphaTest(const PixelFuncID &id); bool Jit_ApplyFog(const PixelFuncID &id); bool Jit_ColorTest(const PixelFuncID &id); bool Jit_StencilAndDepthTest(const PixelFuncID &id); - bool Jit_StencilTest(const PixelFuncID &id, PixelRegCache::Reg stencilReg, PixelRegCache::Reg maskedReg); - bool Jit_DepthTestForStencil(const PixelFuncID &id, PixelRegCache::Reg stencilReg); - bool Jit_ApplyStencilOp(const PixelFuncID &id, GEStencilOp op, PixelRegCache::Reg stencilReg); - bool Jit_WriteStencilOnly(const PixelFuncID &id, PixelRegCache::Reg stencilReg); + bool Jit_StencilTest(const PixelFuncID &id, RegCache::Reg stencilReg, RegCache::Reg maskedReg); + bool Jit_DepthTestForStencil(const PixelFuncID &id, RegCache::Reg stencilReg); + bool Jit_ApplyStencilOp(const PixelFuncID &id, GEStencilOp op, RegCache::Reg stencilReg); + bool Jit_WriteStencilOnly(const PixelFuncID &id, RegCache::Reg stencilReg); bool Jit_DepthTest(const PixelFuncID &id); bool Jit_WriteDepth(const PixelFuncID &id); bool Jit_AlphaBlend(const PixelFuncID &id); - bool Jit_BlendFactor(const PixelFuncID &id, PixelRegCache::Reg factorReg, PixelRegCache::Reg dstReg, GEBlendSrcFactor factor); - bool Jit_DstBlendFactor(const PixelFuncID &id, PixelRegCache::Reg srcFactorReg, PixelRegCache::Reg dstFactorReg, PixelRegCache::Reg dstReg); + bool Jit_BlendFactor(const PixelFuncID &id, RegCache::Reg factorReg, RegCache::Reg dstReg, GEBlendSrcFactor factor); + bool Jit_DstBlendFactor(const PixelFuncID &id, RegCache::Reg srcFactorReg, RegCache::Reg dstFactorReg, RegCache::Reg dstReg); bool Jit_Dither(const PixelFuncID &id); bool Jit_WriteColor(const PixelFuncID &id); - bool Jit_ApplyLogicOp(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg maskReg); - bool Jit_ConvertTo565(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg temp1Reg, PixelRegCache::Reg temp2Reg); - bool Jit_ConvertTo5551(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg temp1Reg, PixelRegCache::Reg temp2Reg, bool keepAlpha); - bool Jit_ConvertTo4444(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg temp1Reg, PixelRegCache::Reg temp2Reg, bool keepAlpha); - bool Jit_ConvertFrom565(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg temp1Reg, PixelRegCache::Reg temp2Reg); - bool Jit_ConvertFrom5551(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg temp1Reg, PixelRegCache::Reg temp2Reg, bool keepAlpha); - bool Jit_ConvertFrom4444(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg temp1Reg, PixelRegCache::Reg temp2Reg, bool keepAlpha); + bool Jit_ApplyLogicOp(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg maskReg); + bool Jit_ConvertTo565(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg temp1Reg, RegCache::Reg temp2Reg); + bool Jit_ConvertTo5551(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg temp1Reg, RegCache::Reg temp2Reg, bool keepAlpha); + bool Jit_ConvertTo4444(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg temp1Reg, RegCache::Reg temp2Reg, bool keepAlpha); + bool Jit_ConvertFrom565(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg temp1Reg, RegCache::Reg temp2Reg); + 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); std::unordered_map cache_; std::unordered_map addresses_; - PixelRegCache regCache_; + RegCache regCache_; #if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) void Discard(); diff --git a/GPU/Software/DrawPixelX86.cpp b/GPU/Software/DrawPixelX86.cpp index 3a076f7c32..a2cd2b9793 100644 --- a/GPU/Software/DrawPixelX86.cpp +++ b/GPU/Software/DrawPixelX86.cpp @@ -65,50 +65,50 @@ static OpArg MConstDisp(X64Reg r, const T *t) { SingleFunc PixelJitCache::CompileSingle(const PixelFuncID &id) { // Setup the reg cache. - regCache_.Add(RAX, PixelRegCache::GEN_INVALID); - regCache_.Add(R10, PixelRegCache::GEN_INVALID); - regCache_.Add(R11, PixelRegCache::GEN_INVALID); - regCache_.Add(XMM1, PixelRegCache::VEC_INVALID); - regCache_.Add(XMM2, PixelRegCache::VEC_INVALID); - regCache_.Add(XMM3, PixelRegCache::VEC_INVALID); - regCache_.Add(XMM5, PixelRegCache::VEC_INVALID); + regCache_.Add(RAX, RegCache::GEN_INVALID); + regCache_.Add(R10, RegCache::GEN_INVALID); + regCache_.Add(R11, RegCache::GEN_INVALID); + regCache_.Add(XMM1, RegCache::VEC_INVALID); + regCache_.Add(XMM2, RegCache::VEC_INVALID); + regCache_.Add(XMM3, RegCache::VEC_INVALID); + regCache_.Add(XMM5, RegCache::VEC_INVALID); #if PPSSPP_PLATFORM(WINDOWS) // Must save: RBX, RSP, RBP, RDI, RSI, R12-R15, XMM6-15 - regCache_.Add(XMM0, PixelRegCache::VEC_INVALID); + regCache_.Add(XMM0, RegCache::VEC_INVALID); - regCache_.Add(RCX, PixelRegCache::GEN_ARG_X); - regCache_.Add(RDX, PixelRegCache::GEN_ARG_Y); - regCache_.Add(R8, PixelRegCache::GEN_ARG_Z); - regCache_.Add(R9, PixelRegCache::GEN_ARG_FOG); - regCache_.Add(XMM4, PixelRegCache::VEC_ARG_COLOR); + regCache_.Add(RCX, RegCache::GEN_ARG_X); + regCache_.Add(RDX, RegCache::GEN_ARG_Y); + regCache_.Add(R8, RegCache::GEN_ARG_Z); + regCache_.Add(R9, RegCache::GEN_ARG_FOG); + regCache_.Add(XMM4, RegCache::VEC_ARG_COLOR); // Windows reserves space to save args, 1 xmm + 4 ints before the id. stackIDOffset_ = 1 * 16 + 4 * PTRBITS / 8; #else // Must save: RBX, RSP, RBP, R12-R15 - regCache_.Add(R8, PixelRegCache::GEN_INVALID); - regCache_.Add(R9, PixelRegCache::GEN_INVALID); - regCache_.Add(XMM4, PixelRegCache::VEC_INVALID); + regCache_.Add(R8, RegCache::GEN_INVALID); + regCache_.Add(R9, RegCache::GEN_INVALID); + regCache_.Add(XMM4, RegCache::VEC_INVALID); - regCache_.Add(RDI, PixelRegCache::GEN_ARG_X); - regCache_.Add(RSI, PixelRegCache::GEN_ARG_Y); - regCache_.Add(RDX, PixelRegCache::GEN_ARG_Z); - regCache_.Add(RCX, PixelRegCache::GEN_ARG_FOG); - regCache_.Add(XMM0, PixelRegCache::VEC_ARG_COLOR); + regCache_.Add(RDI, RegCache::GEN_ARG_X); + regCache_.Add(RSI, RegCache::GEN_ARG_Y); + regCache_.Add(RDX, RegCache::GEN_ARG_Z); + regCache_.Add(RCX, RegCache::GEN_ARG_FOG); + regCache_.Add(XMM0, RegCache::VEC_ARG_COLOR); // Here we just have the return and padding to align RPB. stackIDOffset_ = 16; #endif // Initially, disallow spill for args (they get unlocked when no longer needed.) - regCache_.ForceRetain(PixelRegCache::GEN_ARG_X); - regCache_.ForceRetain(PixelRegCache::GEN_ARG_Y); - regCache_.ForceRetain(PixelRegCache::GEN_ARG_Z); - regCache_.ForceRetain(PixelRegCache::GEN_ARG_FOG); - regCache_.ForceRetain(PixelRegCache::VEC_ARG_COLOR); + regCache_.ForceRetain(RegCache::GEN_ARG_X); + regCache_.ForceRetain(RegCache::GEN_ARG_Y); + regCache_.ForceRetain(RegCache::GEN_ARG_Z); + regCache_.ForceRetain(RegCache::GEN_ARG_FOG); + regCache_.ForceRetain(RegCache::VEC_ARG_COLOR); BeginWrite(); const u8 *start = AlignCode16(); @@ -119,10 +119,10 @@ SingleFunc PixelJitCache::CompileSingle(const PixelFuncID &id) { // Next, let's clamp the color (might affect alpha test, and everything expects it clamped.) // We simply convert to 4x8-bit to clamp. Everything else expects color in this format. - X64Reg argColorReg = regCache_.Find(PixelRegCache::VEC_ARG_COLOR); + X64Reg argColorReg = regCache_.Find(RegCache::VEC_ARG_COLOR); PACKSSDW(argColorReg, R(argColorReg)); PACKUSWB(argColorReg, R(argColorReg)); - regCache_.Unlock(argColorReg, PixelRegCache::VEC_ARG_COLOR); + regCache_.Unlock(argColorReg, RegCache::VEC_ARG_COLOR); colorIs16Bit_ = false; success = success && Jit_AlphaTest(id); @@ -161,40 +161,40 @@ SingleFunc PixelJitCache::CompileSingle(const PixelFuncID &id) { return (SingleFunc)start; } -PixelRegCache::Reg PixelJitCache::GetGState() { - if (!regCache_.Has(PixelRegCache::GEN_GSTATE)) { - X64Reg r = regCache_.Alloc(PixelRegCache::GEN_GSTATE); +RegCache::Reg PixelJitCache::GetGState() { + if (!regCache_.Has(RegCache::GEN_GSTATE)) { + X64Reg r = regCache_.Alloc(RegCache::GEN_GSTATE); MOV(PTRBITS, R(r), ImmPtr(&gstate.nop)); return r; } - return regCache_.Find(PixelRegCache::GEN_GSTATE); + return regCache_.Find(RegCache::GEN_GSTATE); } -PixelRegCache::Reg PixelJitCache::GetConstBase() { - if (!regCache_.Has(PixelRegCache::GEN_CONST_BASE)) { - X64Reg r = regCache_.Alloc(PixelRegCache::GEN_CONST_BASE); +RegCache::Reg PixelJitCache::GetConstBase() { + if (!regCache_.Has(RegCache::GEN_CONST_BASE)) { + X64Reg r = regCache_.Alloc(RegCache::GEN_CONST_BASE); MOV(PTRBITS, R(r), ImmPtr(&const255_16s[0])); return r; } - return regCache_.Find(PixelRegCache::GEN_CONST_BASE); + return regCache_.Find(RegCache::GEN_CONST_BASE); } -PixelRegCache::Reg PixelJitCache::GetZeroVec() { - if (!regCache_.Has(PixelRegCache::VEC_ZERO)) { - X64Reg r = regCache_.Alloc(PixelRegCache::VEC_ZERO); +RegCache::Reg PixelJitCache::GetZeroVec() { + if (!regCache_.Has(RegCache::VEC_ZERO)) { + X64Reg r = regCache_.Alloc(RegCache::VEC_ZERO); PXOR(r, R(r)); return r; } - return regCache_.Find(PixelRegCache::VEC_ZERO); + return regCache_.Find(RegCache::VEC_ZERO); } -PixelRegCache::Reg PixelJitCache::GetColorOff(const PixelFuncID &id) { - if (!regCache_.Has(PixelRegCache::GEN_COLOR_OFF)) { +RegCache::Reg PixelJitCache::GetColorOff(const PixelFuncID &id) { + if (!regCache_.Has(RegCache::GEN_COLOR_OFF)) { if (id.useStandardStride && !id.dithering) { bool loadDepthOff = id.depthWrite || id.DepthTestFunc() != GE_COMP_ALWAYS; X64Reg depthTemp = INVALID_REG; - X64Reg argYReg = regCache_.Find(PixelRegCache::GEN_ARG_Y); - X64Reg argXReg = regCache_.Find(PixelRegCache::GEN_ARG_X); + X64Reg argYReg = regCache_.Find(RegCache::GEN_ARG_Y); + X64Reg argXReg = regCache_.Find(RegCache::GEN_ARG_X); // In this mode, we force argXReg to the off, and throw away argYReg. SHL(32, R(argYReg), Imm8(9)); @@ -203,7 +203,7 @@ PixelRegCache::Reg PixelJitCache::GetColorOff(const PixelFuncID &id) { // Now add the pointer for the color buffer. if (loadDepthOff) { _assert_(Accessible(&fb.data, &depthbuf.data)); - depthTemp = regCache_.Alloc(PixelRegCache::GEN_DEPTH_OFF); + depthTemp = regCache_.Alloc(RegCache::GEN_DEPTH_OFF); MOV(PTRBITS, R(depthTemp), ImmPtr(&fb.data)); MOV(PTRBITS, R(argYReg), MatR(depthTemp)); } else { @@ -212,111 +212,111 @@ PixelRegCache::Reg PixelJitCache::GetColorOff(const PixelFuncID &id) { } LEA(PTRBITS, argYReg, MComplex(argYReg, argXReg, id.FBFormat() == GE_FORMAT_8888 ? 4 : 2, 0)); // With that, argYOff is now GEN_COLOR_OFF. - regCache_.Unlock(argYReg, PixelRegCache::GEN_ARG_Y); - regCache_.Change(PixelRegCache::GEN_ARG_Y, PixelRegCache::GEN_COLOR_OFF); + regCache_.Unlock(argYReg, RegCache::GEN_ARG_Y); + regCache_.Change(RegCache::GEN_ARG_Y, RegCache::GEN_COLOR_OFF); // Retain it, because we can't recalculate this. - regCache_.ForceRetain(PixelRegCache::GEN_COLOR_OFF); + regCache_.ForceRetain(RegCache::GEN_COLOR_OFF); // Next, also calculate the depth offset, unless we won't need it at all. if (loadDepthOff) { MOV(PTRBITS, R(depthTemp), MAccessibleDisp(depthTemp, &fb.data, &depthbuf.data)); LEA(PTRBITS, argXReg, MComplex(depthTemp, argXReg, 2, 0)); - regCache_.Release(depthTemp, PixelRegCache::GEN_DEPTH_OFF); + regCache_.Release(depthTemp, RegCache::GEN_DEPTH_OFF); // Okay, same deal - release as GEN_DEPTH_OFF and force retain it. - regCache_.Unlock(argXReg, PixelRegCache::GEN_ARG_X); - regCache_.Change(PixelRegCache::GEN_ARG_X, PixelRegCache::GEN_DEPTH_OFF); - regCache_.ForceRetain(PixelRegCache::GEN_DEPTH_OFF); + regCache_.Unlock(argXReg, RegCache::GEN_ARG_X); + regCache_.Change(RegCache::GEN_ARG_X, RegCache::GEN_DEPTH_OFF); + regCache_.ForceRetain(RegCache::GEN_DEPTH_OFF); } else { - regCache_.Unlock(argXReg, PixelRegCache::GEN_ARG_X); - regCache_.ForceRelease(PixelRegCache::GEN_ARG_X); + regCache_.Unlock(argXReg, RegCache::GEN_ARG_X); + regCache_.ForceRelease(RegCache::GEN_ARG_X); } - return regCache_.Find(PixelRegCache::GEN_COLOR_OFF); + return regCache_.Find(RegCache::GEN_COLOR_OFF); } - X64Reg argYReg = regCache_.Find(PixelRegCache::GEN_ARG_Y); + X64Reg argYReg = regCache_.Find(RegCache::GEN_ARG_Y); X64Reg r; if (id.useStandardStride) { - r = regCache_.Alloc(PixelRegCache::GEN_COLOR_OFF); + r = regCache_.Alloc(RegCache::GEN_COLOR_OFF); MOV(32, R(r), R(argYReg)); SHL(32, R(r), Imm8(9)); } else { X64Reg gstateReg = GetGState(); - r = regCache_.Alloc(PixelRegCache::GEN_COLOR_OFF); + r = regCache_.Alloc(RegCache::GEN_COLOR_OFF); MOVZX(32, 16, r, MDisp(gstateReg, offsetof(GPUgstate, fbwidth))); - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); AND(16, R(r), Imm16(0x07FC)); IMUL(32, r, R(argYReg)); } - regCache_.Unlock(argYReg, PixelRegCache::GEN_ARG_Y); + regCache_.Unlock(argYReg, RegCache::GEN_ARG_Y); - X64Reg argXReg = regCache_.Find(PixelRegCache::GEN_ARG_X); + X64Reg argXReg = regCache_.Find(RegCache::GEN_ARG_X); ADD(32, R(r), R(argXReg)); - regCache_.Unlock(argXReg, PixelRegCache::GEN_ARG_X); + regCache_.Unlock(argXReg, RegCache::GEN_ARG_X); - X64Reg temp = regCache_.Alloc(PixelRegCache::GEN_TEMP_HELPER); + X64Reg temp = regCache_.Alloc(RegCache::GEN_TEMP_HELPER); MOV(PTRBITS, R(temp), ImmPtr(&fb.data)); MOV(PTRBITS, R(temp), MatR(temp)); LEA(PTRBITS, r, MComplex(temp, r, id.FBFormat() == GE_FORMAT_8888 ? 4 : 2, 0)); - regCache_.Release(temp, PixelRegCache::GEN_TEMP_HELPER); + regCache_.Release(temp, RegCache::GEN_TEMP_HELPER); return r; } - return regCache_.Find(PixelRegCache::GEN_COLOR_OFF); + return regCache_.Find(RegCache::GEN_COLOR_OFF); } -PixelRegCache::Reg PixelJitCache::GetDepthOff(const PixelFuncID &id) { - if (!regCache_.Has(PixelRegCache::GEN_DEPTH_OFF)) { +RegCache::Reg PixelJitCache::GetDepthOff(const PixelFuncID &id) { + if (!regCache_.Has(RegCache::GEN_DEPTH_OFF)) { // If both color and depth use 512, the offsets are the same. if (id.useStandardStride && !id.dithering) { // Calculate once inside GetColorOff(). X64Reg colorOffReg = GetColorOff(id); - regCache_.Unlock(colorOffReg, PixelRegCache::GEN_COLOR_OFF); - return regCache_.Find(PixelRegCache::GEN_DEPTH_OFF); + regCache_.Unlock(colorOffReg, RegCache::GEN_COLOR_OFF); + return regCache_.Find(RegCache::GEN_DEPTH_OFF); } - X64Reg argYReg = regCache_.Find(PixelRegCache::GEN_ARG_Y); + X64Reg argYReg = regCache_.Find(RegCache::GEN_ARG_Y); X64Reg r; if (id.useStandardStride) { - r = regCache_.Alloc(PixelRegCache::GEN_DEPTH_OFF); + r = regCache_.Alloc(RegCache::GEN_DEPTH_OFF); MOV(32, R(r), R(argYReg)); SHL(32, R(r), Imm8(9)); } else { X64Reg gstateReg = GetGState(); - r = regCache_.Alloc(PixelRegCache::GEN_DEPTH_OFF); + r = regCache_.Alloc(RegCache::GEN_DEPTH_OFF); MOVZX(32, 16, r, MDisp(gstateReg, offsetof(GPUgstate, zbwidth))); - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); AND(16, R(r), Imm16(0x07FC)); IMUL(32, r, R(argYReg)); } - regCache_.Unlock(argYReg, PixelRegCache::GEN_ARG_Y); + regCache_.Unlock(argYReg, RegCache::GEN_ARG_Y); - X64Reg argXReg = regCache_.Find(PixelRegCache::GEN_ARG_X); + X64Reg argXReg = regCache_.Find(RegCache::GEN_ARG_X); ADD(32, R(r), R(argXReg)); - regCache_.Unlock(argXReg, PixelRegCache::GEN_ARG_X); + regCache_.Unlock(argXReg, RegCache::GEN_ARG_X); - X64Reg temp = regCache_.Alloc(PixelRegCache::GEN_TEMP_HELPER); + X64Reg temp = regCache_.Alloc(RegCache::GEN_TEMP_HELPER); MOV(PTRBITS, R(temp), ImmPtr(&depthbuf.data)); MOV(PTRBITS, R(temp), MatR(temp)); LEA(PTRBITS, r, MComplex(temp, r, 2, 0)); - regCache_.Release(temp, PixelRegCache::GEN_TEMP_HELPER); + regCache_.Release(temp, RegCache::GEN_TEMP_HELPER); return r; } - return regCache_.Find(PixelRegCache::GEN_DEPTH_OFF); + return regCache_.Find(RegCache::GEN_DEPTH_OFF); } -PixelRegCache::Reg PixelJitCache::GetDestStencil(const PixelFuncID &id) { +RegCache::Reg PixelJitCache::GetDestStencil(const PixelFuncID &id) { // Skip if 565, since stencil is fixed zero. if (id.FBFormat() == GE_FORMAT_565) return INVALID_REG; X64Reg colorOffReg = GetColorOff(id); - X64Reg stencilReg = regCache_.Alloc(PixelRegCache::GEN_STENCIL); + X64Reg stencilReg = regCache_.Alloc(RegCache::GEN_STENCIL); if (id.FBFormat() == GE_FORMAT_8888) { MOVZX(32, 8, stencilReg, MDisp(colorOffReg, 3)); } else if (id.FBFormat() == GE_FORMAT_5551) { @@ -325,13 +325,13 @@ PixelRegCache::Reg PixelJitCache::GetDestStencil(const PixelFuncID &id) { } else if (id.FBFormat() == GE_FORMAT_4444) { MOVZX(32, 8, stencilReg, MDisp(colorOffReg, 1)); SHR(32, R(stencilReg), Imm8(4)); - X64Reg temp = regCache_.Alloc(PixelRegCache::GEN_TEMP_HELPER); + X64Reg temp = regCache_.Alloc(RegCache::GEN_TEMP_HELPER); MOV(32, R(temp), R(stencilReg)); SHL(32, R(temp), Imm8(4)); OR(32, R(stencilReg), R(temp)); - regCache_.Release(temp, PixelRegCache::GEN_TEMP_HELPER); + regCache_.Release(temp, RegCache::GEN_TEMP_HELPER); } - regCache_.Unlock(colorOffReg, PixelRegCache::GEN_COLOR_OFF); + regCache_.Unlock(colorOffReg, RegCache::GEN_COLOR_OFF); return stencilReg; } @@ -347,30 +347,30 @@ void PixelJitCache::Discard(Gen::CCFlags cc) { bool PixelJitCache::Jit_ApplyDepthRange(const PixelFuncID &id) { if (id.applyDepthRange) { X64Reg gstateReg = GetGState(); - X64Reg minReg = regCache_.Alloc(PixelRegCache::GEN_TEMP0); - X64Reg maxReg = regCache_.Alloc(PixelRegCache::GEN_TEMP1); + X64Reg minReg = regCache_.Alloc(RegCache::GEN_TEMP0); + X64Reg maxReg = regCache_.Alloc(RegCache::GEN_TEMP1); // Only load the lowest 16 bits of each, but compare all 32 of z. MOVZX(32, 16, minReg, MDisp(gstateReg, offsetof(GPUgstate, minz))); MOVZX(32, 16, maxReg, MDisp(gstateReg, offsetof(GPUgstate, maxz))); - X64Reg argZReg = regCache_.Find(PixelRegCache::GEN_ARG_Z); + X64Reg argZReg = regCache_.Find(RegCache::GEN_ARG_Z); CMP(32, R(argZReg), R(minReg)); Discard(CC_L); CMP(32, R(argZReg), R(maxReg)); Discard(CC_G); - regCache_.Unlock(argZReg, PixelRegCache::GEN_ARG_Z); + regCache_.Unlock(argZReg, RegCache::GEN_ARG_Z); - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); - regCache_.Release(minReg, PixelRegCache::GEN_TEMP0); - regCache_.Release(maxReg, PixelRegCache::GEN_TEMP1); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); + regCache_.Release(minReg, RegCache::GEN_TEMP0); + regCache_.Release(maxReg, RegCache::GEN_TEMP1); } // Since this is early on, try to free up the z reg if we don't need it anymore. if (id.clearMode && !id.DepthClear()) - regCache_.ForceRelease(PixelRegCache::GEN_ARG_Z); + regCache_.ForceRelease(RegCache::GEN_ARG_Z); else if (!id.clearMode && !id.depthWrite && id.DepthTestFunc() == GE_COMP_ALWAYS) - regCache_.ForceRelease(PixelRegCache::GEN_ARG_Z); + regCache_.ForceRelease(RegCache::GEN_ARG_Z); return true; } @@ -391,14 +391,14 @@ bool PixelJitCache::Jit_AlphaTest(const PixelFuncID &id) { // Load alpha into its own general reg. X64Reg alphaReg; - if (regCache_.Has(PixelRegCache::GEN_SRC_ALPHA)) { - alphaReg = regCache_.Find(PixelRegCache::GEN_SRC_ALPHA); + if (regCache_.Has(RegCache::GEN_SRC_ALPHA)) { + alphaReg = regCache_.Find(RegCache::GEN_SRC_ALPHA); } else { - alphaReg = regCache_.Alloc(PixelRegCache::GEN_SRC_ALPHA); + alphaReg = regCache_.Alloc(RegCache::GEN_SRC_ALPHA); _assert_(!colorIs16Bit_); - X64Reg argColorReg = regCache_.Find(PixelRegCache::VEC_ARG_COLOR); + X64Reg argColorReg = regCache_.Find(RegCache::VEC_ARG_COLOR); MOVD_xmm(R(alphaReg), argColorReg); - regCache_.Unlock(argColorReg, PixelRegCache::VEC_ARG_COLOR); + regCache_.Unlock(argColorReg, RegCache::VEC_ARG_COLOR); SHR(32, R(alphaReg), Imm8(24)); } @@ -406,13 +406,13 @@ bool PixelJitCache::Jit_AlphaTest(const PixelFuncID &id) { // Unfortunate, we'll need gstate to load the mask. // Note: we leave the ALPHA purpose untouched and free it, because later code may reuse. X64Reg gstateReg = GetGState(); - X64Reg maskedReg = regCache_.Alloc(PixelRegCache::GEN_TEMP0); + X64Reg maskedReg = regCache_.Alloc(RegCache::GEN_TEMP0); // The mask is >> 16, so we load + 2. MOVZX(32, 8, maskedReg, MDisp(gstateReg, offsetof(GPUgstate, alphatest) + 2)); - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); AND(32, R(maskedReg), R(alphaReg)); - regCache_.Unlock(alphaReg, PixelRegCache::GEN_SRC_ALPHA); + regCache_.Unlock(alphaReg, RegCache::GEN_SRC_ALPHA); // Okay now do the rest using the masked reg, which we modified. alphaReg = maskedReg; @@ -421,9 +421,9 @@ bool PixelJitCache::Jit_AlphaTest(const PixelFuncID &id) { // We hardcode the ref into this jit func. CMP(8, R(alphaReg), Imm8(id.alphaTestRef)); if (id.hasAlphaTestMask) - regCache_.Release(alphaReg, PixelRegCache::GEN_TEMP0); + regCache_.Release(alphaReg, RegCache::GEN_TEMP0); else - regCache_.Unlock(alphaReg, PixelRegCache::GEN_SRC_ALPHA); + regCache_.Unlock(alphaReg, RegCache::GEN_SRC_ALPHA); switch (id.AlphaTestFunc()) { case GE_COMP_NEVER: @@ -464,9 +464,9 @@ bool PixelJitCache::Jit_ColorTest(const PixelFuncID &id) { // We'll have 4 with fog released, so we're using them all... X64Reg gstateReg = GetGState(); - X64Reg funcReg = regCache_.Alloc(PixelRegCache::GEN_TEMP0); - X64Reg maskReg = regCache_.Alloc(PixelRegCache::GEN_TEMP1); - X64Reg refReg = regCache_.Alloc(PixelRegCache::GEN_TEMP2); + X64Reg funcReg = regCache_.Alloc(RegCache::GEN_TEMP0); + X64Reg maskReg = regCache_.Alloc(RegCache::GEN_TEMP1); + X64Reg refReg = regCache_.Alloc(RegCache::GEN_TEMP2); // First, load the registers: mask and ref. MOV(32, R(maskReg), MDisp(gstateReg, offsetof(GPUgstate, colortestmask))); @@ -474,7 +474,7 @@ bool PixelJitCache::Jit_ColorTest(const PixelFuncID &id) { MOV(32, R(refReg), MDisp(gstateReg, offsetof(GPUgstate, colorref))); AND(32, R(refReg), R(maskReg)); - X64Reg argColorReg = regCache_.Find(PixelRegCache::VEC_ARG_COLOR); + X64Reg argColorReg = regCache_.Find(RegCache::VEC_ARG_COLOR); if (colorIs16Bit_) { // If it's expanded, we need to clamp anyway if it was fogged. PACKUSWB(argColorReg, R(argColorReg)); @@ -484,12 +484,12 @@ bool PixelJitCache::Jit_ColorTest(const PixelFuncID &id) { // Temporarily abuse funcReg to grab the color into maskReg. MOVD_xmm(R(funcReg), argColorReg); AND(32, R(maskReg), R(funcReg)); - regCache_.Unlock(argColorReg, PixelRegCache::VEC_ARG_COLOR); + regCache_.Unlock(argColorReg, RegCache::VEC_ARG_COLOR); // Now that we're setup, get the func and follow it. MOVZX(32, 8, funcReg, MDisp(gstateReg, offsetof(GPUgstate, colortest))); AND(8, R(funcReg), Imm8(3)); - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); CMP(8, R(funcReg), Imm8(GE_COMP_ALWAYS)); // Discard for GE_COMP_NEVER... @@ -498,7 +498,7 @@ bool PixelJitCache::Jit_ColorTest(const PixelFuncID &id) { CMP(8, R(funcReg), Imm8(GE_COMP_EQUAL)); FixupBranch doEqual = J_CC(CC_E); - regCache_.Release(funcReg, PixelRegCache::GEN_TEMP0); + regCache_.Release(funcReg, RegCache::GEN_TEMP0); // The not equal path here... if they are equal, we discard. CMP(32, R(refReg), R(maskReg)); @@ -509,8 +509,8 @@ bool PixelJitCache::Jit_ColorTest(const PixelFuncID &id) { CMP(32, R(refReg), R(maskReg)); Discard(CC_NE); - regCache_.Release(maskReg, PixelRegCache::GEN_TEMP1); - regCache_.Release(refReg, PixelRegCache::GEN_TEMP2); + regCache_.Release(maskReg, RegCache::GEN_TEMP1); + regCache_.Release(refReg, RegCache::GEN_TEMP2); SetJumpTarget(skip); SetJumpTarget(skip2); @@ -521,12 +521,12 @@ bool PixelJitCache::Jit_ColorTest(const PixelFuncID &id) { bool PixelJitCache::Jit_ApplyFog(const PixelFuncID &id) { if (!id.applyFog) { // Okay, anyone can use the fog register then. - regCache_.ForceRelease(PixelRegCache::GEN_ARG_FOG); + regCache_.ForceRelease(RegCache::GEN_ARG_FOG); return true; } // Load fog and expand to 16 bit. Ignore the high 8 bits, which'll match up with A. - X64Reg fogColorReg = regCache_.Alloc(PixelRegCache::VEC_TEMP1); + X64Reg fogColorReg = regCache_.Alloc(RegCache::VEC_TEMP1); X64Reg gstateReg = GetGState(); if (cpu_info.bSSE4_1) { X64Reg gstateReg = GetGState(); @@ -536,46 +536,46 @@ bool PixelJitCache::Jit_ApplyFog(const PixelFuncID &id) { X64Reg zeroReg = GetZeroVec(); MOVD_xmm(fogColorReg, MDisp(gstateReg, offsetof(GPUgstate, fogcolor))); PUNPCKLBW(fogColorReg, R(zeroReg)); - regCache_.Unlock(zeroReg, PixelRegCache::VEC_ZERO); + regCache_.Unlock(zeroReg, RegCache::VEC_ZERO); } - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); // Load a set of 255s at 16 bit into a reg for later... - X64Reg invertReg = regCache_.Alloc(PixelRegCache::VEC_TEMP2); + X64Reg invertReg = regCache_.Alloc(RegCache::VEC_TEMP2); X64Reg constReg = GetConstBase(); MOVDQA(invertReg, MConstDisp(constReg, &const255_16s[0])); - regCache_.Unlock(constReg, PixelRegCache::GEN_CONST_BASE); + regCache_.Unlock(constReg, RegCache::GEN_CONST_BASE); // Expand (we clamped) color to 16 bit as well, so we can multiply with fog. - X64Reg argColorReg = regCache_.Find(PixelRegCache::VEC_ARG_COLOR); + X64Reg argColorReg = regCache_.Find(RegCache::VEC_ARG_COLOR); if (!colorIs16Bit_) { if (cpu_info.bSSE4_1) { PMOVZXBW(argColorReg, R(argColorReg)); } else { X64Reg zeroReg = GetZeroVec(); PUNPCKLBW(argColorReg, R(zeroReg)); - regCache_.Unlock(zeroReg, PixelRegCache::VEC_ZERO); + regCache_.Unlock(zeroReg, RegCache::VEC_ZERO); } colorIs16Bit_ = true; } // Save A so we can put it back, we don't "fog" A. X64Reg alphaReg; - if (regCache_.Has(PixelRegCache::GEN_SRC_ALPHA)) { - alphaReg = regCache_.Find(PixelRegCache::GEN_SRC_ALPHA); + if (regCache_.Has(RegCache::GEN_SRC_ALPHA)) { + alphaReg = regCache_.Find(RegCache::GEN_SRC_ALPHA); } else { - alphaReg = regCache_.Alloc(PixelRegCache::GEN_SRC_ALPHA); + alphaReg = regCache_.Alloc(RegCache::GEN_SRC_ALPHA); PEXTRW(alphaReg, argColorReg, 3); } // Okay, let's broadcast fog to an XMM. - X64Reg fogMultReg = regCache_.Alloc(PixelRegCache::VEC_TEMP3); - X64Reg argFogReg = regCache_.Find(PixelRegCache::GEN_ARG_FOG); + X64Reg fogMultReg = regCache_.Alloc(RegCache::VEC_TEMP3); + X64Reg argFogReg = regCache_.Find(RegCache::GEN_ARG_FOG); MOVD_xmm(fogMultReg, R(argFogReg)); PSHUFLW(fogMultReg, R(fogMultReg), _MM_SHUFFLE(0, 0, 0, 0)); - regCache_.Unlock(argFogReg, PixelRegCache::GEN_ARG_FOG); + regCache_.Unlock(argFogReg, RegCache::GEN_ARG_FOG); // We can free up the actual fog reg now. - regCache_.ForceRelease(PixelRegCache::GEN_ARG_FOG); + regCache_.ForceRelease(RegCache::GEN_ARG_FOG); // Now we multiply the existing color by fog... PMULLW(argColorReg, R(fogMultReg)); @@ -584,23 +584,23 @@ bool PixelJitCache::Jit_ApplyFog(const PixelFuncID &id) { PMULLW(fogColorReg, R(invertReg)); // At this point, argColorReg and fogColorReg are multiplied at 16-bit, so we need to sum. PADDUSW(argColorReg, R(fogColorReg)); - regCache_.Release(fogColorReg, PixelRegCache::VEC_TEMP1); - regCache_.Release(invertReg, PixelRegCache::VEC_TEMP2); - regCache_.Release(fogMultReg, PixelRegCache::VEC_TEMP3); + regCache_.Release(fogColorReg, RegCache::VEC_TEMP1); + regCache_.Release(invertReg, RegCache::VEC_TEMP2); + regCache_.Release(fogMultReg, RegCache::VEC_TEMP3); // Now to divide by 255, we use bit tricks: multiply by 0x8081, and shift right by 16+7. constReg = GetConstBase(); PMULHUW(argColorReg, MConstDisp(constReg, &by255i)); - regCache_.Unlock(constReg, PixelRegCache::GEN_CONST_BASE); + regCache_.Unlock(constReg, RegCache::GEN_CONST_BASE); // Now shift right by 7 (PMULHUW already did 16 of the shift.) PSRLW(argColorReg, 7); // Okay, put A back in, we'll shrink it to 8888 when needed. PINSRW(argColorReg, R(alphaReg), 3); - regCache_.Unlock(argColorReg, PixelRegCache::VEC_ARG_COLOR); + regCache_.Unlock(argColorReg, RegCache::VEC_ARG_COLOR); // We most likely won't use alphaReg again. - regCache_.Unlock(alphaReg, PixelRegCache::GEN_SRC_ALPHA); + regCache_.Unlock(alphaReg, RegCache::GEN_SRC_ALPHA); return true; } @@ -612,16 +612,16 @@ bool PixelJitCache::Jit_StencilAndDepthTest(const PixelFuncID &id) { X64Reg maskedReg = stencilReg; if (id.hasStencilTestMask) { X64Reg gstateReg = GetGState(); - maskedReg = regCache_.Alloc(PixelRegCache::GEN_TEMP0); + maskedReg = regCache_.Alloc(RegCache::GEN_TEMP0); MOV(32, R(maskedReg), R(stencilReg)); AND(8, R(maskedReg), MDisp(gstateReg, offsetof(GPUgstate, stenciltest) + 2)); - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); } bool success = true; success = success && Jit_StencilTest(id, stencilReg, maskedReg); if (maskedReg != stencilReg) - regCache_.Unlock(maskedReg, PixelRegCache::GEN_TEMP0); + regCache_.Unlock(maskedReg, RegCache::GEN_TEMP0); // Next up, the depth test. if (stencilReg == INVALID_REG) { @@ -634,12 +634,12 @@ bool PixelJitCache::Jit_StencilAndDepthTest(const PixelFuncID &id) { success = success && Jit_ApplyStencilOp(id, id.ZPass(), stencilReg); // At this point, stencilReg can't be spilled. It contains the updated value. - regCache_.ForceRetain(PixelRegCache::GEN_STENCIL); + regCache_.ForceRetain(RegCache::GEN_STENCIL); return success; } -bool PixelJitCache::Jit_StencilTest(const PixelFuncID &id, PixelRegCache::Reg stencilReg, PixelRegCache::Reg maskedReg) { +bool PixelJitCache::Jit_StencilTest(const PixelFuncID &id, RegCache::Reg stencilReg, RegCache::Reg maskedReg) { bool hasFixedResult = false; bool fixedResult = false; FixupBranch toPass; @@ -715,15 +715,15 @@ bool PixelJitCache::Jit_StencilTest(const PixelFuncID &id, PixelRegCache::Reg st return success; } -bool PixelJitCache::Jit_DepthTestForStencil(const PixelFuncID &id, PixelRegCache::Reg stencilReg) { +bool PixelJitCache::Jit_DepthTestForStencil(const PixelFuncID &id, RegCache::Reg stencilReg) { if (id.DepthTestFunc() == GE_COMP_ALWAYS) return true; X64Reg depthOffReg = GetDepthOff(id); - X64Reg argZReg = regCache_.Find(PixelRegCache::GEN_ARG_Z); + X64Reg argZReg = regCache_.Find(RegCache::GEN_ARG_Z); CMP(16, R(argZReg), MatR(depthOffReg)); - regCache_.Unlock(depthOffReg, PixelRegCache::GEN_DEPTH_OFF); - regCache_.Unlock(argZReg, PixelRegCache::GEN_ARG_Z); + regCache_.Unlock(depthOffReg, RegCache::GEN_DEPTH_OFF); + regCache_.Unlock(argZReg, RegCache::GEN_ARG_Z); // We discard the opposite of the passing test. FixupBranch skip; @@ -775,12 +775,12 @@ bool PixelJitCache::Jit_DepthTestForStencil(const PixelFuncID &id, PixelRegCache // Like in Jit_DepthTest(), at this point we may not need this reg anymore. if (!id.depthWrite) - regCache_.ForceRelease(PixelRegCache::GEN_ARG_Z); + regCache_.ForceRelease(RegCache::GEN_ARG_Z); return success; } -bool PixelJitCache::Jit_ApplyStencilOp(const PixelFuncID &id, GEStencilOp op, PixelRegCache::Reg stencilReg) { +bool PixelJitCache::Jit_ApplyStencilOp(const PixelFuncID &id, GEStencilOp op, RegCache::Reg stencilReg) { _assert_(stencilReg != INVALID_REG); FixupBranch skip; @@ -798,7 +798,7 @@ bool PixelJitCache::Jit_ApplyStencilOp(const PixelFuncID &id, GEStencilOp op, Pi // Load the unmasked value. X64Reg gstateReg = GetGState(); MOVZX(32, 8, stencilReg, MDisp(gstateReg, offsetof(GPUgstate, stenciltest) + 1)); - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); } else { MOV(8, R(stencilReg), Imm8(id.stencilTestRef)); } @@ -862,14 +862,14 @@ bool PixelJitCache::Jit_ApplyStencilOp(const PixelFuncID &id, GEStencilOp op, Pi return true; } -bool PixelJitCache::Jit_WriteStencilOnly(const PixelFuncID &id, PixelRegCache::Reg stencilReg) { +bool PixelJitCache::Jit_WriteStencilOnly(const PixelFuncID &id, RegCache::Reg stencilReg) { _assert_(stencilReg != INVALID_REG); // It's okay to destory stencilReg here, we know we're the last writing it. X64Reg colorOffReg = GetColorOff(id); if (id.applyColorWriteMask) { X64Reg gstateReg = GetGState(); - X64Reg maskReg = regCache_.Alloc(PixelRegCache::GEN_TEMP5); + X64Reg maskReg = regCache_.Alloc(RegCache::GEN_TEMP5); switch (id.fbFormat) { case GE_FORMAT_565: @@ -914,8 +914,8 @@ bool PixelJitCache::Jit_WriteStencilOnly(const PixelFuncID &id, PixelRegCache::R break; } - regCache_.Release(maskReg, PixelRegCache::GEN_TEMP5); - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); + regCache_.Release(maskReg, RegCache::GEN_TEMP5); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); } else { switch (id.fbFormat) { case GE_FORMAT_565: @@ -939,7 +939,7 @@ bool PixelJitCache::Jit_WriteStencilOnly(const PixelFuncID &id, PixelRegCache::R } } - regCache_.Unlock(colorOffReg, PixelRegCache::GEN_COLOR_OFF); + regCache_.Unlock(colorOffReg, RegCache::GEN_COLOR_OFF); return true; } @@ -953,10 +953,10 @@ bool PixelJitCache::Jit_DepthTest(const PixelFuncID &id) { } X64Reg depthOffReg = GetDepthOff(id); - X64Reg argZReg = regCache_.Find(PixelRegCache::GEN_ARG_Z); + X64Reg argZReg = regCache_.Find(RegCache::GEN_ARG_Z); CMP(16, R(argZReg), MatR(depthOffReg)); - regCache_.Unlock(depthOffReg, PixelRegCache::GEN_DEPTH_OFF); - regCache_.Unlock(argZReg, PixelRegCache::GEN_ARG_Z); + regCache_.Unlock(depthOffReg, RegCache::GEN_DEPTH_OFF); + regCache_.Unlock(argZReg, RegCache::GEN_ARG_Z); // We discard the opposite of the passing test. switch (id.DepthTestFunc()) { @@ -991,7 +991,7 @@ bool PixelJitCache::Jit_DepthTest(const PixelFuncID &id) { // If we're not writing, we don't need Z anymore. We'll free GEN_DEPTH_OFF in Jit_WriteDepth(). if (!id.depthWrite) - regCache_.ForceRelease(PixelRegCache::GEN_ARG_Z); + regCache_.ForceRelease(RegCache::GEN_ARG_Z); return true; } @@ -1000,16 +1000,16 @@ bool PixelJitCache::Jit_WriteDepth(const PixelFuncID &id) { // Clear mode shares depthWrite for DepthClear(). if (id.depthWrite) { X64Reg depthOffReg = GetDepthOff(id); - X64Reg argZReg = regCache_.Find(PixelRegCache::GEN_ARG_Z); + X64Reg argZReg = regCache_.Find(RegCache::GEN_ARG_Z); MOV(16, MatR(depthOffReg), R(argZReg)); - regCache_.Unlock(depthOffReg, PixelRegCache::GEN_DEPTH_OFF); - regCache_.Unlock(argZReg, PixelRegCache::GEN_ARG_Z); - regCache_.ForceRelease(PixelRegCache::GEN_ARG_Z); + regCache_.Unlock(depthOffReg, RegCache::GEN_DEPTH_OFF); + regCache_.Unlock(argZReg, RegCache::GEN_ARG_Z); + regCache_.ForceRelease(RegCache::GEN_ARG_Z); } // We can free up this reg if we force locked it. - if (regCache_.Has(PixelRegCache::GEN_DEPTH_OFF)) { - regCache_.ForceRelease(PixelRegCache::GEN_DEPTH_OFF); + if (regCache_.Has(RegCache::GEN_DEPTH_OFF)) { + regCache_.ForceRelease(RegCache::GEN_DEPTH_OFF); } return true; @@ -1026,19 +1026,19 @@ bool PixelJitCache::Jit_AlphaBlend(const PixelFuncID &id) { bool success = true; // Step 1: Load and expand dest color. - X64Reg dstReg = regCache_.Alloc(PixelRegCache::VEC_TEMP0); + X64Reg dstReg = regCache_.Alloc(RegCache::VEC_TEMP0); if (id.FBFormat() == GE_FORMAT_8888) { X64Reg colorOff = GetColorOff(id); MOVD_xmm(dstReg, MatR(colorOff)); - regCache_.Unlock(colorOff, PixelRegCache::GEN_COLOR_OFF); + regCache_.Unlock(colorOff, RegCache::GEN_COLOR_OFF); } else { X64Reg colorOff = GetColorOff(id); - X64Reg dstGenReg = regCache_.Alloc(PixelRegCache::GEN_TEMP0); + X64Reg dstGenReg = regCache_.Alloc(RegCache::GEN_TEMP0); MOVZX(32, 16, dstGenReg, MatR(colorOff)); - regCache_.Unlock(colorOff, PixelRegCache::GEN_COLOR_OFF); + regCache_.Unlock(colorOff, RegCache::GEN_COLOR_OFF); - X64Reg temp1Reg = regCache_.Alloc(PixelRegCache::GEN_TEMP1); - X64Reg temp2Reg = regCache_.Alloc(PixelRegCache::GEN_TEMP2); + X64Reg temp1Reg = regCache_.Alloc(RegCache::GEN_TEMP1); + X64Reg temp2Reg = regCache_.Alloc(RegCache::GEN_TEMP2); switch (id.fbFormat) { case GE_FORMAT_565: @@ -1060,16 +1060,16 @@ bool PixelJitCache::Jit_AlphaBlend(const PixelFuncID &id) { MOVD_xmm(dstReg, R(dstGenReg)); - regCache_.Release(dstGenReg, PixelRegCache::GEN_TEMP0); - regCache_.Release(temp1Reg, PixelRegCache::GEN_TEMP1); - regCache_.Release(temp2Reg, PixelRegCache::GEN_TEMP2); + regCache_.Release(dstGenReg, RegCache::GEN_TEMP0); + regCache_.Release(temp1Reg, RegCache::GEN_TEMP1); + regCache_.Release(temp2Reg, RegCache::GEN_TEMP2); } // Step 2: Load and apply factors. - X64Reg argColorReg = regCache_.Find(PixelRegCache::VEC_ARG_COLOR); + X64Reg argColorReg = regCache_.Find(RegCache::VEC_ARG_COLOR); if (blendState.usesFactors) { - X64Reg srcFactorReg = regCache_.Alloc(PixelRegCache::VEC_TEMP1); - X64Reg dstFactorReg = regCache_.Alloc(PixelRegCache::VEC_TEMP2); + X64Reg srcFactorReg = regCache_.Alloc(RegCache::VEC_TEMP1); + X64Reg dstFactorReg = regCache_.Alloc(RegCache::VEC_TEMP2); // We apply these at 16-bit, because they can be doubled and have a half offset. if (cpu_info.bSSE4_1) { @@ -1081,7 +1081,7 @@ bool PixelJitCache::Jit_AlphaBlend(const PixelFuncID &id) { if (!colorIs16Bit_) PUNPCKLBW(argColorReg, R(zeroReg)); PUNPCKLBW(dstReg, R(zeroReg)); - regCache_.Unlock(zeroReg, PixelRegCache::VEC_ZERO); + regCache_.Unlock(zeroReg, RegCache::VEC_ZERO); } colorIs16Bit_ = true; @@ -1095,10 +1095,10 @@ bool PixelJitCache::Jit_AlphaBlend(const PixelFuncID &id) { success = success && Jit_DstBlendFactor(id, srcFactorReg, dstFactorReg, dstReg); X64Reg constReg = GetConstBase(); - X64Reg halfReg = regCache_.Alloc(PixelRegCache::VEC_TEMP3); + X64Reg halfReg = regCache_.Alloc(RegCache::VEC_TEMP3); // We'll use this several times, so load into a reg. MOVDQA(halfReg, MConstDisp(constReg, &blendHalf_11_4s[0])); - regCache_.Unlock(constReg, PixelRegCache::GEN_CONST_BASE); + regCache_.Unlock(constReg, RegCache::GEN_CONST_BASE); // Add in the half bit to the factors and color values, then multiply. // We take the high 16 bits to get a free right shift by 16. @@ -1110,9 +1110,9 @@ bool PixelJitCache::Jit_AlphaBlend(const PixelFuncID &id) { POR(dstReg, R(halfReg)); PMULHUW(dstReg, R(dstFactorReg)); - regCache_.Release(srcFactorReg, PixelRegCache::VEC_TEMP1); - regCache_.Release(dstFactorReg, PixelRegCache::VEC_TEMP2); - regCache_.Release(halfReg, PixelRegCache::VEC_TEMP3); + regCache_.Release(srcFactorReg, RegCache::VEC_TEMP1); + regCache_.Release(dstFactorReg, RegCache::VEC_TEMP2); + regCache_.Release(halfReg, RegCache::VEC_TEMP3); } else if (colorIs16Bit_) { // If it's expanded, shrink and clamp for our min/max/absdiff handling. PACKUSWB(argColorReg, R(argColorReg)); @@ -1122,7 +1122,7 @@ bool PixelJitCache::Jit_AlphaBlend(const PixelFuncID &id) { // Step 3: Apply equation. // Note: below, we completely ignore what happens to the alpha bits. // It won't matter, since we'll replace those with stencil anyway. - X64Reg tempReg = regCache_.Alloc(PixelRegCache::VEC_TEMP1); + X64Reg tempReg = regCache_.Alloc(RegCache::VEC_TEMP1); switch (id.AlphaBlendEq()) { case GE_BLENDMODE_MUL_AND_ADD: PADDUSW(argColorReg, R(dstReg)); @@ -1157,19 +1157,19 @@ bool PixelJitCache::Jit_AlphaBlend(const PixelFuncID &id) { break; } - regCache_.Release(dstReg, PixelRegCache::VEC_TEMP0); - regCache_.Release(tempReg, PixelRegCache::VEC_TEMP1); - regCache_.Unlock(argColorReg, PixelRegCache::VEC_ARG_COLOR); + regCache_.Release(dstReg, RegCache::VEC_TEMP0); + regCache_.Release(tempReg, RegCache::VEC_TEMP1); + regCache_.Unlock(argColorReg, RegCache::VEC_ARG_COLOR); return success; } -bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, PixelRegCache::Reg factorReg, PixelRegCache::Reg dstReg, GEBlendSrcFactor factor) { +bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, RegCache::Reg factorReg, RegCache::Reg dstReg, GEBlendSrcFactor factor) { X64Reg constReg = INVALID_REG; X64Reg gstateReg = INVALID_REG; X64Reg tempReg = INVALID_REG; - X64Reg argColorReg = regCache_.Find(PixelRegCache::VEC_ARG_COLOR); + X64Reg argColorReg = regCache_.Find(RegCache::VEC_ARG_COLOR); // Everything below expects an expanded 16-bit color _assert_(colorIs16Bit_); @@ -1194,7 +1194,7 @@ bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, PixelRegCache::Reg fa case GE_SRCBLEND_INVSRCALPHA: constReg = GetConstBase(); - tempReg = regCache_.Alloc(PixelRegCache::VEC_TEMP3); + tempReg = regCache_.Alloc(RegCache::VEC_TEMP3); MOVDQA(factorReg, MConstDisp(constReg, &blendInvert_11_4s[0])); PSHUFLW(tempReg, R(argColorReg), _MM_SHUFFLE(3, 3, 3, 3)); @@ -1207,7 +1207,7 @@ bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, PixelRegCache::Reg fa case GE_SRCBLEND_INVDSTALPHA: constReg = GetConstBase(); - tempReg = regCache_.Alloc(PixelRegCache::VEC_TEMP3); + tempReg = regCache_.Alloc(RegCache::VEC_TEMP3); MOVDQA(factorReg, MConstDisp(constReg, &blendInvert_11_4s[0])); PSHUFLW(tempReg, R(dstReg), _MM_SHUFFLE(3, 3, 3, 3)); @@ -1221,7 +1221,7 @@ bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, PixelRegCache::Reg fa case GE_SRCBLEND_DOUBLEINVSRCALPHA: constReg = GetConstBase(); - tempReg = regCache_.Alloc(PixelRegCache::VEC_TEMP3); + tempReg = regCache_.Alloc(RegCache::VEC_TEMP3); MOVDQA(factorReg, MConstDisp(constReg, &blendInvert_11_4s[0])); PSHUFLW(tempReg, R(argColorReg), _MM_SHUFFLE(3, 3, 3, 3)); @@ -1236,7 +1236,7 @@ bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, PixelRegCache::Reg fa case GE_SRCBLEND_DOUBLEINVDSTALPHA: constReg = GetConstBase(); - tempReg = regCache_.Alloc(PixelRegCache::VEC_TEMP3); + tempReg = regCache_.Alloc(RegCache::VEC_TEMP3); MOVDQA(factorReg, MConstDisp(constReg, &blendInvert_11_4s[0])); PSHUFLW(tempReg, R(dstReg), _MM_SHUFFLE(3, 3, 3, 3)); @@ -1253,7 +1253,7 @@ bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, PixelRegCache::Reg fa } else { X64Reg zeroReg = GetZeroVec(); PUNPCKLBW(factorReg, R(zeroReg)); - regCache_.Unlock(zeroReg, PixelRegCache::VEC_ZERO); + regCache_.Unlock(zeroReg, RegCache::VEC_ZERO); } // Round it out by shifting into place. PSLLW(factorReg, 4); @@ -1261,21 +1261,21 @@ bool PixelJitCache::Jit_BlendFactor(const PixelFuncID &id, PixelRegCache::Reg fa } if (constReg != INVALID_REG) - regCache_.Unlock(constReg, PixelRegCache::GEN_CONST_BASE); + regCache_.Unlock(constReg, RegCache::GEN_CONST_BASE); if (gstateReg != INVALID_REG) - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); if (tempReg != INVALID_REG) - regCache_.Release(tempReg, PixelRegCache::VEC_TEMP3); - regCache_.Unlock(argColorReg, PixelRegCache::VEC_ARG_COLOR); + regCache_.Release(tempReg, RegCache::VEC_TEMP3); + regCache_.Unlock(argColorReg, RegCache::VEC_ARG_COLOR); return true; } -bool PixelJitCache::Jit_DstBlendFactor(const PixelFuncID &id, PixelRegCache::Reg srcFactorReg, PixelRegCache::Reg dstFactorReg, PixelRegCache::Reg dstReg) { +bool PixelJitCache::Jit_DstBlendFactor(const PixelFuncID &id, RegCache::Reg srcFactorReg, RegCache::Reg dstFactorReg, RegCache::Reg dstReg) { bool success = true; X64Reg constReg = INVALID_REG; X64Reg gstateReg = INVALID_REG; - X64Reg argColorReg = regCache_.Find(PixelRegCache::VEC_ARG_COLOR); + X64Reg argColorReg = regCache_.Find(RegCache::VEC_ARG_COLOR); // Everything below expects an expanded 16-bit color _assert_(colorIs16Bit_); @@ -1324,7 +1324,7 @@ bool PixelJitCache::Jit_DstBlendFactor(const PixelFuncID &id, PixelRegCache::Reg } else { X64Reg zeroReg = GetZeroVec(); PUNPCKLBW(dstFactorReg, R(zeroReg)); - regCache_.Unlock(zeroReg, PixelRegCache::VEC_ZERO); + regCache_.Unlock(zeroReg, RegCache::VEC_ZERO); } // Round it out by shifting into place. PSLLW(dstFactorReg, 4); @@ -1332,10 +1332,10 @@ bool PixelJitCache::Jit_DstBlendFactor(const PixelFuncID &id, PixelRegCache::Reg } if (constReg != INVALID_REG) - regCache_.Unlock(constReg, PixelRegCache::GEN_CONST_BASE); + regCache_.Unlock(constReg, RegCache::GEN_CONST_BASE); if (gstateReg != INVALID_REG) - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); - regCache_.Unlock(argColorReg, PixelRegCache::VEC_ARG_COLOR); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); + regCache_.Unlock(argColorReg, RegCache::VEC_ARG_COLOR); return success; } @@ -1347,27 +1347,27 @@ bool PixelJitCache::Jit_Dither(const PixelFuncID &id) { #ifndef SOFTPIXEL_USE_CACHE X64Reg gstateReg = GetGState(); #endif - X64Reg valueReg = regCache_.Alloc(PixelRegCache::GEN_TEMP0); + X64Reg valueReg = regCache_.Alloc(RegCache::GEN_TEMP0); // Load the row dither matrix entry (will still need to get the X.) - X64Reg argYReg = regCache_.Find(PixelRegCache::GEN_ARG_Y); + X64Reg argYReg = regCache_.Find(RegCache::GEN_ARG_Y); MOV(32, R(valueReg), R(argYReg)); AND(32, R(valueReg), Imm8(3)); #ifndef SOFTPIXEL_USE_CACHE MOVZX(32, 16, valueReg, MComplex(gstateReg, valueReg, 4, offsetof(GPUgstate, dithmtx))); - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); #endif // At this point, we're done with depth and y, so let's grab GEN_COLOR_OFF and retain it. // Then we can modify x and throw it away too, which is our actual goal. X64Reg colorOffReg = GetColorOff(id); - regCache_.Unlock(colorOffReg, PixelRegCache::GEN_COLOR_OFF); - regCache_.ForceRetain(PixelRegCache::GEN_COLOR_OFF); + regCache_.Unlock(colorOffReg, RegCache::GEN_COLOR_OFF); + regCache_.ForceRetain(RegCache::GEN_COLOR_OFF); // And get rid of y, we can use for other regs. - regCache_.Unlock(argYReg, PixelRegCache::GEN_ARG_Y); - regCache_.ForceRelease(PixelRegCache::GEN_ARG_Y); + regCache_.Unlock(argYReg, RegCache::GEN_ARG_Y); + regCache_.ForceRelease(RegCache::GEN_ARG_Y); - X64Reg argXReg = regCache_.Find(PixelRegCache::GEN_ARG_X); + X64Reg argXReg = regCache_.Find(RegCache::GEN_ARG_X); AND(32, R(argXReg), Imm32(3)); #ifndef SOFTPIXEL_USE_CACHE @@ -1378,7 +1378,7 @@ bool PixelJitCache::Jit_Dither(const PixelFuncID &id) { if (argXReg != RCX) { bool needsSwap = false; // This will force release argXReg if swapped. - regCache_.GrabReg(RCX, PixelRegCache::GEN_TEMP1, needsSwap, argXReg, PixelRegCache::GEN_ARG_X); + regCache_.GrabReg(RCX, RegCache::GEN_TEMP1, needsSwap, argXReg, RegCache::GEN_ARG_X); shiftReg = RCX; if (needsSwap) { @@ -1400,7 +1400,7 @@ bool PixelJitCache::Jit_Dither(const PixelFuncID &id) { // Release RCX if we explicitly grabbed. if (shiftReg != INVALID_REG) - regCache_.Release(shiftReg, PixelRegCache::GEN_TEMP1); + regCache_.Release(shiftReg, RegCache::GEN_TEMP1); // Now we need to make 0-7 positive, 8-F negative.. so sign extend. SHL(32, R(valueReg), Imm8(4)); @@ -1416,14 +1416,14 @@ bool PixelJitCache::Jit_Dither(const PixelFuncID &id) { MOVSX(32, 16, valueReg, MRegSum(argXReg, valueReg)); #endif if (argXReg != INVALID_REG) { - regCache_.Unlock(argXReg, PixelRegCache::GEN_ARG_X); - regCache_.ForceRelease(PixelRegCache::GEN_ARG_X); + regCache_.Unlock(argXReg, RegCache::GEN_ARG_X); + regCache_.ForceRelease(RegCache::GEN_ARG_X); } // Copy that value into a vec to add to the color. - X64Reg vecValueReg = regCache_.Alloc(PixelRegCache::VEC_TEMP0); + X64Reg vecValueReg = regCache_.Alloc(RegCache::VEC_TEMP0); MOVD_xmm(vecValueReg, R(valueReg)); - regCache_.Release(valueReg, PixelRegCache::GEN_TEMP0); + regCache_.Release(valueReg, RegCache::GEN_TEMP0); // Now we want to broadcast RGB in 16-bit, but keep A as 0. // Luckily, we know that second lane (in 16-bit) is zero from valueReg's high 16 bits. @@ -1431,39 +1431,39 @@ bool PixelJitCache::Jit_Dither(const PixelFuncID &id) { PSHUFLW(vecValueReg, R(vecValueReg), _MM_SHUFFLE(1, 0, 0, 0)); // With that, now let's convert the color to 16 bit... - X64Reg argColorReg = regCache_.Find(PixelRegCache::VEC_ARG_COLOR); + X64Reg argColorReg = regCache_.Find(RegCache::VEC_ARG_COLOR); if (!colorIs16Bit_) { if (cpu_info.bSSE4_1) { PMOVZXBW(argColorReg, R(argColorReg)); } else { X64Reg zeroReg = GetZeroVec(); PUNPCKLBW(argColorReg, R(zeroReg)); - regCache_.Unlock(zeroReg, PixelRegCache::VEC_ZERO); + regCache_.Unlock(zeroReg, RegCache::VEC_ZERO); } colorIs16Bit_ = true; } // And simply add the dither values. PADDSW(argColorReg, R(vecValueReg)); - regCache_.Release(vecValueReg, PixelRegCache::VEC_TEMP0); - regCache_.Unlock(argColorReg, PixelRegCache::VEC_ARG_COLOR); + regCache_.Release(vecValueReg, RegCache::VEC_TEMP0); + regCache_.Unlock(argColorReg, RegCache::VEC_ARG_COLOR); return true; } bool PixelJitCache::Jit_WriteColor(const PixelFuncID &id) { X64Reg colorOff = GetColorOff(id); - if (regCache_.Has(PixelRegCache::GEN_ARG_X)) { + if (regCache_.Has(RegCache::GEN_ARG_X)) { // We normally toss x and y during dithering or useStandardStride with no dithering. // Free up the regs now to get more reg space. - regCache_.ForceRelease(PixelRegCache::GEN_ARG_X); - regCache_.ForceRelease(PixelRegCache::GEN_ARG_Y); + regCache_.ForceRelease(RegCache::GEN_ARG_X); + regCache_.ForceRelease(RegCache::GEN_ARG_Y); // But make sure we don't lose GEN_COLOR_OFF, we'll be lost without that now. - regCache_.ForceRetain(PixelRegCache::GEN_COLOR_OFF); + regCache_.ForceRetain(RegCache::GEN_COLOR_OFF); } // Convert back to 8888 and clamp. - X64Reg argColorReg = regCache_.Find(PixelRegCache::VEC_ARG_COLOR); + X64Reg argColorReg = regCache_.Find(RegCache::VEC_ARG_COLOR); if (colorIs16Bit_) { PACKUSWB(argColorReg, R(argColorReg)); colorIs16Bit_ = false; @@ -1478,34 +1478,34 @@ bool PixelJitCache::Jit_WriteColor(const PixelFuncID &id) { if (!id.ColorClear()) { // Let's reuse Jit_WriteStencilOnly for this path. X64Reg alphaReg; - if (regCache_.Has(PixelRegCache::GEN_SRC_ALPHA)) { - alphaReg = regCache_.Find(PixelRegCache::GEN_SRC_ALPHA); + if (regCache_.Has(RegCache::GEN_SRC_ALPHA)) { + alphaReg = regCache_.Find(RegCache::GEN_SRC_ALPHA); } else { - alphaReg = regCache_.Alloc(PixelRegCache::GEN_SRC_ALPHA); + alphaReg = regCache_.Alloc(RegCache::GEN_SRC_ALPHA); MOVD_xmm(R(alphaReg), argColorReg); SHR(32, R(alphaReg), Imm8(24)); } bool success = Jit_WriteStencilOnly(id, alphaReg); - regCache_.Release(alphaReg, PixelRegCache::GEN_SRC_ALPHA); - regCache_.Unlock(argColorReg, PixelRegCache::VEC_ARG_COLOR); + regCache_.Release(alphaReg, RegCache::GEN_SRC_ALPHA); + regCache_.Unlock(argColorReg, RegCache::VEC_ARG_COLOR); return success; } // In this case, we're clearing only color or only color and stencil. Proceed. } - X64Reg colorReg = regCache_.Alloc(PixelRegCache::GEN_TEMP0); + X64Reg colorReg = regCache_.Alloc(RegCache::GEN_TEMP0); MOVD_xmm(R(colorReg), argColorReg); - regCache_.Unlock(argColorReg, PixelRegCache::VEC_ARG_COLOR); - regCache_.ForceRelease(PixelRegCache::VEC_ARG_COLOR); + regCache_.Unlock(argColorReg, RegCache::VEC_ARG_COLOR); + regCache_.ForceRelease(RegCache::VEC_ARG_COLOR); X64Reg stencilReg = INVALID_REG; - if (regCache_.Has(PixelRegCache::GEN_STENCIL)) - stencilReg = regCache_.Find(PixelRegCache::GEN_STENCIL); + if (regCache_.Has(RegCache::GEN_STENCIL)) + stencilReg = regCache_.Find(RegCache::GEN_STENCIL); - X64Reg temp1Reg = regCache_.Alloc(PixelRegCache::GEN_TEMP1); - X64Reg temp2Reg = regCache_.Alloc(PixelRegCache::GEN_TEMP2); + X64Reg temp1Reg = regCache_.Alloc(RegCache::GEN_TEMP1); + X64Reg temp2Reg = regCache_.Alloc(RegCache::GEN_TEMP2); bool convertAlpha = id.clearMode && id.StencilClear(); bool writeAlpha = convertAlpha || stencilReg != INVALID_REG; uint32_t fixedKeepMask = 0x00000000; @@ -1560,7 +1560,7 @@ bool PixelJitCache::Jit_WriteColor(const PixelFuncID &id) { if (id.applyColorWriteMask) { #ifndef SOFTPIXEL_USE_CACHE X64Reg gstateReg = GetGState(); - maskReg = regCache_.Alloc(PixelRegCache::GEN_TEMP3); + maskReg = regCache_.Alloc(RegCache::GEN_TEMP3); // Load the write mask, combine in the stencil/alpha mask bits. MOV(32, R(maskReg), MDisp(gstateReg, offsetof(GPUgstate, pmskc))); @@ -1569,7 +1569,7 @@ bool PixelJitCache::Jit_WriteColor(const PixelFuncID &id) { SHL(32, R(temp2Reg), Imm8(24)); OR(32, R(maskReg), R(temp2Reg)); } - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); // Switch the mask into the specified bit depth. This is easier. switch (id.fbFormat) { @@ -1595,7 +1595,7 @@ bool PixelJitCache::Jit_WriteColor(const PixelFuncID &id) { break; } #else - maskReg = regCache_.Alloc(PixelRegCache::GEN_TEMP3); + maskReg = regCache_.Alloc(RegCache::GEN_TEMP3); // Load the pre-converted and combined write mask. MOV(PTRBITS, R(maskReg), MDisp(RSP, stackIDOffset_)); MOV(32, R(maskReg), MDisp(maskReg, offsetof(PixelFuncID, cached.colorWriteMask))); @@ -1603,7 +1603,7 @@ bool PixelJitCache::Jit_WriteColor(const PixelFuncID &id) { } // We've run out of regs, let's live without temp2 from here on. - regCache_.Release(temp2Reg, PixelRegCache::GEN_TEMP2); + regCache_.Release(temp2Reg, RegCache::GEN_TEMP2); // Step 3: Apply logic op, combine stencil. skipStandardWrites_.clear(); @@ -1660,34 +1660,34 @@ bool PixelJitCache::Jit_WriteColor(const PixelFuncID &id) { SetJumpTarget(fixup); skipStandardWrites_.clear(); - regCache_.Unlock(colorOff, PixelRegCache::GEN_COLOR_OFF); - regCache_.ForceRelease(PixelRegCache::GEN_COLOR_OFF); - regCache_.Release(colorReg, PixelRegCache::GEN_TEMP0); - regCache_.Release(temp1Reg, PixelRegCache::GEN_TEMP1); + regCache_.Unlock(colorOff, RegCache::GEN_COLOR_OFF); + regCache_.ForceRelease(RegCache::GEN_COLOR_OFF); + regCache_.Release(colorReg, RegCache::GEN_TEMP0); + regCache_.Release(temp1Reg, RegCache::GEN_TEMP1); if (maskReg != INVALID_REG) - regCache_.Release(maskReg, PixelRegCache::GEN_TEMP3); + regCache_.Release(maskReg, RegCache::GEN_TEMP3); if (stencilReg != INVALID_REG) { - regCache_.Unlock(stencilReg, PixelRegCache::GEN_STENCIL); - regCache_.ForceRelease(PixelRegCache::GEN_STENCIL); + regCache_.Unlock(stencilReg, RegCache::GEN_STENCIL); + regCache_.ForceRelease(RegCache::GEN_STENCIL); } return success; } -bool PixelJitCache::Jit_ApplyLogicOp(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg maskReg) { +bool PixelJitCache::Jit_ApplyLogicOp(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg maskReg) { X64Reg gstateReg = GetGState(); - X64Reg logicOpReg = regCache_.Alloc(PixelRegCache::GEN_TEMP3); + X64Reg logicOpReg = regCache_.Alloc(RegCache::GEN_TEMP3); MOVZX(32, 8, logicOpReg, MDisp(gstateReg, offsetof(GPUgstate, lop))); AND(8, R(logicOpReg), Imm8(0x0F)); - regCache_.Unlock(gstateReg, PixelRegCache::GEN_GSTATE); + regCache_.Unlock(gstateReg, RegCache::GEN_GSTATE); X64Reg stencilReg = INVALID_REG; - if (regCache_.Has(PixelRegCache::GEN_STENCIL)) - stencilReg = regCache_.Find(PixelRegCache::GEN_STENCIL); + if (regCache_.Has(RegCache::GEN_STENCIL)) + stencilReg = regCache_.Find(RegCache::GEN_STENCIL); // Should already be allocated. - X64Reg colorOff = regCache_.Find(PixelRegCache::GEN_COLOR_OFF); - X64Reg temp1Reg = regCache_.Find(PixelRegCache::GEN_TEMP1); + X64Reg colorOff = regCache_.Find(RegCache::GEN_COLOR_OFF); + X64Reg temp1Reg = regCache_.Find(RegCache::GEN_TEMP1); // We'll use these in several cases, so prepare. int bits = id.fbFormat == GE_FORMAT_8888 ? 32 : 16; @@ -2006,16 +2006,16 @@ bool PixelJitCache::Jit_ApplyLogicOp(const PixelFuncID &id, PixelRegCache::Reg c for (FixupBranch &fixup : finishes) SetJumpTarget(fixup); - regCache_.Unlock(colorOff, PixelRegCache::GEN_COLOR_OFF); - regCache_.Unlock(temp1Reg, PixelRegCache::GEN_TEMP1); - regCache_.Unlock(logicOpReg, PixelRegCache::GEN_TEMP3); + regCache_.Unlock(colorOff, RegCache::GEN_COLOR_OFF); + regCache_.Unlock(temp1Reg, RegCache::GEN_TEMP1); + regCache_.Unlock(logicOpReg, RegCache::GEN_TEMP3); if (stencilReg != INVALID_REG) - regCache_.Unlock(stencilReg, PixelRegCache::GEN_STENCIL); + regCache_.Unlock(stencilReg, RegCache::GEN_STENCIL); return true; } -bool PixelJitCache::Jit_ConvertTo565(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg temp1Reg, PixelRegCache::Reg temp2Reg) { +bool PixelJitCache::Jit_ConvertTo565(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg temp1Reg, RegCache::Reg temp2Reg) { // Assemble the 565 color, starting with R... MOV(32, R(temp1Reg), R(colorReg)); SHR(32, R(temp1Reg), Imm8(3)); @@ -2035,7 +2035,7 @@ bool PixelJitCache::Jit_ConvertTo565(const PixelFuncID &id, PixelRegCache::Reg c return true; } -bool PixelJitCache::Jit_ConvertTo5551(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg temp1Reg, PixelRegCache::Reg temp2Reg, bool keepAlpha) { +bool PixelJitCache::Jit_ConvertTo5551(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg temp1Reg, RegCache::Reg temp2Reg, bool keepAlpha) { // This is R, pretty simple. MOV(32, R(temp1Reg), R(colorReg)); SHR(32, R(temp1Reg), Imm8(3)); @@ -2065,7 +2065,7 @@ bool PixelJitCache::Jit_ConvertTo5551(const PixelFuncID &id, PixelRegCache::Reg return true; } -bool PixelJitCache::Jit_ConvertTo4444(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg temp1Reg, PixelRegCache::Reg temp2Reg, bool keepAlpha) { +bool PixelJitCache::Jit_ConvertTo4444(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg temp1Reg, RegCache::Reg temp2Reg, bool keepAlpha) { // Shift and mask out R. MOV(32, R(temp1Reg), R(colorReg)); SHR(32, R(temp1Reg), Imm8(4)); @@ -2095,7 +2095,7 @@ bool PixelJitCache::Jit_ConvertTo4444(const PixelFuncID &id, PixelRegCache::Reg return true; } -bool PixelJitCache::Jit_ConvertFrom565(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg temp1Reg, PixelRegCache::Reg temp2Reg) { +bool PixelJitCache::Jit_ConvertFrom565(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg temp1Reg, RegCache::Reg temp2Reg) { // Filter out red only into temp1. MOV(32, R(temp1Reg), R(colorReg)); AND(16, R(temp1Reg), Imm16(0x1F << 0)); @@ -2129,7 +2129,7 @@ bool PixelJitCache::Jit_ConvertFrom565(const PixelFuncID &id, PixelRegCache::Reg return true; } -bool PixelJitCache::Jit_ConvertFrom5551(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg temp1Reg, PixelRegCache::Reg temp2Reg, bool keepAlpha) { +bool PixelJitCache::Jit_ConvertFrom5551(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg temp1Reg, RegCache::Reg temp2Reg, bool keepAlpha) { // Filter out red only into temp1. MOV(32, R(temp1Reg), R(colorReg)); AND(16, R(temp1Reg), Imm16(0x1F << 0)); @@ -2165,7 +2165,7 @@ bool PixelJitCache::Jit_ConvertFrom5551(const PixelFuncID &id, PixelRegCache::Re return true; } -bool PixelJitCache::Jit_ConvertFrom4444(const PixelFuncID &id, PixelRegCache::Reg colorReg, PixelRegCache::Reg temp1Reg, PixelRegCache::Reg temp2Reg, bool keepAlpha) { +bool PixelJitCache::Jit_ConvertFrom4444(const PixelFuncID &id, RegCache::Reg colorReg, RegCache::Reg temp1Reg, RegCache::Reg temp2Reg, bool keepAlpha) { // Move red into position within temp1. MOV(32, R(temp1Reg), R(colorReg)); AND(16, R(temp1Reg), Imm16(0xF << 0)); diff --git a/GPU/Software/RasterizerRegCache.cpp b/GPU/Software/RasterizerRegCache.cpp new file mode 100644 index 0000000000..21646a667f --- /dev/null +++ b/GPU/Software/RasterizerRegCache.cpp @@ -0,0 +1,214 @@ +// Copyright (c) 2021- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#include "GPU/Software/RasterizerRegCache.h" + +namespace Rasterizer { + +void RegCache::Reset(bool validate) { + if (validate) { + for (auto ® : regs) { + _assert_msg_(reg.locked == 0, "softjit: Reset() with reg still locked (%04X)", reg.purpose); + _assert_msg_(!reg.forceRetained, "softjit: Reset() with reg force retained (%04X)", reg.purpose); + } + } + regs.clear(); +} + +void RegCache::Add(Reg r, Purpose p) { + for (auto ® : regs) { + if (reg.reg == r && (reg.purpose & FLAG_GEN) == (p & FLAG_GEN)) { + _assert_msg_(false, "softjit Add() reg duplicate (%04X)", p); + } + } + _assert_msg_(r != REG_INVALID_VALUE, "softjit Add() invalid reg (%04X)", p); + + RegStatus newStatus; + newStatus.reg = r; + newStatus.purpose = p; + regs.push_back(newStatus); +} + +void RegCache::Change(Purpose history, Purpose destiny) { + for (auto ® : regs) { + if (reg.purpose == history) { + reg.purpose = destiny; + return; + } + } + + _assert_msg_(false, "softjit Change() reg that isn't there (%04X)", history); +} + +void RegCache::Release(Reg &r, Purpose p) { + RegStatus *status = FindReg(r, p); + _assert_msg_(status != nullptr, "softjit Release() reg that isn't there (%04X)", p); + _assert_msg_(status->locked > 0, "softjit Release() reg that isn't locked (%04X)", p); + _assert_msg_(!status->forceRetained, "softjit Release() reg that is force retained (%04X)", p); + + status->locked--; + if (status->locked == 0) { + if ((status->purpose & FLAG_GEN) != 0) + status->purpose = GEN_INVALID; + else + status->purpose = VEC_INVALID; + } + + r = REG_INVALID_VALUE; +} + +void RegCache::Unlock(Reg &r, Purpose p) { + RegStatus *status = FindReg(r, p); + if (status) { + _assert_msg_(status->locked > 0, "softjit Unlock() reg that isn't locked (%04X)", p); + status->locked--; + r = REG_INVALID_VALUE; + return; + } + + _assert_msg_(false, "softjit Unlock() reg that isn't there (%04X)", p); +} + +bool RegCache::Has(Purpose p) { + for (auto ® : regs) { + if (reg.purpose == p) { + return true; + } + } + return false; +} + +RegCache::Reg RegCache::Find(Purpose p) { + for (auto ® : regs) { + if (reg.purpose == p) { + _assert_msg_(reg.locked <= 255, "softjit Find() reg has lots of locks (%04X)", p); + reg.locked++; + return reg.reg; + } + } + _assert_msg_(false, "softjit Find() reg that isn't there (%04X)", p); + return REG_INVALID_VALUE; +} + +RegCache::Reg RegCache::Alloc(Purpose p) { + _assert_msg_(!Has(p), "softjit Alloc() reg duplicate (%04X)", p); + RegStatus *best = nullptr; + for (auto ® : regs) { + if (reg.locked != 0 || reg.forceRetained) + continue; + // Needs to be the same type. + if ((reg.purpose & FLAG_GEN) != (p & FLAG_GEN)) + continue; + + if (best == nullptr) + best = ® + // Prefer a free/purposeless reg (includes INVALID.) + if ((reg.purpose & FLAG_TEMP) != 0) { + best = ® + break; + } + // But also prefer a lower priority reg. + if (reg.purpose < best->purpose) + best = ® + } + + if (best) { + best->locked = 1; + best->purpose = p; + return best->reg; + } + + _assert_msg_(false, "softjit Alloc() reg with none free (%04X)", p); + return REG_INVALID_VALUE; +} + +void RegCache::ForceRetain(Purpose p) { + for (auto ® : regs) { + if (reg.purpose == p) { + reg.forceRetained = true; + return; + } + } + + _assert_msg_(false, "softjit ForceRetain() reg that isn't there (%04X)", p); +} + +void RegCache::ForceRelease(Purpose p) { + for (auto ® : regs) { + if (reg.purpose == p) { + _assert_msg_(reg.locked == 0, "softjit ForceRelease() while locked (%04X)", p); + reg.forceRetained = false; + if ((reg.purpose & FLAG_GEN) != 0) + reg.purpose = GEN_INVALID; + else + reg.purpose = VEC_INVALID; + return; + } + } + + _assert_msg_(false, "softjit ForceRelease() reg that isn't there (%04X)", p); +} + +void RegCache::GrabReg(Reg r, Purpose p, bool &needsSwap, Reg swapReg, Purpose swapPurpose) { + for (auto ® : regs) { + if (reg.reg != r) + continue; + if ((reg.purpose & FLAG_GEN) != (p & FLAG_GEN)) + continue; + + // Easy version, it's free. + if (reg.locked == 0 && !reg.forceRetained) { + needsSwap = false; + reg.purpose = p; + reg.locked = 1; + return; + } + + // Okay, we need to swap. Find that reg. + needsSwap = true; + RegStatus *swap = FindReg(swapReg, swapPurpose); + if (swap) { + swap->purpose = reg.purpose; + swap->forceRetained = reg.forceRetained; + swap->locked = reg.locked; + } else { + _assert_msg_(!Has(swapPurpose), "softjit GrabReg() wrong purpose (%04X)", swapPurpose); + RegStatus newStatus = reg; + newStatus.reg = swapReg; + regs.push_back(newStatus); + } + + reg.purpose = p; + reg.locked = 1; + reg.forceRetained = false; + return; + } + + _assert_msg_(false, "softjit GrabReg() reg that isn't there"); +} + +RegCache::RegStatus *RegCache::FindReg(Reg r, Purpose p) { + for (auto ® : regs) { + if (reg.reg == r && reg.purpose == p) { + return ® + } + } + + return nullptr; +} + +}; diff --git a/GPU/Software/RasterizerRegCache.h b/GPU/Software/RasterizerRegCache.h new file mode 100644 index 0000000000..8efe81925a --- /dev/null +++ b/GPU/Software/RasterizerRegCache.h @@ -0,0 +1,122 @@ +// Copyright (c) 2021- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include "ppsspp_config.h" + +#include +#include +#if PPSSPP_ARCH(ARM) +#include "Common/ArmEmitter.h" +#elif PPSSPP_ARCH(ARM64) +#include "Common/Arm64Emitter.h" +#elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) +#include "Common/x64Emitter.h" +#elif PPSSPP_ARCH(MIPS) +#include "Common/MipsEmitter.h" +#else +#include "Common/FakeEmitter.h" +#endif + +namespace Rasterizer { + +struct RegCache { + enum Purpose { + FLAG_GEN = 0x0100, + FLAG_TEMP = 0x1000, + + VEC_ZERO = 0x0000, + + GEN_SRC_ALPHA = 0x0100, + GEN_GSTATE = 0x0101, + GEN_CONST_BASE = 0x0102, + GEN_STENCIL = 0x0103, + GEN_COLOR_OFF = 0x0104, + GEN_DEPTH_OFF = 0x0105, + + GEN_ARG_X = 0x0180, + GEN_ARG_Y = 0x0181, + GEN_ARG_Z = 0x0182, + GEN_ARG_FOG = 0x0183, + VEC_ARG_COLOR = 0x0080, + VEC_ARG_MASK = 0x0081, + + VEC_TEMP0 = 0x1000, + VEC_TEMP1 = 0x1001, + VEC_TEMP2 = 0x1002, + VEC_TEMP3 = 0x1003, + VEC_TEMP4 = 0x1004, + VEC_TEMP5 = 0x1005, + + GEN_TEMP0 = 0x1100, + GEN_TEMP1 = 0x1101, + GEN_TEMP2 = 0x1102, + GEN_TEMP3 = 0x1103, + GEN_TEMP4 = 0x1104, + GEN_TEMP5 = 0x1105, + GEN_TEMP_HELPER = 0x1106, + + VEC_INVALID = 0xFEFF, + GEN_INVALID = 0xFFFF, + }; + +#if PPSSPP_ARCH(ARM) + typedef ArmGen::ARMReg Reg; + static constexpr Reg REG_INVALID_VALUE = ArmGen::INVALID_REG; +#elif PPSSPP_ARCH(ARM64) + typedef Arm64Gen::ARM64Reg Reg; + static constexpr Reg REG_INVALID_VALUE = Arm64Gen::INVALID_REG; +#elif PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64) + typedef Gen::X64Reg Reg; + static constexpr Reg REG_INVALID_VALUE = Gen::INVALID_REG; +#elif PPSSPP_ARCH(MIPS) + typedef MIPSGen::MIPSReg Reg; + static constexpr Reg REG_INVALID_VALUE = MIPSGen::INVALID_REG; +#else + typedef int Reg; + static constexpr Reg REG_INVALID_VALUE = -1; +#endif + + struct RegStatus { + Reg reg; + Purpose purpose; + uint8_t locked = 0; + bool forceRetained = false; + }; + + void Reset(bool validate); + void Add(Reg r, Purpose p); + void Change(Purpose history, Purpose destiny); + void Release(Reg &r, Purpose p); + void Unlock(Reg &r, Purpose p); + bool Has(Purpose p); + Reg Find(Purpose p); + Reg Alloc(Purpose p); + void ForceRetain(Purpose p); + void ForceRelease(Purpose p); + + // For getting a specific reg. WARNING: May return a locked reg, so you have to check. + void GrabReg(Reg r, Purpose p, bool &needsSwap, Reg swapReg, Purpose swapPurpose); + +private: + RegStatus *FindReg(Reg r, Purpose p); + + std::vector regs; +}; + +}; diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj b/UWP/GPU_UWP/GPU_UWP.vcxproj index 76458d8906..d8e70972e6 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj @@ -431,6 +431,7 @@ + @@ -491,6 +492,7 @@ + diff --git a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters index 591297863e..2f982e10b0 100644 --- a/UWP/GPU_UWP/GPU_UWP.vcxproj.filters +++ b/UWP/GPU_UWP/GPU_UWP.vcxproj.filters @@ -55,6 +55,7 @@ + @@ -114,6 +115,7 @@ + diff --git a/android/jni/Android.mk b/android/jni/Android.mk index a3039ecd41..c62de2889f 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -369,6 +369,7 @@ EXEC_AND_LIB_FILES := \ $(SRC)/GPU/Software/Lighting.cpp \ $(SRC)/GPU/Software/Rasterizer.cpp.arm \ $(SRC)/GPU/Software/RasterizerRectangle.cpp.arm \ + $(SRC)/GPU/Software/RasterizerRegCache.cpp \ $(SRC)/GPU/Software/Sampler.cpp \ $(SRC)/GPU/Software/SoftGpu.cpp \ $(SRC)/GPU/Software/TransformUnit.cpp \ diff --git a/libretro/Makefile.common b/libretro/Makefile.common index fd8048c7ee..32c10ee8db 100644 --- a/libretro/Makefile.common +++ b/libretro/Makefile.common @@ -356,6 +356,7 @@ SOURCES_CXX += \ $(GPUDIR)/Software/Lighting.cpp \ $(GPUDIR)/Software/Rasterizer.cpp \ $(GPUDIR)/Software/RasterizerRectangle.cpp \ + $(GPUDIR)/Software/RasterizerRegCache.cpp \ $(GPUDIR)/GLES/DepalettizeShaderGLES.cpp \ $(GPUDIR)/GLES/DepthBufferGLES.cpp \ $(GPUDIR)/GLES/DrawEngineGLES.cpp \