mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-14 10:09:32 +01:00
Merge pull request #9674 from unknownbrackets/vertexjit
Implement a few x86 vertexjit optimizations
This commit is contained in:
commit
f06daba448
1 file changed
+53
-81
@@ -890,71 +890,23 @@ static const u32 MEMORY_ALIGNED16(nibbles[4]) = { 0x0f0f0f0f, 0x0f0f0f0f, 0x0f0f
|
||||
static const u32 MEMORY_ALIGNED16(color4444mask[4]) = { 0xf00ff00f, 0xf00ff00f, 0xf00ff00f, 0xf00ff00f, };
|
||||
|
||||
void VertexDecoderJitCache::Jit_Color4444() {
|
||||
// Needs benchmarking. A bit wasteful by only using 1 SSE lane.
|
||||
#if 0
|
||||
// This over-reads slightly, but we assume pos or another component follows anyway.
|
||||
MOVD_xmm(fpScratchReg, MDisp(srcReg, dec_->coloff));
|
||||
// Spread to RGBA -> R00GB00A.
|
||||
PUNPCKLBW(fpScratchReg, R(fpScratchReg));
|
||||
PAND(fpScratchReg, M(color4444mask));
|
||||
MOVSS(fpScratchReg2, R(fpScratchReg));
|
||||
MOVSS(fpScratchReg3, R(fpScratchReg));
|
||||
// Create 0R000B00 and 00G000A0.
|
||||
PSRLW(fpScratchReg2, 4);
|
||||
PSLLW(fpScratchReg3, 4);
|
||||
// Combine for the complete set: RRGGBBAA.
|
||||
POR(fpScratchReg, R(fpScratchReg2));
|
||||
POR(fpScratchReg, R(fpScratchReg3));
|
||||
MOVD_xmm(MDisp(dstReg, dec_->decFmt.c0off), fpScratchReg);
|
||||
return;
|
||||
#elif 0
|
||||
// Alternate approach
|
||||
MOVD_xmm(XMM3, MDisp(srcReg, dec_->coloff));
|
||||
MOVAPS(XMM2, R(XMM3));
|
||||
MOVAPS(XMM1, M(nibbles));
|
||||
PSLLD(XMM2, 4);
|
||||
PAND(XMM3, R(XMM1));
|
||||
PAND(XMM2, R(XMM1));
|
||||
PSRLD(XMM2, 4);
|
||||
PXOR(XMM1, R(XMM1));
|
||||
PUNPCKLBW(XMM2, R(XMM1));
|
||||
PUNPCKLBW(XMM3, R(XMM1));
|
||||
PSLLD(XMM2, 4);
|
||||
POR(XMM3, R(XMM2));
|
||||
MOVAPS(XMM2, R(XMM3));
|
||||
PSLLD(XMM2, 4);
|
||||
POR(XMM3, R(XMM2));
|
||||
MOVD_xmm(MDisp(dstReg, dec_->decFmt.c0off), XMM3);
|
||||
return;
|
||||
#endif
|
||||
MOVD_xmm(R(tempReg1), fpScratchReg);
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.c0off), R(tempReg1));
|
||||
|
||||
MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->coloff));
|
||||
|
||||
// Pick out A and B, and space them out by a nibble.
|
||||
MOV(32, R(tempReg2), R(tempReg1));
|
||||
MOV(32, R(tempReg3), R(tempReg1));
|
||||
AND(32, R(tempReg2), Imm32(0x0000F000));
|
||||
AND(32, R(tempReg3), Imm32(0x00000F00));
|
||||
SHL(32, R(tempReg2), Imm8(4));
|
||||
OR(32, R(tempReg2), R(tempReg3));
|
||||
|
||||
// Now grab R and G.
|
||||
MOV(32, R(tempReg3), R(tempReg1));
|
||||
AND(32, R(tempReg1), Imm32(0x0000000F));
|
||||
AND(32, R(tempReg3), Imm32(0x000000F0));
|
||||
|
||||
// Currently: 000A0B00, so let's shift once so G is spaced out.
|
||||
SHL(32, R(tempReg2), Imm8(4));
|
||||
OR(32, R(tempReg2), R(tempReg3));
|
||||
|
||||
// Now: 00A0B0G0, so shift it once more to add R at the bottom.
|
||||
SHL(32, R(tempReg2), Imm8(4));
|
||||
OR(32, R(tempReg2), R(tempReg1));
|
||||
|
||||
// Now we just need to duplicate the nibbles.
|
||||
MOV(32, R(tempReg3), R(tempReg2));
|
||||
SHL(32, R(tempReg3), Imm8(4));
|
||||
OR(32, R(tempReg2), R(tempReg3));
|
||||
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.c0off), R(tempReg2));
|
||||
|
||||
CMP(32, R(tempReg2), Imm32(0xFF000000));
|
||||
CMP(32, R(tempReg1), Imm32(0xFF000000));
|
||||
FixupBranch skip = J_CC(CC_AE, false);
|
||||
MOV(8, M(&gstate_c.vertexFullAlpha), Imm8(0));
|
||||
SetJumpTarget(skip);
|
||||
@@ -1269,12 +1221,19 @@ void VertexDecoderJitCache::Jit_NormalS16() {
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_NormalFloat() {
|
||||
MOV(32, R(tempReg1), MDisp(srcReg, dec_->nrmoff));
|
||||
MOV(32, R(tempReg2), MDisp(srcReg, dec_->nrmoff + 4));
|
||||
MOV(32, R(tempReg3), MDisp(srcReg, dec_->nrmoff + 8));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff), R(tempReg1));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff + 4), R(tempReg2));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff + 8), R(tempReg3));
|
||||
if (cpu_info.Mode64bit) {
|
||||
MOV(64, R(tempReg1), MDisp(srcReg, dec_->nrmoff));
|
||||
MOV(32, R(tempReg3), MDisp(srcReg, dec_->nrmoff + 8));
|
||||
MOV(64, MDisp(dstReg, dec_->decFmt.posoff), R(tempReg1));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.posoff + 8), R(tempReg3));
|
||||
} else {
|
||||
MOV(32, R(tempReg1), MDisp(srcReg, dec_->nrmoff));
|
||||
MOV(32, R(tempReg2), MDisp(srcReg, dec_->nrmoff + 4));
|
||||
MOV(32, R(tempReg3), MDisp(srcReg, dec_->nrmoff + 8));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff), R(tempReg1));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff + 4), R(tempReg2));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.nrmoff + 8), R(tempReg3));
|
||||
}
|
||||
}
|
||||
|
||||
// This could be a bit shorter with AVX 3-operand instructions and FMA.
|
||||
@@ -1313,7 +1272,7 @@ void VertexDecoderJitCache::Jit_NormalFloatSkin() {
|
||||
// Through expands into floats, always. Might want to look at changing this.
|
||||
void VertexDecoderJitCache::Jit_PosS8Through() {
|
||||
DEBUG_LOG_REPORT_ONCE(vertexS8Through, G3D, "Using S8 positions in throughmode");
|
||||
// TODO: SIMD
|
||||
// SIMD doesn't really matter since this isn't useful on hardware.
|
||||
for (int i = 0; i < 3; i++) {
|
||||
MOVSX(32, 8, tempReg1, MDisp(srcReg, dec_->posoff + i));
|
||||
CVTSI2SS(fpScratchReg, R(tempReg1));
|
||||
@@ -1323,15 +1282,25 @@ void VertexDecoderJitCache::Jit_PosS8Through() {
|
||||
|
||||
// Through expands into floats, always. Might want to look at changing this.
|
||||
void VertexDecoderJitCache::Jit_PosS16Through() {
|
||||
MOVSX(32, 16, tempReg1, MDisp(srcReg, dec_->posoff));
|
||||
MOVSX(32, 16, tempReg2, MDisp(srcReg, dec_->posoff + 2));
|
||||
MOVZX(32, 16, tempReg3, MDisp(srcReg, dec_->posoff + 4)); // NOTE: MOVZX
|
||||
CVTSI2SS(fpScratchReg, R(tempReg1));
|
||||
MOVSS(MDisp(dstReg, dec_->decFmt.posoff), fpScratchReg);
|
||||
CVTSI2SS(fpScratchReg, R(tempReg2));
|
||||
MOVSS(MDisp(dstReg, dec_->decFmt.posoff + 4), fpScratchReg);
|
||||
CVTSI2SS(fpScratchReg, R(tempReg3));
|
||||
MOVSS(MDisp(dstReg, dec_->decFmt.posoff + 8), fpScratchReg);
|
||||
if (cpu_info.bSSE4_1) {
|
||||
MOVD_xmm(fpScratchReg, MDisp(srcReg, dec_->posoff));
|
||||
MOVZX(32, 16, tempReg3, MDisp(srcReg, dec_->posoff + 4));
|
||||
MOVD_xmm(fpScratchReg2, R(tempReg3));
|
||||
PMOVSXWD(fpScratchReg, R(fpScratchReg));
|
||||
PUNPCKLQDQ(fpScratchReg, R(fpScratchReg2));
|
||||
CVTDQ2PS(fpScratchReg, R(fpScratchReg));
|
||||
MOVUPS(MDisp(dstReg, dec_->decFmt.posoff), fpScratchReg);
|
||||
} else {
|
||||
MOVSX(32, 16, tempReg1, MDisp(srcReg, dec_->posoff));
|
||||
MOVSX(32, 16, tempReg2, MDisp(srcReg, dec_->posoff + 2));
|
||||
MOVZX(32, 16, tempReg3, MDisp(srcReg, dec_->posoff + 4)); // NOTE: MOVZX
|
||||
CVTSI2SS(fpScratchReg, R(tempReg1));
|
||||
MOVSS(MDisp(dstReg, dec_->decFmt.posoff), fpScratchReg);
|
||||
CVTSI2SS(fpScratchReg, R(tempReg2));
|
||||
MOVSS(MDisp(dstReg, dec_->decFmt.posoff + 4), fpScratchReg);
|
||||
CVTSI2SS(fpScratchReg, R(tempReg3));
|
||||
MOVSS(MDisp(dstReg, dec_->decFmt.posoff + 8), fpScratchReg);
|
||||
}
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_PosS8() {
|
||||
@@ -1346,12 +1315,19 @@ void VertexDecoderJitCache::Jit_PosS16() {
|
||||
|
||||
// Just copy 12 bytes.
|
||||
void VertexDecoderJitCache::Jit_PosFloat() {
|
||||
MOV(32, R(tempReg1), MDisp(srcReg, dec_->posoff));
|
||||
MOV(32, R(tempReg2), MDisp(srcReg, dec_->posoff + 4));
|
||||
MOV(32, R(tempReg3), MDisp(srcReg, dec_->posoff + 8));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.posoff), R(tempReg1));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.posoff + 4), R(tempReg2));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.posoff + 8), R(tempReg3));
|
||||
if (cpu_info.Mode64bit) {
|
||||
MOV(64, R(tempReg1), MDisp(srcReg, dec_->posoff));
|
||||
MOV(32, R(tempReg3), MDisp(srcReg, dec_->posoff + 8));
|
||||
MOV(64, MDisp(dstReg, dec_->decFmt.posoff), R(tempReg1));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.posoff + 8), R(tempReg3));
|
||||
} else {
|
||||
MOV(32, R(tempReg1), MDisp(srcReg, dec_->posoff));
|
||||
MOV(32, R(tempReg2), MDisp(srcReg, dec_->posoff + 4));
|
||||
MOV(32, R(tempReg3), MDisp(srcReg, dec_->posoff + 8));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.posoff), R(tempReg1));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.posoff + 4), R(tempReg2));
|
||||
MOV(32, MDisp(dstReg, dec_->decFmt.posoff + 8), R(tempReg3));
|
||||
}
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_PosS8Skin() {
|
||||
@@ -1364,7 +1340,6 @@ void VertexDecoderJitCache::Jit_PosS16Skin() {
|
||||
Jit_WriteMatrixMul(dec_->decFmt.posoff, true);
|
||||
}
|
||||
|
||||
// Just copy 12 bytes.
|
||||
void VertexDecoderJitCache::Jit_PosFloatSkin() {
|
||||
MOVUPS(XMM3, MDisp(srcReg, dec_->posoff));
|
||||
Jit_WriteMatrixMul(dec_->decFmt.posoff, true);
|
||||
@@ -1493,7 +1468,6 @@ void VertexDecoderJitCache::Jit_AnyS8Morph(int srcoff, int dstoff) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Is it okay that we're over-writing by 4 bytes? Probably...
|
||||
MOVUPS(MDisp(dstReg, dstoff), fpScratchReg);
|
||||
}
|
||||
|
||||
@@ -1532,7 +1506,6 @@ void VertexDecoderJitCache::Jit_AnyS16Morph(int srcoff, int dstoff) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Is it okay that we're over-writing by 4 bytes? Probably...
|
||||
MOVUPS(MDisp(dstReg, dstoff), fpScratchReg);
|
||||
}
|
||||
|
||||
@@ -1554,7 +1527,6 @@ void VertexDecoderJitCache::Jit_AnyFloatMorph(int srcoff, int dstoff) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Is it okay that we're over-writing by 4 bytes? Probably...
|
||||
MOVUPS(MDisp(dstReg, dstoff), fpScratchReg);
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user