diff --git a/GPU/Common/VertexDecoderCommon.cpp b/GPU/Common/VertexDecoderCommon.cpp index eed7049be8..390d24cfcd 100644 --- a/GPU/Common/VertexDecoderCommon.cpp +++ b/GPU/Common/VertexDecoderCommon.cpp @@ -1363,14 +1363,17 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options, // Only use the handwritten decoders if we have SSE or NEON. Don't want to use these on RISC-V, probably? #if PPSSPP_ARCH(ARM_NEON) || PPSSPP_ARCH(SSE2) - // See GetVertTypeID - uint32_t fmtWithoutSkinFlag = (fmt_ & ~0x04000000); - if (fmtWithoutSkinFlag == (GE_VTYPE_TC_8BIT | GE_VTYPE_COL_5551 | GE_VTYPE_POS_16BIT)) { + // See GetVertTypeID. The UV generation modes that don't prescale UV convert it the same way with a + // scale of 1 and no offset, which the NoPrescale versions pass. + const uint32_t vtype = fmt_ & 0x00FFFFFF; + const GETexMapMode uvGenMode = VertTypeIDUVGenMode(fmt_); + const bool prescale = uvGenMode == GE_TEXMAP_TEXTURE_COORDS || uvGenMode == GE_TEXMAP_UNKNOWN; + if (vtype == (GE_VTYPE_TC_8BIT | GE_VTYPE_COL_5551 | GE_VTYPE_POS_16BIT)) { // Can skip looking up in the JIT. - jitted_ = &VtxDec_Tu8_C5551_Ps16; + jitted_ = prescale ? &VtxDec_Tu8_C5551_Ps16 : &VtxDec_Tu8_C5551_Ps16_NoPrescale; return; - } else if (!options.expand8BitNormalsToFloat && fmtWithoutSkinFlag == (GE_VTYPE_TC_16BIT | GE_VTYPE_NRM_8BIT | GE_VTYPE_COL_8888 | GE_VTYPE_POS_FLOAT)) { - jitted_ = &VtxDec_Tu16_C8888_Pfloat; + } else if (!options.expand8BitNormalsToFloat && vtype == (GE_VTYPE_TC_16BIT | GE_VTYPE_NRM_8BIT | GE_VTYPE_COL_8888 | GE_VTYPE_POS_FLOAT)) { + jitted_ = prescale ? &VtxDec_Tu16_C8888_Pfloat : &VtxDec_Tu16_C8888_Pfloat_NoPrescale; return; } #endif diff --git a/GPU/Common/VertexDecoderHandwritten.cpp b/GPU/Common/VertexDecoderHandwritten.cpp index 896423b286..41d3ea6b77 100644 --- a/GPU/Common/VertexDecoderHandwritten.cpp +++ b/GPU/Common/VertexDecoderHandwritten.cpp @@ -324,3 +324,15 @@ void VtxDec_Tu8_C5551_Ps16(const u8 *srcp, u8 *dstp, int numVerts, const UVScale gstate_c.vertexFullAlpha = (alpha >> 15) & 1; } + +// Converting UV without a prescale is the same as with a scale of 1 and no offset: the division by a power +// of two in the scale is exact either way. +static const UVScale identityUVScale = { 1.0f, 1.0f, 0.0f, 0.0f }; + +void VtxDec_Tu16_C8888_Pfloat_NoPrescale(const u8 *srcp, u8 *dstp, int count, const UVScale *uvScaleOffset) { + VtxDec_Tu16_C8888_Pfloat(srcp, dstp, count, &identityUVScale); +} + +void VtxDec_Tu8_C5551_Ps16_NoPrescale(const u8 *srcp, u8 *dstp, int count, const UVScale *uvScaleOffset) { + VtxDec_Tu8_C5551_Ps16(srcp, dstp, count, &identityUVScale); +} diff --git a/GPU/Common/VertexDecoderHandwritten.h b/GPU/Common/VertexDecoderHandwritten.h index fdf666cc85..a14679d917 100644 --- a/GPU/Common/VertexDecoderHandwritten.h +++ b/GPU/Common/VertexDecoderHandwritten.h @@ -5,3 +5,7 @@ void VtxDec_Tu16_C8888_Pfloat(const u8 *srcp, u8 *dstp, int count, const UVScale *uvScaleOffset); void VtxDec_Tu8_C5551_Ps16(const u8 *srcp, u8 *dstp, int count, const UVScale *uvScaleOffset); + +// For the UV generation modes that don't prescale. +void VtxDec_Tu16_C8888_Pfloat_NoPrescale(const u8 *srcp, u8 *dstp, int count, const UVScale *uvScaleOffset); +void VtxDec_Tu8_C5551_Ps16_NoPrescale(const u8 *srcp, u8 *dstp, int count, const UVScale *uvScaleOffset);