From 1e00a3b842dab28f72d8631379217fd2482ae522 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 21 Nov 2021 16:01:55 -0800 Subject: [PATCH] softjit: Add color test. --- GPU/Software/DrawPixel.h | 1 + GPU/Software/DrawPixelX86.cpp | 53 +++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/GPU/Software/DrawPixel.h b/GPU/Software/DrawPixel.h index fa03000919..8d2530165c 100644 --- a/GPU/Software/DrawPixel.h +++ b/GPU/Software/DrawPixel.h @@ -138,6 +138,7 @@ private: bool Jit_ApplyDepthRange(const PixelFuncID &id); bool Jit_AlphaTest(const PixelFuncID &id); bool Jit_ApplyFog(const PixelFuncID &id); + bool Jit_ColorTest(const PixelFuncID &id); std::unordered_map cache_; std::unordered_map addresses_; diff --git a/GPU/Software/DrawPixelX86.cpp b/GPU/Software/DrawPixelX86.cpp index 65157ee0ba..e7b2103ce5 100644 --- a/GPU/Software/DrawPixelX86.cpp +++ b/GPU/Software/DrawPixelX86.cpp @@ -99,6 +99,7 @@ SingleFunc PixelJitCache::CompileSingle(const PixelFuncID &id) { success = success && Jit_AlphaTest(id); // Fog is applied prior to color test. Maybe before alpha test too, but it doesn't affect it... success = success && Jit_ApplyFog(id); + success = success && Jit_ColorTest(id); // TODO: There's more... success = false; @@ -254,6 +255,58 @@ bool PixelJitCache::Jit_AlphaTest(const PixelFuncID &id) { return true; } +bool PixelJitCache::Jit_ColorTest(const PixelFuncID &id) { + if (!id.colorTest || id.clearMode) + return true; + + // We'll have 4 with fog released, so we're using them all... + X64Reg gstateReg = GetGState(); + X64Reg funcReg = regCache_.Alloc(PixelRegCache::TEMP0, PixelRegCache::T_GEN); + X64Reg maskReg = regCache_.Alloc(PixelRegCache::TEMP1, PixelRegCache::T_GEN); + X64Reg refReg = regCache_.Alloc(PixelRegCache::TEMP2, PixelRegCache::T_GEN); + + // First, load the registers: mask and ref. + MOV(32, R(maskReg), MDisp(gstateReg, offsetof(GPUgstate, colortestmask))); + AND(32, R(maskReg), Imm32(0x00FFFFFF)); + MOV(32, R(refReg), MDisp(gstateReg, offsetof(GPUgstate, colorref))); + AND(32, R(refReg), R(maskReg)); + + // Temporarily abuse funcReg to grab the color into maskReg. + MOVD_xmm(R(funcReg), argColorReg); + AND(32, R(maskReg), R(funcReg)); + + // Now that we're setup, get the func and follow it. + MOVZX(32, 8, funcReg, MDisp(gstateReg, offsetof(GPUgstate, colortest))); + AND(32, R(funcReg), Imm32(3)); + regCache_.Unlock(gstateReg, PixelRegCache::T_GEN); + + CMP(32, R(funcReg), Imm32(GE_COMP_ALWAYS)); + // Discard for GE_COMP_NEVER... + Discard(CC_B); + FixupBranch skip = J_CC(CC_E); + + CMP(32, R(funcReg), Imm32(GE_COMP_EQUAL)); + FixupBranch doEqual = J_CC(CC_E); + regCache_.Release(funcReg, PixelRegCache::T_GEN); + + // The not equal path here... if they are equal, we discard. + CMP(32, R(refReg), R(maskReg)); + Discard(CC_E); + FixupBranch skip2 = J(); + + SetJumpTarget(doEqual); + CMP(32, R(refReg), R(maskReg)); + Discard(CC_NE); + + regCache_.Release(maskReg, PixelRegCache::T_GEN); + regCache_.Release(refReg, PixelRegCache::T_GEN); + + SetJumpTarget(skip); + SetJumpTarget(skip2); + + return true; +} + bool PixelJitCache::Jit_ApplyFog(const PixelFuncID &id) { if (!id.applyFog) { // Okay, anyone can use the fog register then.