samplerjit: Avoid frac uv transfer to gen regs.

It should just stay in vec, this is more convenient anyway.
This commit is contained in:
Unknown W. Brackets committed 2022-01-28 23:50:54 -08:00
1 parent 99cfff3ac6
commit eb70a90347
3 files changed
+47 -73

No files matched your search

+2 -3
View File
@@ -127,15 +127,14 @@ struct RegCache {
GEN_ARG_LEVEL = 0x0189,
GEN_ARG_TEXPTR_PTR = 0x018A,
GEN_ARG_BUFW_PTR = 0x018B,
GEN_ARG_FRAC_U = 0x018C,
GEN_ARG_FRAC_V = 0x018D,
GEN_ARG_LEVELFRAC = 0x018E,
GEN_ARG_LEVELFRAC = 0x018C,
VEC_ARG_COLOR = 0x0080,
VEC_ARG_MASK = 0x0081,
VEC_ARG_U = 0x0082,
VEC_ARG_V = 0x0083,
VEC_ARG_S = 0x0084,
VEC_ARG_T = 0x0085,
VEC_FRAC = 0x0086,
VEC_TEMP0 = 0x1000,
VEC_TEMP1 = 0x1001,
+1 -1
View File
@@ -101,7 +101,7 @@ private:
#if PPSSPP_ARCH(AMD64) || PPSSPP_ARCH(X86)
int stackArgPos_ = 0;
int stackIDOffset_ = -1;
int stackFracUV1Offset_ = 0;
int stackUV1Offset_ = 0;
#endif
const u8 *constWidthHeight256f_ = nullptr;
+44 -69
View File
@@ -165,11 +165,11 @@ NearestFunc SamplerJitCache::CompileNearest(const SamplerID &id) {
stackArgPos_ += 32;
#if PPSSPP_PLATFORM(WINDOWS)
// Use the shadow space to save U1/V1. We also use this var for frac U1/V1 in linear.
stackFracUV1Offset_ = -8;
// Use the shadow space to save U1/V1.
stackUV1Offset_ = -8;
#else
// Use the red zone, but account for the R15-R12 we push just below.
stackFracUV1Offset_ = -stackArgPos_ - 8;
stackUV1Offset_ = -stackArgPos_ - 8;
#endif
// We can throw these away right off if there are no mips.
@@ -296,12 +296,12 @@ NearestFunc SamplerJitCache::CompileNearest(const SamplerID &id) {
regCache_.ForceRelease(RegCache::GEN_ARG_TEXPTR_PTR);
X64Reg uReg = regCache_.Alloc(RegCache::GEN_ARG_U);
MOV(32, R(uReg), MDisp(RSP, stackArgPos_ + stackFracUV1Offset_ + 0));
MOV(32, R(uReg), MDisp(RSP, stackArgPos_ + stackUV1Offset_ + 0));
regCache_.Unlock(uReg, RegCache::GEN_ARG_U);
regCache_.ForceRetain(RegCache::GEN_ARG_U);
X64Reg vReg = regCache_.Alloc(RegCache::GEN_ARG_V);
MOV(32, R(vReg), MDisp(RSP, stackArgPos_ + stackFracUV1Offset_ + 4));
MOV(32, R(vReg), MDisp(RSP, stackArgPos_ + stackUV1Offset_ + 4));
regCache_.Unlock(vReg, RegCache::GEN_ARG_V);
regCache_.ForceRetain(RegCache::GEN_ARG_V);
@@ -529,8 +529,8 @@ LinearFunc SamplerJitCache::CompileLinear(const SamplerID &id) {
// Positions: stackArgPos_+0=src, stackArgPos_+8=bufw, stackArgPos_+16=level, stackArgPos_+24=levelFrac
stackIDOffset_ = 32;
// Store frac UV in the shadow space right before the args.
stackFracUV1Offset_ = -8;
// If needed, we could store UV1 data in shadow space, but we no longer due.
stackUV1Offset_ = -8;
#else
stackArgPos_ = 0;
stackArgPos_ += WriteProlog(0, {}, { R15, R14, R13, R12 });
@@ -538,17 +538,13 @@ LinearFunc SamplerJitCache::CompileLinear(const SamplerID &id) {
stackIDOffset_ = 8;
// Use the red zone.
stackFracUV1Offset_ = -stackArgPos_ - 8;
stackUV1Offset_ = -stackArgPos_ - 8;
#endif
// This is what we'll put in them, anyway...
if (nearest != nullptr) {
regCache_.ChangeReg(R13, RegCache::GEN_ARG_FRAC_V);
regCache_.ChangeReg(R12, RegCache::GEN_ARG_FRAC_U);
} else {
// If we don't need to preserve across the CALL, try to avoid saving regs.
regCache_.ChangeReg(R11, RegCache::GEN_ARG_FRAC_V);
regCache_.ChangeReg(R10, RegCache::GEN_ARG_FRAC_U);
regCache_.ChangeReg(XMM10, RegCache::VEC_FRAC);
regCache_.ForceRetain(RegCache::VEC_FRAC);
}
// Reserve a couple regs that the nearest CALL won't use.
@@ -807,6 +803,9 @@ LinearFunc SamplerJitCache::CompileLinear(const SamplerID &id) {
SetJumpTarget(skip);
}
if (regCache_.Has(RegCache::VEC_FRAC))
regCache_.ForceRelease(RegCache::VEC_FRAC);
// Finally, it's time to apply the texture function.
success = success && Jit_ApplyTextureFunc(id);
@@ -1279,17 +1278,16 @@ bool SamplerJitCache::Jit_BlendQuad(const SamplerID &id, bool level1) {
// Next up, we want to multiply and add using a repeated TB frac pair.
// That's (0x10 - frac_v) in byte 1, frac_v in byte 2, repeating.
X64Reg fracReg = regCache_.Alloc(RegCache::VEC_TEMP0);
X64Reg allFracReg = regCache_.Find(RegCache::VEC_FRAC);
X64Reg zeroReg = GetZeroVec();
if (level1) {
MOVD_xmm(fracReg, MDisp(RSP, stackArgPos_ + stackFracUV1Offset_ + 4));
PSHUFLW(fracReg, R(allFracReg), _MM_SHUFFLE(3, 3, 3, 3));
} else {
X64Reg fracVReg = regCache_.Find(RegCache::GEN_ARG_FRAC_V);
MOVD_xmm(fracReg, R(fracVReg));
regCache_.Unlock(fracVReg, RegCache::GEN_ARG_FRAC_V);
regCache_.ForceRelease(RegCache::GEN_ARG_FRAC_V);
PSHUFLW(fracReg, R(allFracReg), _MM_SHUFFLE(1, 1, 1, 1));
}
PSHUFB(fracReg, R(zeroReg));
regCache_.Unlock(zeroReg, RegCache::VEC_ZERO);
regCache_.Unlock(allFracReg, RegCache::VEC_FRAC);
// Now, inverse fracReg, then interleave into the actual multiplier.
// This gives us the repeated TB pairs we wanted.
@@ -1307,16 +1305,14 @@ bool SamplerJitCache::Jit_BlendQuad(const SamplerID &id, bool level1) {
// With that done, we need to multiply by LR, or rather 0L0R, and sum again.
// Since RRRR was all next to each other, this gives us a clean total R.
fracReg = regCache_.Alloc(RegCache::VEC_TEMP0);
allFracReg = regCache_.Find(RegCache::VEC_FRAC);
if (level1) {
MOVD_xmm(fracReg, MDisp(RSP, stackArgPos_ + stackFracUV1Offset_));
PSHUFLW(fracReg, R(allFracReg), _MM_SHUFFLE(2, 2, 2, 2));
} else {
X64Reg fracUReg = regCache_.Find(RegCache::GEN_ARG_FRAC_U);
MOVD_xmm(fracReg, R(fracUReg));
regCache_.Unlock(fracUReg, RegCache::GEN_ARG_FRAC_U);
regCache_.ForceRelease(RegCache::GEN_ARG_FRAC_U);
// We can ignore the high bits, since we'll interleave those away anyway.
PSHUFLW(fracReg, R(allFracReg), _MM_SHUFFLE(0, 0, 0, 0));
}
// We can ignore the high bits, since we'll interleave those away anyway.
PSHUFLW(fracReg, R(fracReg), _MM_SHUFFLE(0, 0, 0, 0));
regCache_.Unlock(allFracReg, RegCache::VEC_FRAC);
// Again, we're inversing into an interleaved multiplier. L is the inversed one.
// 0L0R is (0x10 - frac_u), frac_u - 2x16 repeated four times.
@@ -1372,16 +1368,14 @@ bool SamplerJitCache::Jit_BlendQuad(const SamplerID &id, bool level1) {
// Grab frac_u and spread to lower (L) lanes.
X64Reg fracReg = regCache_.Alloc(RegCache::VEC_TEMP2);
X64Reg allFracReg = regCache_.Find(RegCache::VEC_FRAC);
X64Reg fracMulReg = regCache_.Alloc(RegCache::VEC_TEMP3);
if (level1) {
MOVD_xmm(fracReg, MDisp(RSP, stackArgPos_ + stackFracUV1Offset_));
PSHUFLW(fracReg, R(allFracReg), _MM_SHUFFLE(2, 2, 2, 2));
} else {
X64Reg fracUReg = regCache_.Find(RegCache::GEN_ARG_FRAC_U);
MOVD_xmm(fracReg, R(fracUReg));
regCache_.Unlock(fracUReg, RegCache::GEN_ARG_FRAC_U);
regCache_.ForceRelease(RegCache::GEN_ARG_FRAC_U);
PSHUFLW(fracReg, R(allFracReg), _MM_SHUFFLE(0, 0, 0, 0));
}
PSHUFLW(fracReg, R(fracReg), _MM_SHUFFLE(0, 0, 0, 0));
regCache_.Unlock(allFracReg, RegCache::VEC_FRAC);
// Now subtract 0x10 - frac_u in the L lanes only: 00000000 LLLLLLLL.
MOVDQA(fracMulReg, M(const10Low_));
PSUBW(fracMulReg, R(fracReg));
@@ -1397,17 +1391,15 @@ bool SamplerJitCache::Jit_BlendQuad(const SamplerID &id, bool level1) {
// Time for frac_v. This time, we want it in all 8 lanes.
fracReg = regCache_.Alloc(RegCache::VEC_TEMP2);
allFracReg = regCache_.Find(RegCache::VEC_FRAC);
X64Reg fracTopReg = regCache_.Alloc(RegCache::VEC_TEMP3);
if (level1) {
MOVD_xmm(fracReg, MDisp(RSP, stackArgPos_ + stackFracUV1Offset_ + 4));
PSHUFLW(fracReg, R(allFracReg), _MM_SHUFFLE(3, 3, 3, 3));
} else {
X64Reg fracVReg = regCache_.Find(RegCache::GEN_ARG_FRAC_V);
MOVD_xmm(fracReg, R(fracVReg));
regCache_.Unlock(fracVReg, RegCache::GEN_ARG_FRAC_V);
regCache_.ForceRelease(RegCache::GEN_ARG_FRAC_V);
PSHUFLW(fracReg, R(allFracReg), _MM_SHUFFLE(2, 2, 2, 2));
}
PSHUFLW(fracReg, R(fracReg), _MM_SHUFFLE(0, 0, 0, 0));
PSHUFD(fracReg, R(fracReg), _MM_SHUFFLE(0, 0, 0, 0));
regCache_.Unlock(allFracReg, RegCache::VEC_FRAC);
// Now, inverse fracReg into fracTopReg for the top row.
MOVDQA(fracTopReg, M(const10All16_));
@@ -2486,8 +2478,8 @@ bool SamplerJitCache::Jit_GetTexelCoords(const SamplerID &id) {
applyClampWrap(vReg, id.clampT, true, true);
// Okay, now stuff them on the stack - we'll load them again later.
MOV(32, MDisp(RSP, stackArgPos_ + stackFracUV1Offset_ + 0), R(uReg));
MOV(32, MDisp(RSP, stackArgPos_ + stackFracUV1Offset_ + 4), R(vReg));
MOV(32, MDisp(RSP, stackArgPos_ + stackUV1Offset_ + 0), R(uReg));
MOV(32, MDisp(RSP, stackArgPos_ + stackUV1Offset_ + 4), R(vReg));
// And then the given level.
// Note: for non-SSE4, this must be in S/T order.
@@ -2656,36 +2648,19 @@ bool SamplerJitCache::Jit_GetTexelCoordsQuad(const SamplerID &id) {
regCache_.ForceRelease(RegCache::GEN_ARG_X);
regCache_.ForceRelease(RegCache::GEN_ARG_Y);
// We do want the fraction, though, so extract that.
X64Reg fracUReg = regCache_.Find(RegCache::GEN_ARG_FRAC_U);
X64Reg fracVReg = regCache_.Find(RegCache::GEN_ARG_FRAC_V);
X64Reg fracExtractReg = regCache_.Alloc(RegCache::VEC_TEMP0);
// We do want the fraction, though, so extract that to an XMM for later.
X64Reg allFracReg = INVALID_REG;
if (regCache_.Has(RegCache::VEC_FRAC))
allFracReg = regCache_.Find(RegCache::VEC_FRAC);
else
allFracReg = regCache_.Alloc(RegCache::VEC_FRAC);
// We only want the four bits after the first four, though.
PSLLD(fracExtractReg, sReg, 24);
PSRLD(fracExtractReg, 28);
// Okay, grab the regs.
if (cpu_info.bSSE4_1) {
MOVD_xmm(R(fracUReg), fracExtractReg);
PEXTRD(R(fracVReg), fracExtractReg, 1);
} else {
MOVD_xmm(R(fracUReg), fracExtractReg);
PSRLDQ(fracExtractReg, 4);
MOVD_xmm(R(fracVReg), fracExtractReg);
}
// And store frac U1/V1 on the stack, if we have mips.
if (id.hasAnyMips) {
if (cpu_info.bSSE4_1) {
// They're next to each other, so one extract is enough.
PEXTRQ(MDisp(RSP, stackArgPos_ + stackFracUV1Offset_), fracExtractReg, 1);
} else {
// We already shifted 4 for fracVReg, shift again and store.
PSRLDQ(fracExtractReg, 4);
MOVQ_xmm(MDisp(RSP, stackArgPos_ + stackFracUV1Offset_), fracExtractReg);
}
}
regCache_.Release(fracExtractReg, RegCache::VEC_TEMP0);
regCache_.Unlock(fracUReg, RegCache::GEN_ARG_FRAC_U);
regCache_.Unlock(fracVReg, RegCache::GEN_ARG_FRAC_V);
PSLLD(allFracReg, sReg, 24);
PSRLD(allFracReg, 28);
// It's convenient later if this is in the low words only.
PACKSSDW(allFracReg, R(allFracReg));
regCache_.Unlock(allFracReg, RegCache::VEC_FRAC);
regCache_.ForceRetain(RegCache::VEC_FRAC);
// With those extracted, we can now get rid of the fractional bits.
PSRAD(sReg, 8);