mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-17 00:10:31 +02:00
Vertex decoder: Build the skin matrix without a branch per weight on ARM64
The steps skipped bones with a zero weight. With weights that vary from vertex to vertex that branch mispredicts a lot, and it saves only a few multiplies. Now every weight is applied, with fused multiply-adds, as the vertex JIT does. Without the vertex JIT (as on iOS): Tekken 4.5% fewer cycles, God Eater 2.6%, God of War 1.7%. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
4dedfa2b8b
commit
bf7e32cdae
1 file changed
+8
@@ -247,12 +247,20 @@ void VertexDecoder::ComputeSkinMatrix(const float weights[8]) const {
|
||||
float32x4_t skin2 = vdupq_n_f32(0.0f);
|
||||
for (int j = 0; j < count; j++) {
|
||||
const float *bone = &gstate.boneMatrix[j * 12];
|
||||
#if PPSSPP_ARCH(ARM64_NEON)
|
||||
// Every weight, fused, like the vertex JIT (and no branch on varying weights).
|
||||
const float32x4_t w = vdupq_n_f32(weights[j]);
|
||||
skin0 = vfmaq_f32(skin0, vld1q_f32(bone), w);
|
||||
skin1 = vfmaq_f32(skin1, vld1q_f32(bone + 4), w);
|
||||
skin2 = vfmaq_f32(skin2, vld1q_f32(bone + 8), w);
|
||||
#else
|
||||
if (weights[j] != 0.0f) {
|
||||
float32x4_t w = vdupq_n_f32(weights[j]);
|
||||
skin0 = vaddq_f32(skin0, vmulq_f32(vld1q_f32(bone), w));
|
||||
skin1 = vaddq_f32(skin1, vmulq_f32(vld1q_f32(bone + 4), w));
|
||||
skin2 = vaddq_f32(skin2, vmulq_f32(vld1q_f32(bone + 8), w));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
vst1q_f32(skinMatrix, skin0);
|
||||
vst1q_f32(skinMatrix + 4, skin1);
|
||||
|
||||
Reference in new issue
Block a user