Remove obsolete vertex decoder code and options

This commit is contained in:
Henrik Rydgård committed 2026-07-14 17:26:00 +02:00
1 parent cd40e2d4f0
commit c3eafeb005
10 files changed
+4 -499

No files matched your search

-52
View File
@@ -104,9 +104,6 @@ static const ARMReg srcNEON = Q2;
static const ARMReg accNEON = Q3;
static const JitLookup jitLookup[] = {
{&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8},
{&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16},
{&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat},
{&VertexDecoder::Step_WeightsU8Skin, &VertexDecoderJitCache::Jit_WeightsU8Skin},
{&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin},
{&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin},
@@ -296,55 +293,6 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int
return (JittedVertexDecoder)start;
}
void VertexDecoderJitCache::Jit_WeightsU8() {
// Basic implementation - a byte at a time. TODO: Optimize
int j;
for (j = 0; j < dec_->nweights; j++) {
LDRB(tempReg1, srcReg, dec_->weightoff + j);
STRB(tempReg1, dstReg, dec_->decFmt.w0off + j);
}
if (j & 3) {
// Create a zero register. Might want to make a fixed one.
EOR(scratchReg, scratchReg, scratchReg);
}
while (j & 3) {
STRB(scratchReg, dstReg, dec_->decFmt.w0off + j);
j++;
}
}
void VertexDecoderJitCache::Jit_WeightsU16() {
// Basic implementation - a short at a time. TODO: Optimize
int j;
for (j = 0; j < dec_->nweights; j++) {
LDRH(tempReg1, srcReg, dec_->weightoff + j * 2);
STRH(tempReg1, dstReg, dec_->decFmt.w0off + j * 2);
}
if (j & 3) {
// Create a zero register. Might want to make a fixed one.
EOR(scratchReg, scratchReg, scratchReg);
}
while (j & 3) {
STRH(scratchReg, dstReg, dec_->decFmt.w0off + j * 2);
j++;
}
}
void VertexDecoderJitCache::Jit_WeightsFloat() {
int j;
for (j = 0; j < dec_->nweights; j++) {
LDR(tempReg1, srcReg, dec_->weightoff + j * 4);
STR(tempReg1, dstReg, dec_->decFmt.w0off + j * 4);
}
if (j & 3) {
EOR(tempReg1, tempReg1, tempReg1);
}
while (j & 3) { // Zero additional weights rounding up to 4.
STR(tempReg1, dstReg, dec_->decFmt.w0off + j * 4);
j++;
}
}
static const ARMReg weightRegs[8] = { S8, S9, S10, S11, S12, S13, S14, S15 };
static const ARMReg neonWeightRegsD[4] = { D4, D5, D6, D7 };
static const ARMReg neonWeightRegsQ[2] = { Q2, Q3 };
-41
View File
@@ -81,9 +81,6 @@ static const ARM64Reg neonWeightRegsQ[2] = { Q3, Q2 }; // reverse order to prev
// Q16+ are free-for-all for matrices. In 16 registers, we can fit 4 4x4 matrices.
static const JitLookup jitLookup[] = {
{&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8},
{&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16},
{&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat},
{&VertexDecoder::Step_WeightsU8Skin, &VertexDecoderJitCache::Jit_WeightsU8Skin},
{&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin},
{&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin},
@@ -359,44 +356,6 @@ void VertexDecoderJitCache::Jit_ApplyWeights() {
}
}
void VertexDecoderJitCache::Jit_WeightsU8() {
// Basic implementation - a byte at a time. TODO: Optimize
int j;
for (j = 0; j < dec_->nweights; j++) {
LDRB(INDEX_UNSIGNED, tempReg1, srcReg, dec_->weightoff + j);
STRB(INDEX_UNSIGNED, tempReg1, dstReg, dec_->decFmt.w0off + j);
}
while (j & 3) {
STRB(INDEX_UNSIGNED, WZR, dstReg, dec_->decFmt.w0off + j);
j++;
}
}
void VertexDecoderJitCache::Jit_WeightsU16() {
// Basic implementation - a short at a time. TODO: Optimize
int j;
for (j = 0; j < dec_->nweights; j++) {
LDRH(INDEX_UNSIGNED, tempReg1, srcReg, dec_->weightoff + j * 2);
STRH(INDEX_UNSIGNED, tempReg1, dstReg, dec_->decFmt.w0off + j * 2);
}
while (j & 3) {
STRH(INDEX_UNSIGNED, WZR, dstReg, dec_->decFmt.w0off + j * 2);
j++;
}
}
void VertexDecoderJitCache::Jit_WeightsFloat() {
int j;
for (j = 0; j < dec_->nweights; j++) {
LDR(INDEX_UNSIGNED, tempReg1, srcReg, dec_->weightoff + j * 4);
STR(INDEX_UNSIGNED, tempReg1, dstReg, dec_->decFmt.w0off + j * 4);
}
while (j & 3) { // Zero additional weights rounding up to 4.
STR(INDEX_UNSIGNED, WZR, dstReg, dec_->decFmt.w0off + j * 4);
j++;
}
}
void VertexDecoderJitCache::Jit_WeightsU8Skin() {
// Weight is first so srcReg is correct.
switch (dec_->nweights) {
+4 -123
View File
@@ -55,13 +55,6 @@ inline int align(int n, int align) {
return (n + (align - 1)) & ~(align - 1);
}
// Map 1-4 bones to 4 bones. works fine.
int TranslateNumBones(int bones) {
if (!bones) return 0;
if (bones < 4) return 4;
return bones;
}
static int DecFmtSize(u8 fmt) {
switch (fmt) {
case DEC_NONE: return 0;
@@ -230,66 +223,6 @@ void PrintDecodedVertex(const VertexReader &vtx) {
printf("P: %f %f %f\n", pos[0], pos[1], pos[2]);
}
void VertexDecoder::Step_WeightsU8(const VertexDecoder *dec, const u8 *ptr, u8 *decoded) {
u8 *wt = (u8 *)(decoded + dec->decFmt.w0off);
const u8 *wdata = (const u8*)(ptr);
int j;
const int nweights = dec->nweights;
for (j = 0; j < nweights; j++)
wt[j] = wdata[j];
while (j & 3) // Zero additional weights rounding up to 4.
wt[j++] = 0;
}
void VertexDecoder::Step_WeightsU16(const VertexDecoder *dec, const u8 *ptr, u8 *decoded) {
u16 *wt = (u16 *)(decoded + dec->decFmt.w0off);
const u16_le *wdata = (const u16_le *)(ptr);
int j;
const int nweights = dec->nweights;
for (j = 0; j < nweights; j++)
wt[j] = wdata[j];
while (j & 3) // Zero additional weights rounding up to 4.
wt[j++] = 0;
}
void VertexDecoder::Step_WeightsU8ToFloat(const VertexDecoder *dec, const u8 *ptr, u8 *decoded) {
float *wt = (float *)(decoded + dec->decFmt.w0off);
const u8 *wdata = (const u8*)(ptr);
int j;
const int nweights = dec->nweights;
for (j = 0; j < nweights; j++) {
wt[j] = (float)wdata[j] * (1.0f / 128.0f);
}
while (j & 3) // Zero additional weights rounding up to 4.
wt[j++] = 0;
}
void VertexDecoder::Step_WeightsU16ToFloat(const VertexDecoder *dec, const u8 *ptr, u8 *decoded) {
float *wt = (float *)(decoded + dec->decFmt.w0off);
const u16_le *wdata = (const u16_le *)(ptr);
int j;
const int nweights = dec->nweights;
for (j = 0; j < nweights; j++) {
wt[j] = (float)wdata[j] * (1.0f / 32768.0f);
}
while (j & 3) // Zero additional weights rounding up to 4.
wt[j++] = 0;
}
// Float weights should be uncommon, we can live with having to multiply these by 2.0
// to avoid special checks in the vertex shader generator.
// (PSP uses 0.0-2.0 fixed point numbers for weights)
void VertexDecoder::Step_WeightsFloat(const VertexDecoder *dec, const u8 *ptr, u8 *decoded) {
float *wt = (float *)(decoded + dec->decFmt.w0off);
const float_le *wdata = (const float_le *)(ptr);
int j;
for (j = 0; j < dec->nweights; j++) {
wt[j] = wdata[j];
}
while (j & 3) // Zero additional weights rounding up to 4.
wt[j++] = 0.0f;
}
void VertexDecoder::ComputeSkinMatrix(const float weights[8]) const {
const int count = nweights;
#if PPSSPP_ARCH(SSE2)
@@ -1061,20 +994,6 @@ void VertexDecoder::Step_PosFloatMorphSkin(const VertexDecoder *dec, const u8 *p
Vec3ByMatrix43(v, pos, skinMatrix);
}
static const StepFunction wtstep[4] = {
0,
&VertexDecoder::Step_WeightsU8,
&VertexDecoder::Step_WeightsU16,
&VertexDecoder::Step_WeightsFloat,
};
static const StepFunction wtstepToFloat[4] = {
0,
&VertexDecoder::Step_WeightsU8ToFloat,
&VertexDecoder::Step_WeightsU16ToFloat,
&VertexDecoder::Step_WeightsFloat,
};
// TODO: Morph weights correctly! This is missing. Not sure if any game actually
// use this functionality at all.
@@ -1273,50 +1192,18 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options,
DEBUG_LOG(Log::G3D, "VTYPE: THRU=%i TC=%i COL=%i POS=%i NRM=%i WT=%i NW=%i IDX=%i MC=%i", (int)throughmode, tc, col, pos, nrm, weighttype, nweights, idx, morphcount);
}
skinInDecode = weighttype != 0 && VertTypeIDSkinInDecode(fmt);
if (weighttype) { // && nweights?
skinInDecode = true;
weightoff = size;
//size = align(size, wtalign[weighttype]); unnecessary
size += wtsize[weighttype] * nweights;
if (wtalign[weighttype] > biggest)
biggest = wtalign[weighttype];
if (skinInDecode) {
// No visible output, computes a matrix that is passed through the skinMatrix variable
// to the "nrm" and "pos" steps.
steps_[numSteps_++] = wtstep_skin[weighttype];
} else {
int fmtBase = DEC_FLOAT_1;
if (options.expandAllWeightsToFloat) {
steps_[numSteps_++] = wtstepToFloat[weighttype];
fmtBase = DEC_FLOAT_1;
} else {
steps_[numSteps_++] = wtstep[weighttype];
if (weighttype == GE_VTYPE_WEIGHT_8BIT >> GE_VTYPE_WEIGHT_SHIFT) {
fmtBase = DEC_U8_1;
} else if (weighttype == GE_VTYPE_WEIGHT_16BIT >> GE_VTYPE_WEIGHT_SHIFT) {
fmtBase = DEC_U16_1;
} else if (weighttype == GE_VTYPE_WEIGHT_FLOAT >> GE_VTYPE_WEIGHT_SHIFT) {
fmtBase = DEC_FLOAT_1;
}
}
int numWeights = TranslateNumBones(nweights);
if (numWeights <= 4) {
decFmt.w0off = decOff;
decFmt.w0fmt = fmtBase + numWeights - 1;
decOff += DecFmtSize(decFmt.w0fmt);
} else {
decFmt.w0off = decOff;
decFmt.w0fmt = fmtBase + 3;
decOff += DecFmtSize(decFmt.w0fmt);
decFmt.w1off = decOff;
decFmt.w1fmt = fmtBase + numWeights - 5;
decOff += DecFmtSize(decFmt.w1fmt);
}
}
// No visible output, computes a matrix that is passed through the skinMatrix variable
// to the "nrm" and "pos" steps.
steps_[numSteps_++] = wtstep_skin[weighttype];
}
if (tc) {
@@ -1747,12 +1634,6 @@ struct StepFunctionNameEntry {
};
static const StepFunctionNameEntry stepFunctionNames[] = {
{VertexDecoder::Step_WeightsU8, "WeightsU8"},
{VertexDecoder::Step_WeightsU16, "WeightsU16"},
{VertexDecoder::Step_WeightsU8ToFloat, "WeightsU8ToFloat"},
{VertexDecoder::Step_WeightsU16ToFloat, "WeightsU16ToFloat"},
{VertexDecoder::Step_WeightsFloat, "WeightsFloat"},
{VertexDecoder::Step_WeightsU8Skin, "WeightsU8Skin"},
{VertexDecoder::Step_WeightsU16Skin, "WeightsU16Skin"},
{VertexDecoder::Step_WeightsFloatSkin, "WeightsFloatSkin"},
-20
View File
@@ -133,13 +133,9 @@ struct JitLookup {
JitStepFunction jitFunc;
};
// Collapse to less skinning shaders to reduce shader switching, which is expensive.
int TranslateNumBones(int bones);
typedef void (*JittedVertexDecoder)(const u8 *src, u8 *dst, int count, const UVScale *uvScaleOffset);
struct VertexDecoderOptions {
bool expandAllWeightsToFloat;
bool expand8BitNormalsToFloat;
};
@@ -149,10 +145,6 @@ inline uint32_t GetVertTypeID(uint32_t vertType, int uvGenMode) {
return (vertType & 0xFFFFFF) | (uvGenMode << 24);
}
inline bool VertTypeIDSkinInDecode(uint32_t vertType) {
return true;
}
inline GETexMapMode VertTypeIDUVGenMode(uint32_t vertType) {
return (GETexMapMode)((vertType >> 24) & 3);
}
@@ -179,12 +171,6 @@ public:
void ComputeSkinMatrix(const float weights[8]) const;
static void Step_WeightsU8(const VertexDecoder *dec, const u8 *ptr, u8 *decoded);
static void Step_WeightsU16(const VertexDecoder *dec, const u8 *ptr, u8 *decoded);
static void Step_WeightsU8ToFloat(const VertexDecoder *dec, const u8 *ptr, u8 *decoded);
static void Step_WeightsU16ToFloat(const VertexDecoder *dec, const u8 *ptr, u8 *decoded);
static void Step_WeightsFloat(const VertexDecoder *dec, const u8 *ptr, u8 *decoded);
static void Step_WeightsU8Skin(const VertexDecoder *dec, const u8 *ptr, u8 *decoded);
static void Step_WeightsU16Skin(const VertexDecoder *dec, const u8 *ptr, u8 *decoded);
static void Step_WeightsFloatSkin(const VertexDecoder *dec, const u8 *ptr, u8 *decoded);
@@ -351,12 +337,6 @@ public:
JittedVertexDecoder Compile(const VertexDecoder &dec, int32_t *jittedSize);
void Clear();
void Jit_WeightsU8();
void Jit_WeightsU16();
void Jit_WeightsU8ToFloat();
void Jit_WeightsU16ToFloat();
void Jit_WeightsFloat();
void Jit_WeightsU8Skin();
void Jit_WeightsU16Skin();
void Jit_WeightsFloatSkin();
-43
View File
@@ -93,9 +93,6 @@ static constexpr LoongArch64Reg regs_to_save_fp[]{ F24, F25, F26, F27, F28, F29,
// V16+ are free-for-all for matrices. In 16 registers, we can fit 4 4x4 matrices.
static const JitLookup jitLookup[] = {
{&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8},
{&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16},
{&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat},
{&VertexDecoder::Step_WeightsU8Skin, &VertexDecoderJitCache::Jit_WeightsU8Skin},
{&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin},
{&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin},
@@ -415,46 +412,6 @@ void VertexDecoderJitCache::Jit_ApplyWeights() {
}
}
void VertexDecoderJitCache::Jit_WeightsU8() {
// Basic implementation - a byte at a time.
// TODO: Could optimize with unaligned load/store
int j;
for (j = 0; j < dec_->nweights; j++) {
LD_B(tempReg1, srcReg, dec_->weightoff + j);
ST_B(tempReg1, dstReg, dec_->decFmt.w0off + j);
}
while (j & 3) {
ST_B(R_ZERO, dstReg, dec_->decFmt.w0off + j);
j++;
}
}
void VertexDecoderJitCache::Jit_WeightsU16() {
// Basic implementation - a short at a time.
// TODO: Could optimize with unaligned load/store
int j;
for (j = 0; j < dec_->nweights; j++) {
LD_H(tempReg1, srcReg, dec_->weightoff + j * 2);
ST_H(tempReg1, dstReg, dec_->decFmt.w0off + j * 2);
}
while (j & 3) {
ST_H(R_ZERO, dstReg, dec_->decFmt.w0off + j * 2);
j++;
}
}
void VertexDecoderJitCache::Jit_WeightsFloat() {
int j;
for (j = 0; j < dec_->nweights; j++) {
LD_W(tempReg1, srcReg, dec_->weightoff + j * 4);
ST_W(tempReg1, dstReg, dec_->decFmt.w0off + j * 4);
}
while (j & 3) { // Zero additional weights rounding up to 4.
ST_W(R_ZERO, dstReg, dec_->decFmt.w0off + j * 4);
j++;
}
}
void VertexDecoderJitCache::Jit_WeightsU8Skin() {
// Weight is first so srcReg is correct.
switch (dec_->nweights) {
-42
View File
@@ -123,9 +123,6 @@ static uint32_t GetMorphValueUsage(uint32_t vtype) {
// TODO: Use vector, where supported.
static const JitLookup jitLookup[] = {
{&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8},
{&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16},
{&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat},
{&VertexDecoder::Step_WeightsU8Skin, &VertexDecoderJitCache::Jit_WeightsU8Skin},
{&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin},
{&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin},
@@ -374,45 +371,6 @@ bool VertexDecoderJitCache::CompileStep(const VertexDecoder &dec, int step) {
return false;
}
void VertexDecoderJitCache::Jit_WeightsU8() {
// Just copy a byte at a time. Would be nice if we knew if misaligned access was fast.
// If it's not fast, it can crash or hit a software trap (100x slower.)
int j;
for (j = 0; j < dec_->nweights; j++) {
LB(tempReg1, srcReg, dec_->weightoff + j);
SB(tempReg1, dstReg, dec_->decFmt.w0off + j);
}
// We zero out any weights up to a multiple of 4.
while (j & 3) {
SB(R_ZERO, dstReg, dec_->decFmt.w0off + j);
j++;
}
}
void VertexDecoderJitCache::Jit_WeightsU16() {
int j;
for (j = 0; j < dec_->nweights; j++) {
LH(tempReg1, srcReg, dec_->weightoff + j * 2);
SH(tempReg1, dstReg, dec_->decFmt.w0off + j * 2);
}
while (j & 3) {
SH(R_ZERO, dstReg, dec_->decFmt.w0off + j * 2);
j++;
}
}
void VertexDecoderJitCache::Jit_WeightsFloat() {
int j;
for (j = 0; j < dec_->nweights; j++) {
LW(tempReg1, srcReg, dec_->weightoff + j * 4);
SW(tempReg1, dstReg, dec_->decFmt.w0off + j * 4);
}
while (j & 3) {
SW(R_ZERO, dstReg, dec_->decFmt.w0off + j * 4);
j++;
}
}
void VertexDecoderJitCache::Jit_WeightsU8Skin() {
Jit_ApplyWeights();
}
-175
View File
@@ -101,16 +101,10 @@ static const X64Reg fpScratchReg4 = XMM4;
// on the interpreter if the compiler fails.
static const JitLookup jitLookup[] = {
{&VertexDecoder::Step_WeightsU8, &VertexDecoderJitCache::Jit_WeightsU8},
{&VertexDecoder::Step_WeightsU16, &VertexDecoderJitCache::Jit_WeightsU16},
{&VertexDecoder::Step_WeightsFloat, &VertexDecoderJitCache::Jit_WeightsFloat},
{&VertexDecoder::Step_WeightsU8Skin, &VertexDecoderJitCache::Jit_WeightsU8Skin},
{&VertexDecoder::Step_WeightsU16Skin, &VertexDecoderJitCache::Jit_WeightsU16Skin},
{&VertexDecoder::Step_WeightsFloatSkin, &VertexDecoderJitCache::Jit_WeightsFloatSkin},
{&VertexDecoder::Step_WeightsU8ToFloat, &VertexDecoderJitCache::Jit_WeightsU8ToFloat},
{&VertexDecoder::Step_WeightsU16ToFloat, &VertexDecoderJitCache::Jit_WeightsU16ToFloat},
{&VertexDecoder::Step_TcFloat, &VertexDecoderJitCache::Jit_TcFloat},
{&VertexDecoder::Step_TcU8ToFloat, &VertexDecoderJitCache::Jit_TcU8ToFloat},
{&VertexDecoder::Step_TcU16ToFloat, &VertexDecoderJitCache::Jit_TcU16ToFloat},
@@ -333,175 +327,6 @@ JittedVertexDecoder VertexDecoderJitCache::Compile(const VertexDecoder &dec, int
return (JittedVertexDecoder)start;
}
void VertexDecoderJitCache::Jit_WeightsU8() {
switch (dec_->nweights) {
case 1:
MOVZX(32, 8, tempReg1, MDisp(srcReg, dec_->weightoff));
break;
case 2:
MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->weightoff));
break;
case 3:
MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff));
AND(32, R(tempReg1), Imm32(0x00FFFFFF));
break;
case 4:
MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff));
break;
case 5:
MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff));
MOVZX(32, 8, tempReg2, MDisp(srcReg, dec_->weightoff + 4));
break;
case 6:
MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff));
MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->weightoff + 4));
break;
case 7:
MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff));
MOV(32, R(tempReg2), MDisp(srcReg, dec_->weightoff + 4));
AND(32, R(tempReg2), Imm32(0x00FFFFFF));
break;
case 8:
MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff));
MOV(32, R(tempReg2), MDisp(srcReg, dec_->weightoff + 4));
break;
}
if (dec_->nweights <= 4) {
MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1));
} else {
MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1));
MOV(32, MDisp(dstReg, dec_->decFmt.w1off), R(tempReg2));
}
}
void VertexDecoderJitCache::Jit_WeightsU16() {
switch (dec_->nweights) {
case 1:
MOVZX(32, 16, tempReg1, MDisp(srcReg, dec_->weightoff));
MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1));
MOV(32, MDisp(dstReg, dec_->decFmt.w0off + 4), Imm32(0));
return;
case 2:
MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff));
MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1));
MOV(32, MDisp(dstReg, dec_->decFmt.w0off + 4), Imm32(0));
return;
case 3:
MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff));
MOVZX(32, 16, tempReg2, MDisp(srcReg, dec_->weightoff + 4));
MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1));
MOV(32, MDisp(dstReg, dec_->decFmt.w0off + 4), R(tempReg2));
return;
case 4:
// Anything above 4 will do 4 here, and then the rest after.
case 5:
case 6:
case 7:
case 8:
MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff));
MOV(32, R(tempReg2), MDisp(srcReg, dec_->weightoff + 4));
MOV(32, MDisp(dstReg, dec_->decFmt.w0off), R(tempReg1));
MOV(32, MDisp(dstReg, dec_->decFmt.w0off + 4), R(tempReg2));
break;
}
// Basic implementation - a short at a time. TODO: Optimize
int j;
for (j = 4; j < dec_->nweights; j++) {
MOV(16, R(tempReg1), MDisp(srcReg, dec_->weightoff + j * 2));
MOV(16, MDisp(dstReg, dec_->decFmt.w0off + j * 2), R(tempReg1));
}
while (j & 3) {
MOV(16, MDisp(dstReg, dec_->decFmt.w0off + j * 2), Imm16(0));
j++;
}
}
void VertexDecoderJitCache::Jit_WeightsU8ToFloat() {
if (dec_->nweights >= 4) {
Jit_AnyU8ToFloat(dec_->weightoff, 32);
MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3);
if (dec_->nweights > 4) {
Jit_AnyU8ToFloat(dec_->weightoff + 4, (dec_->nweights - 4) * 8);
MOVUPS(MDisp(dstReg, dec_->decFmt.w1off), XMM3);
}
} else {
Jit_AnyU8ToFloat(dec_->weightoff, dec_->nweights * 8);
MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3);
}
}
void VertexDecoderJitCache::Jit_WeightsU16ToFloat() {
if (dec_->nweights >= 4) {
Jit_AnyU16ToFloat(dec_->weightoff, 64);
MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3);
if (dec_->nweights > 4) {
Jit_AnyU16ToFloat(dec_->weightoff + 4 * 2, (dec_->nweights - 4) * 16);
MOVUPS(MDisp(dstReg, dec_->decFmt.w1off), XMM3);
}
} else {
Jit_AnyU16ToFloat(dec_->weightoff, dec_->nweights * 16);
MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3);
}
}
void VertexDecoderJitCache::Jit_WeightsFloat() {
int j;
switch (dec_->nweights) {
case 1:
// MOVSS: When the source operand is a memory location and destination operand is an XMM register, the three high-order doublewords of the destination operand are cleared to all 0s.
MOVSS(XMM3, MDisp(srcReg, dec_->weightoff));
MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3);
break;
case 2:
MOVQ_xmm(XMM3, MDisp(srcReg, dec_->weightoff));
MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3);
break;
case 4:
MOVUPS(XMM3, MDisp(srcReg, dec_->weightoff));
MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3);
break;
case 5:
MOVUPS(XMM3, MDisp(srcReg, dec_->weightoff));
MOVSS(XMM4, MDisp(srcReg, dec_->weightoff + 16));
MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3);
MOVUPS(MDisp(dstReg, dec_->decFmt.w0off + 16), XMM4);
break;
case 6:
MOVUPS(XMM3, MDisp(srcReg, dec_->weightoff));
MOVQ_xmm(XMM4, MDisp(srcReg, dec_->weightoff + 16));
MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3);
MOVUPS(MDisp(dstReg, dec_->decFmt.w0off + 16), XMM4);
break;
case 8:
MOVUPS(XMM3, MDisp(srcReg, dec_->weightoff));
MOVUPS(XMM4, MDisp(srcReg, dec_->weightoff + 16));
MOVUPS(MDisp(dstReg, dec_->decFmt.w0off), XMM3);
MOVUPS(MDisp(dstReg, dec_->decFmt.w0off + 16), XMM4);
break;
default:
for (j = 0; j < dec_->nweights; j++) {
MOV(32, R(tempReg1), MDisp(srcReg, dec_->weightoff + j * 4));
MOV(32, MDisp(dstReg, dec_->decFmt.w0off + j * 4), R(tempReg1));
}
while (j & 3) { // Zero additional weights rounding up to 4.
MOV(32, MDisp(dstReg, dec_->decFmt.w0off + j * 4), Imm32(0));
j++;
}
break;
}
}
void VertexDecoderJitCache::Jit_WeightsU8Skin() {
MOV(PTRBITS, R(tempReg2), ImmPtr(&bones));
-1
View File
@@ -71,7 +71,6 @@ DrawEngineD3D11::DrawEngineD3D11(Draw::DrawContext *draw, ID3D11Device *device,
rasterCache_(4) {
device1_ = (ID3D11Device1 *)draw->GetNativeObject(Draw::NativeObject::DEVICE_EX);
context1_ = (ID3D11DeviceContext1 *)draw->GetNativeObject(Draw::NativeObject::CONTEXT_EX);
decOptions_.expandAllWeightsToFloat = true;
decOptions_.expand8BitNormalsToFloat = true;
InitDeviceObjects();
-1
View File
@@ -53,7 +53,6 @@ enum {
DrawEngineGLES::DrawEngineGLES(Draw::DrawContext *draw) : inputLayoutMap_(16), draw_(draw) {
render_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
decOptions_.expandAllWeightsToFloat = false;
decOptions_.expand8BitNormalsToFloat = false;
InitDeviceObjects();
-1
View File
@@ -50,7 +50,6 @@ enum {
DrawEngineVulkan::DrawEngineVulkan(Draw::DrawContext *draw)
: draw_(draw) {
decOptions_.expandAllWeightsToFloat = false;
decOptions_.expand8BitNormalsToFloat = false;
}