mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Merge pull request #20644 from lrzlin/loong-morph
loongarch: Implement Morph in VertexJIT & QuickTexHashLSX
This commit is contained in:
@@ -183,6 +183,45 @@ static u32 QuickTexHashNEON(const void *checkp, u32 size) {
|
||||
|
||||
#endif // PPSSPP_ARCH(ARM_NEON)
|
||||
|
||||
#if PPSSPP_ARCH(LOONGARCH64_LSX)
|
||||
|
||||
alignas(16) static const u16 QuickTexHashInitial[8] = { 0xc00bU, 0x9bd9U, 0x4b73U, 0xb651U, 0x4d9bU, 0x4309U, 0x0083U, 0x0001U };
|
||||
|
||||
static u32 QuickTexHashLSX(const void *checkp, u32 size) {
|
||||
u32 check = 0;
|
||||
|
||||
if (((intptr_t)checkp & 0xf) == 0 && (size & 0x3f) == 0) {
|
||||
__m128i cursor = __lsx_vrepli_d(0);
|
||||
__m128i cursor2 = __lsx_vld(QuickTexHashInitial, 0);
|
||||
__m128i update = __lsx_vreplgr2vr_h(0x2455U);
|
||||
const __m128i *p = (const __m128i *)checkp;
|
||||
for (u32 i = 0; i < size / 16; i += 4) {
|
||||
__m128i chunk = __lsx_vmul_h(__lsx_vld(&p[i], 0), cursor2);
|
||||
cursor = __lsx_vadd_h(cursor, chunk);
|
||||
cursor = __lsx_vxor_v(cursor, __lsx_vld(&p[i + 1], 0));
|
||||
cursor = __lsx_vadd_w(cursor, __lsx_vld(&p[i + 2], 0));
|
||||
chunk = __lsx_vmul_h(__lsx_vld(&p[i + 3], 0), cursor2);
|
||||
cursor = __lsx_vxor_v(cursor, chunk);
|
||||
cursor2 = __lsx_vadd_h(cursor2, update);
|
||||
}
|
||||
cursor = __lsx_vadd_w(cursor, cursor2);
|
||||
// Add the four parts into the low i32.
|
||||
cursor = __lsx_vadd_w(cursor, __lsx_vbsrl_v(cursor, 8));
|
||||
cursor = __lsx_vadd_w(cursor, __lsx_vbsrl_v(cursor, 4));
|
||||
check = __lsx_vpickve2gr_w(cursor, 0);
|
||||
} else {
|
||||
const u32 *p = (const u32 *)checkp;
|
||||
for (u32 i = 0; i < size / 8; ++i) {
|
||||
check += *p++;
|
||||
check ^= *p++;
|
||||
}
|
||||
}
|
||||
|
||||
return check;
|
||||
}
|
||||
|
||||
#endif // PPSSPP_ARCH(LOONGARCH64_LSX)
|
||||
|
||||
// Masks to downalign bufw to 16 bytes, and wrap at 2048.
|
||||
static const u32 textureAlignMask16[16] = {
|
||||
0x7FF & ~(((8 * 16) / 16) - 1), //GE_TFMT_5650,
|
||||
@@ -278,6 +317,8 @@ u32 StableQuickTexHash(const void *checkp, u32 size) {
|
||||
return QuickTexHashSSE2(checkp, size);
|
||||
#elif PPSSPP_ARCH(ARM_NEON)
|
||||
return QuickTexHashNEON(checkp, size);
|
||||
#elif PPSSPP_ARCH(LOONGARCH64_LSX)
|
||||
return QuickTexHashLSX(checkp, size);
|
||||
#else
|
||||
return QuickTexHashNonSSE(checkp, size);
|
||||
#endif
|
||||
|
||||
@@ -66,6 +66,8 @@ static const LoongArch64Reg fpScratchReg4 = F7;
|
||||
|
||||
static const LoongArch64Reg lsxScratchReg = V2;
|
||||
static const LoongArch64Reg lsxScratchReg2 = V3;
|
||||
static const LoongArch64Reg lsxScratchReg3 = V10;
|
||||
static const LoongArch64Reg lsxScratchReg4 = V11;
|
||||
|
||||
static const LoongArch64Reg fpSrc[4] = {F2, F3, F10, F11};
|
||||
|
||||
@@ -109,6 +111,13 @@ static const JitLookup jitLookup[] = {
|
||||
{&VertexDecoder::Step_TcFloatThrough, &VertexDecoderJitCache::Jit_TcFloatThrough},
|
||||
{&VertexDecoder::Step_TcU16ThroughToFloat, &VertexDecoderJitCache::Jit_TcU16ThroughToFloat},
|
||||
|
||||
{&VertexDecoder::Step_TcU8MorphToFloat, &VertexDecoderJitCache::Jit_TcU8MorphToFloat},
|
||||
{&VertexDecoder::Step_TcU16MorphToFloat, &VertexDecoderJitCache::Jit_TcU16MorphToFloat},
|
||||
{&VertexDecoder::Step_TcFloatMorph, &VertexDecoderJitCache::Jit_TcFloatMorph},
|
||||
{&VertexDecoder::Step_TcU8PrescaleMorph, &VertexDecoderJitCache::Jit_TcU8PrescaleMorph},
|
||||
{&VertexDecoder::Step_TcU16PrescaleMorph, &VertexDecoderJitCache::Jit_TcU16PrescaleMorph},
|
||||
{&VertexDecoder::Step_TcFloatPrescaleMorph, &VertexDecoderJitCache::Jit_TcFloatPrescaleMorph},
|
||||
|
||||
{&VertexDecoder::Step_NormalS8, &VertexDecoderJitCache::Jit_NormalS8},
|
||||
{&VertexDecoder::Step_NormalS16, &VertexDecoderJitCache::Jit_NormalS16},
|
||||
{&VertexDecoder::Step_NormalFloat, &VertexDecoderJitCache::Jit_NormalFloat},
|
||||
@@ -134,20 +143,24 @@ static const JitLookup jitLookup[] = {
|
||||
{&VertexDecoder::Step_PosS16Skin, &VertexDecoderJitCache::Jit_PosS16Skin},
|
||||
{&VertexDecoder::Step_PosFloatSkin, &VertexDecoderJitCache::Jit_PosFloatSkin},
|
||||
|
||||
/*
|
||||
{&VertexDecoder::Step_NormalS8Morph, &VertexDecoderJitCache::Jit_NormalS8Morph},
|
||||
{&VertexDecoder::Step_NormalS16Morph, &VertexDecoderJitCache::Jit_NormalS16Morph},
|
||||
{&VertexDecoder::Step_NormalFloatMorph, &VertexDecoderJitCache::Jit_NormalFloatMorph},
|
||||
{&VertexDecoder::Step_NormalS8MorphSkin, &VertexDecoderJitCache::Jit_NormalS8MorphSkin},
|
||||
{&VertexDecoder::Step_NormalS16MorphSkin, &VertexDecoderJitCache::Jit_NormalS16MorphSkin},
|
||||
{&VertexDecoder::Step_NormalFloatMorphSkin, &VertexDecoderJitCache::Jit_NormalFloatMorphSkin},
|
||||
|
||||
{&VertexDecoder::Step_PosS8Morph, &VertexDecoderJitCache::Jit_PosS8Morph},
|
||||
{&VertexDecoder::Step_PosS16Morph, &VertexDecoderJitCache::Jit_PosS16Morph},
|
||||
{&VertexDecoder::Step_PosFloatMorph, &VertexDecoderJitCache::Jit_PosFloatMorph},
|
||||
{&VertexDecoder::Step_PosS8MorphSkin, &VertexDecoderJitCache::Jit_PosS8MorphSkin},
|
||||
{&VertexDecoder::Step_PosS16MorphSkin, &VertexDecoderJitCache::Jit_PosS16MorphSkin},
|
||||
{&VertexDecoder::Step_PosFloatMorphSkin, &VertexDecoderJitCache::Jit_PosFloatMorphSkin},
|
||||
|
||||
{&VertexDecoder::Step_Color8888Morph, &VertexDecoderJitCache::Jit_Color8888Morph},
|
||||
{&VertexDecoder::Step_Color4444Morph, &VertexDecoderJitCache::Jit_Color4444Morph},
|
||||
{&VertexDecoder::Step_Color565Morph, &VertexDecoderJitCache::Jit_Color565Morph},
|
||||
{&VertexDecoder::Step_Color5551Morph, &VertexDecoderJitCache::Jit_Color5551Morph},
|
||||
*/
|
||||
};
|
||||
|
||||
JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int32_t *jittedSize) {
|
||||
@@ -660,6 +673,197 @@ void VertexDecoderJitCache::Jit_Color5551() {
|
||||
ST_W(tempReg1, dstReg, dec_->decFmt.c0off);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_Color8888Morph() {
|
||||
LI(tempReg1, &gstate_c.morphWeights[0]);
|
||||
VXOR_V(lsxScratchReg4, lsxScratchReg4, lsxScratchReg4);
|
||||
|
||||
bool first = true;
|
||||
for (int n = 0; n < dec_->morphcount; ++n) {
|
||||
const LoongArch64Reg reg = first ? lsxScratchReg : lsxScratchReg2;
|
||||
FLD_S((LoongArch64Reg)(DecodeReg(reg) + F0), srcReg, dec_->onesize_ * n + dec_->coloff);
|
||||
|
||||
VILVL_B(reg, lsxScratchReg4, reg);
|
||||
VILVL_H(reg, lsxScratchReg4, reg);
|
||||
VFFINT_S_W(reg, reg);
|
||||
|
||||
// And now the weight.
|
||||
VLDREPL_W(lsxScratchReg3, tempReg1, n * sizeof(float));
|
||||
VFMUL_S(reg, reg, lsxScratchReg3);
|
||||
|
||||
if (!first) {
|
||||
VFADD_S(lsxScratchReg, lsxScratchReg,lsxScratchReg2);
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
Jit_WriteMorphColor(dec_->decFmt.c0off);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_Color4444Morph() {
|
||||
LI(tempReg1, &gstate_c.morphWeights[0]);
|
||||
VXOR_V(lsxScratchReg4, lsxScratchReg4, lsxScratchReg4);
|
||||
|
||||
LI(tempReg2, 0xf00ff00f); // color 4444 mask
|
||||
VREPLGR2VR_W(V8, tempReg2);
|
||||
LI(tempReg3, 255.0f / 15.0f); // by color 4444
|
||||
VREPLGR2VR_W(V9, tempReg2);
|
||||
|
||||
bool first = true;
|
||||
for (int n = 0; n < dec_->morphcount; ++n) {
|
||||
const LoongArch64Reg reg = first ? lsxScratchReg : lsxScratchReg2;
|
||||
FLD_S((LoongArch64Reg)(DecodeReg(reg) + F0), srcReg, dec_->onesize_ * n + dec_->coloff);
|
||||
VILVL_B(reg, reg, reg);
|
||||
VAND_V(reg, reg, V8);
|
||||
VEXTRINS_W(lsxScratchReg3, reg, 0);
|
||||
VSLLI_H(fpScratchReg3, fpScratchReg3, 4);
|
||||
VOR_V(reg, reg,lsxScratchReg3);
|
||||
VSRLI_W(reg, reg, 4);
|
||||
|
||||
VILVL_B(reg, lsxScratchReg4, reg);
|
||||
VILVL_H(reg, lsxScratchReg4, reg);
|
||||
|
||||
VFFINT_S_W(reg, reg);
|
||||
VFMUL_S(reg, reg, V9);
|
||||
|
||||
// And now the weight.
|
||||
VLDREPL_W(lsxScratchReg3, tempReg1, n * sizeof(float));
|
||||
VFMUL_S(reg, reg, lsxScratchReg3);
|
||||
|
||||
if (!first) {
|
||||
VFADD_S(lsxScratchReg, lsxScratchReg,lsxScratchReg2);
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
Jit_WriteMorphColor(dec_->decFmt.c0off);
|
||||
}
|
||||
|
||||
// The mask is intentionally in reverse order (but skips A.)
|
||||
alignas(16) static const u32 color565Mask[4] = { 0x0000f800, 0x000007e0, 0x0000001f, 0x00000000, };
|
||||
alignas(16) static const float byColor565[4] = { 255.0f / 31.0f, 255.0f / 63.0f, 255.0f / 31.0f, 255.0f / 1.0f, };
|
||||
|
||||
void VertexDecoderJitCache::Jit_Color565Morph() {
|
||||
LI(tempReg1, &gstate_c.morphWeights[0]);
|
||||
LI(tempReg2, &color565Mask[0]);
|
||||
VLD(V8, tempReg2, 0);
|
||||
LI(tempReg2, &byColor565[0]);
|
||||
VLD(V9, tempReg2, 0);
|
||||
|
||||
bool first = true;
|
||||
for (int n = 0; n < dec_->morphcount; ++n) {
|
||||
const LoongArch64Reg reg = first ? lsxScratchReg : lsxScratchReg3;
|
||||
// Spread it out into each lane. We end up with it reversed (R high, A low.)
|
||||
// Below, we shift out each lane from low to high and reverse them.
|
||||
VLDREPL_W(lsxScratchReg2, srcReg, dec_->onesize_ * n + dec_->coloff);
|
||||
VAND_V(lsxScratchReg2, lsxScratchReg2, V8);
|
||||
|
||||
// Alpha handled in Jit_WriteMorphColor.
|
||||
|
||||
// Blue first.
|
||||
VEXTRINS_W(reg, lsxScratchReg2, 0);
|
||||
VSRLI_W(reg, reg, 6);
|
||||
VSHUF4I_W(reg, reg, 3 << 6);
|
||||
|
||||
// Green, let's shift it into the right lane first.
|
||||
VEXTRINS_W(reg, lsxScratchReg2, 1);
|
||||
VSRLI_W(reg, reg, 5);
|
||||
VSHUF4I_W(reg, reg, (3 << 6 | 2 << 4));
|
||||
|
||||
// Last one, red.
|
||||
VEXTRINS_W(reg, lsxScratchReg2, 2);
|
||||
VFFINT_S_W(reg, reg);
|
||||
VFMUL_S(reg, reg, V9);
|
||||
|
||||
// And now the weight.
|
||||
VLDREPL_W(lsxScratchReg2, tempReg1, n * sizeof(float));
|
||||
VFMUL_S(reg, reg, lsxScratchReg2);
|
||||
|
||||
if (!first) {
|
||||
VFADD_S(fpScratchReg, fpScratchReg, fpScratchReg3);
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
Jit_WriteMorphColor(dec_->decFmt.c0off, false);
|
||||
}
|
||||
|
||||
// The mask is intentionally in reverse order.
|
||||
alignas(16) static const u32 color5551Mask[4] = { 0x00008000, 0x00007c00, 0x000003e0, 0x0000001f, };
|
||||
alignas(16) static const float byColor5551[4] = { 255.0f / 31.0f, 255.0f / 31.0f, 255.0f / 31.0f, 255.0f / 1.0f, };
|
||||
|
||||
void VertexDecoderJitCache::Jit_Color5551Morph() {
|
||||
LI(tempReg1, &gstate_c.morphWeights[0]);
|
||||
LI(tempReg2, &color5551Mask[0]);
|
||||
VLD(V8, tempReg2, 0);
|
||||
LI(tempReg2, &byColor5551[0]);
|
||||
VLD(V9, tempReg2, 0);
|
||||
|
||||
bool first = true;
|
||||
for (int n = 0; n < dec_->morphcount; ++n) {
|
||||
const LoongArch64Reg reg = first ? lsxScratchReg : lsxScratchReg3;
|
||||
// Spread it out into each lane.
|
||||
VLDREPL_W(lsxScratchReg2, srcReg, dec_->onesize_ * n + dec_->coloff);
|
||||
VAND_V(lsxScratchReg2, lsxScratchReg2, V8);
|
||||
|
||||
// Alpha first.
|
||||
VEXTRINS_W(reg, lsxScratchReg2, 0);
|
||||
VSRLI_W(reg, reg, 5);
|
||||
VSHUF4I_W(reg, reg, 0);
|
||||
|
||||
// Blue, let's shift it into the right lane first.
|
||||
VEXTRINS_W(reg, lsxScratchReg2, 1);
|
||||
VSRLI_W(reg, reg, 5);
|
||||
VSHUF4I_W(reg, reg, 3 << 6);
|
||||
|
||||
// Green.
|
||||
VEXTRINS_W(reg, lsxScratchReg2, 2);
|
||||
VSRLI_W(reg, reg, 5);
|
||||
VSHUF4I_W(reg, reg, (3 << 6 | 2 << 4));
|
||||
|
||||
// Last one, red.
|
||||
VEXTRINS_W(reg, lsxScratchReg2, 3);
|
||||
VFFINT_S_W(reg, reg);
|
||||
VFMUL_S(reg, reg, V9);
|
||||
|
||||
// And now the weight.
|
||||
VLDREPL_W(lsxScratchReg2, tempReg1, n * sizeof(float));
|
||||
VFMUL_S(reg, reg, lsxScratchReg2);
|
||||
|
||||
if (!first) {
|
||||
VFADD_S(fpScratchReg, fpScratchReg, fpScratchReg3);
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
Jit_WriteMorphColor(dec_->decFmt.c0off);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_WriteMorphColor(int outOff, bool checkAlpha) {
|
||||
// Pack back into a u32, with saturation.
|
||||
VFTINT_W_S(lsxScratchReg, lsxScratchReg);
|
||||
VSSRLNI_H_W(lsxScratchReg, lsxScratchReg, 0);
|
||||
VSSRLNI_BU_H(lsxScratchReg, lsxScratchReg, 0);
|
||||
VPICKVE2GR_W(tempReg1, lsxScratchReg, 0);
|
||||
|
||||
// TODO: Could be optimize with a SLLI on fullAlphaReg
|
||||
SLLI_D(tempReg2, fullAlphaReg, 24);
|
||||
if (checkAlpha) {
|
||||
SLTU(tempReg3, tempReg1, tempReg2);
|
||||
FixupBranch skip = BEQZ(tempReg3);
|
||||
XOR(fullAlphaReg, fullAlphaReg, fullAlphaReg);
|
||||
SetJumpTarget(skip);
|
||||
} else {
|
||||
// Force alpha to full if we're not checking it.
|
||||
OR(tempReg1, tempReg1, tempReg2);
|
||||
}
|
||||
|
||||
ST_W(tempReg1, dstReg, outOff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcU16ThroughToFloat() {
|
||||
LD_HU(tempReg1, srcReg, dec_->tcoff + 0);
|
||||
LD_HU(tempReg2, srcReg, dec_->tcoff + 2);
|
||||
@@ -739,6 +943,82 @@ void VertexDecoderJitCache::Jit_TcFloatPrescale() {
|
||||
FST_D(fpSrc[0], dstReg, dec_->decFmt.uvoff); // save the lower 64-bit of lsxScratchReg
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcAnyMorph(int bits) {
|
||||
LI(tempReg1, &gstate_c.morphWeights[0]);
|
||||
VXOR_V(lsxScratchReg4, lsxScratchReg4, lsxScratchReg4);
|
||||
|
||||
bool first = true;
|
||||
for (int n = 0; n < dec_->morphcount; ++n) {
|
||||
const LoongArch64Reg reg = first ? lsxScratchReg : lsxScratchReg2;
|
||||
|
||||
// Load the actual values and convert to float.
|
||||
if (bits == 32) {
|
||||
// Two floats
|
||||
FLD_D((LoongArch64Reg)(DecodeReg(reg) + F0), srcReg, dec_->onesize_ * n + dec_->tcoff);
|
||||
} else {
|
||||
if (bits == 8) {
|
||||
LD_HU(tempReg2, srcReg, dec_->onesize_ * n + dec_->tcoff);
|
||||
VINSGR2VR_W(reg, tempReg2, 0);
|
||||
VILVL_B(reg, lsxScratchReg4, reg);
|
||||
} else {
|
||||
FLD_S((LoongArch64Reg)(DecodeReg(reg) + F0), srcReg, dec_->onesize_ * n + dec_->tcoff);
|
||||
}
|
||||
|
||||
VILVL_H(reg, lsxScratchReg4, reg);
|
||||
VFFINT_S_W(reg, reg);
|
||||
}
|
||||
|
||||
// And now scale by the weight.
|
||||
VLDREPL_W(lsxScratchReg3, tempReg1, n * sizeof(float));
|
||||
VFMUL_S(reg, reg, lsxScratchReg3);
|
||||
|
||||
if (!first) {
|
||||
VFADD_S(lsxScratchReg, lsxScratchReg,lsxScratchReg2);
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcU8MorphToFloat() {
|
||||
Jit_TcAnyMorph(8);
|
||||
// They were all added (weighted) pre-normalize, we normalize once here.
|
||||
VFMUL_S(lsxScratchReg, lsxScratchReg, by128LSX);
|
||||
FST_D(fpSrc[0], dstReg, dec_->decFmt.uvoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcU16MorphToFloat() {
|
||||
Jit_TcAnyMorph(16);
|
||||
// They were all added (weighted) pre-normalize, we normalize once here.
|
||||
VFMUL_S(lsxScratchReg, lsxScratchReg, by32768LSX);
|
||||
FST_D(fpSrc[0], dstReg, dec_->decFmt.uvoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcFloatMorph() {
|
||||
Jit_TcAnyMorph(32);
|
||||
FST_D(fpSrc[0], dstReg, dec_->decFmt.uvoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcU8PrescaleMorph() {
|
||||
Jit_TcAnyMorph(8);
|
||||
// The scale takes into account the u8 normalization.
|
||||
VFMADD_S(lsxScratchReg, lsxScratchReg, lsxScaleOffsetReg, lsxOffsetScaleReg);
|
||||
FST_D(fpSrc[0], dstReg, dec_->decFmt.uvoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcU16PrescaleMorph() {
|
||||
Jit_TcAnyMorph(16);
|
||||
// The scale takes into account the u16 normalization.
|
||||
VFMADD_S(lsxScratchReg, lsxScratchReg, lsxScaleOffsetReg, lsxOffsetScaleReg);
|
||||
FST_D(fpSrc[0], dstReg, dec_->decFmt.uvoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_TcFloatPrescaleMorph() {
|
||||
Jit_TcAnyMorph(32);
|
||||
VFMADD_S(lsxScratchReg, lsxScratchReg, lsxScaleOffsetReg, lsxOffsetScaleReg);
|
||||
FST_D(fpSrc[0], dstReg, dec_->decFmt.uvoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_PosS8() {
|
||||
Jit_AnyS8ToFloat(dec_->posoff);
|
||||
VST(lsxScratchReg, dstReg, dec_->decFmt.posoff);
|
||||
@@ -881,4 +1161,136 @@ void VertexDecoderJitCache::Jit_WriteMatrixMul(int outOff, bool pos) {
|
||||
VST(accLSX, dstReg, outOff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_AnyS8Morph(int srcoff, int dstoff) {
|
||||
LI(tempReg1, &gstate_c.morphWeights[0]);
|
||||
|
||||
// Sum into lsxScratchReg.
|
||||
bool first = true;
|
||||
for (int n = 0; n < dec_->morphcount; ++n) {
|
||||
const LoongArch64Reg reg = first ? lsxScratchReg : lsxScratchReg2;
|
||||
// Okay, first convert to floats.
|
||||
FLD_S((LoongArch64Reg)(DecodeReg(reg) + F0), srcReg, dec_->onesize_ * n + srcoff);
|
||||
VSLLWIL_H_B(reg, reg, 0);
|
||||
VSLLWIL_W_H(reg, reg, 0);
|
||||
|
||||
VFFINT_S_W(reg, reg);
|
||||
|
||||
// Now, It's time to multiply by the weight and 1.0f/128.0f.
|
||||
VLDREPL_W(lsxScratchReg3, tempReg1, sizeof(float) * n);
|
||||
VFMUL_S(lsxScratchReg3, lsxScratchReg3, by128LSX);
|
||||
VFMUL_S(reg, reg, lsxScratchReg3);
|
||||
|
||||
if (!first) {
|
||||
VFADD_S(lsxScratchReg, lsxScratchReg, lsxScratchReg2);
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (dstoff >= 0)
|
||||
VST(lsxScratchReg, dstReg, dstoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_AnyS16Morph(int srcoff, int dstoff) {
|
||||
LI(tempReg1, &gstate_c.morphWeights[0]);
|
||||
|
||||
// Sum into lsxScratchReg.
|
||||
bool first = true;
|
||||
for (int n = 0; n < dec_->morphcount; ++n) {
|
||||
const LoongArch64Reg reg = first ? lsxScratchReg : lsxScratchReg2;
|
||||
// Okay, first convert to floats.
|
||||
FLD_D((LoongArch64Reg)(DecodeReg(reg) + F0), srcReg, dec_->onesize_ * n + srcoff);
|
||||
VSLLWIL_W_H(reg, reg, 0);
|
||||
VFFINT_S_W(reg, reg);
|
||||
|
||||
// Now, It's time to multiply by the weight and 1.0f/32768.0f.
|
||||
VLDREPL_W(lsxScratchReg3, tempReg1, sizeof(float) * n);
|
||||
VFMUL_S(lsxScratchReg3, lsxScratchReg3, by32768LSX);
|
||||
VFMUL_S(reg, reg, lsxScratchReg3);
|
||||
|
||||
if (!first) {
|
||||
VFADD_S(lsxScratchReg, lsxScratchReg, lsxScratchReg2);
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (dstoff >= 0)
|
||||
VST(lsxScratchReg, dstReg, dstoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_AnyFloatMorph(int srcoff, int dstoff) {
|
||||
LI(tempReg1, &gstate_c.morphWeights[0]);
|
||||
|
||||
// Sum into lsxScratchReg.
|
||||
bool first = true;
|
||||
for (int n = 0; n < dec_->morphcount; ++n) {
|
||||
const LoongArch64Reg reg = first ? lsxScratchReg : lsxScratchReg2;
|
||||
VLD(reg, srcReg, dec_->onesize_ * n + srcoff);
|
||||
VLDREPL_W(lsxScratchReg3, tempReg1, sizeof(float) * n);
|
||||
VFMUL_S(reg, reg, lsxScratchReg3);
|
||||
if (!first) {
|
||||
VFADD_S(lsxScratchReg, lsxScratchReg, lsxScratchReg2);
|
||||
} else {
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (dstoff >= 0)
|
||||
VST(lsxScratchReg, dstReg, dstoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_PosS8Morph() {
|
||||
Jit_AnyS8Morph(dec_->posoff, dec_->decFmt.posoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_PosS16Morph() {
|
||||
Jit_AnyS16Morph(dec_->posoff, dec_->decFmt.posoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_PosFloatMorph() {
|
||||
Jit_AnyFloatMorph(dec_->posoff, dec_->decFmt.posoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_PosS8MorphSkin() {
|
||||
Jit_AnyS8Morph(dec_->posoff, -1);
|
||||
Jit_WriteMatrixMul(dec_->decFmt.posoff, true);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_PosS16MorphSkin() {
|
||||
Jit_AnyS16Morph(dec_->posoff, -1);
|
||||
Jit_WriteMatrixMul(dec_->decFmt.posoff, true);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_PosFloatMorphSkin() {
|
||||
Jit_AnyFloatMorph(dec_->posoff, -1);
|
||||
Jit_WriteMatrixMul(dec_->decFmt.posoff, true);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_NormalS8Morph() {
|
||||
Jit_AnyS8Morph(dec_->nrmoff, dec_->decFmt.nrmoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_NormalS16Morph() {
|
||||
Jit_AnyS16Morph(dec_->nrmoff, dec_->decFmt.nrmoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_NormalFloatMorph() {
|
||||
Jit_AnyFloatMorph(dec_->nrmoff, dec_->decFmt.nrmoff);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_NormalS8MorphSkin() {
|
||||
Jit_AnyS8Morph(dec_->nrmoff, -1);
|
||||
Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_NormalS16MorphSkin() {
|
||||
Jit_AnyS16Morph(dec_->nrmoff, -1);
|
||||
Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false);
|
||||
}
|
||||
|
||||
void VertexDecoderJitCache::Jit_NormalFloatMorphSkin() {
|
||||
Jit_AnyFloatMorph(dec_->nrmoff, -1);
|
||||
Jit_WriteMatrixMul(dec_->decFmt.nrmoff, false);
|
||||
}
|
||||
#endif // PPSSPP_ARCH(LOONGARCH64)
|
||||
Reference in New Issue
Block a user