From eeb25d0f57b562d4b21c39fdfeca71cfc5dcc9db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Thu, 5 Nov 2026 10:36:41 +0100 Subject: [PATCH] GPU: Remove leftovers of hardware skinning The vertex decoder always skins now (except for the software renderer's own), so NormalizeVertices never sees weights to apply, and the GLES shaders have no bone uniforms to look up. Co-Authored-By: Claude Opus 5.5 --- GPU/Common/SoftwareTransformCommon.cpp | 96 ++++++-------------------- GPU/GLES/ShaderManagerGLES.cpp | 9 --- GPU/GLES/ShaderManagerGLES.h | 7 -- 3 files changed, 22 insertions(+), 90 deletions(-) diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index 792be7833d..d3dc8765b0 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -1492,8 +1492,7 @@ u32 NormalizeVertices(SimpleVertex *sverts, u8 *bufPtr, const u8 *inPtr, int low const int count = upperBound + 1 - lowerBound; dec->DecodeVerts(bufPtr, inPtr + lowerBound * dec->VertexSize(), &uvScale, count); - // OK, morphing eliminated but bones still remain to be taken care of. - // Let's do a partial software transform where we only do skinning. + // The decoder has morphed and skinned them. VertexReader reader(bufPtr, dec->GetDecVtxFmt(), vertType); @@ -1504,80 +1503,29 @@ u32 NormalizeVertices(SimpleVertex *sverts, u8 *bufPtr, const u8 *inPtr, int low (u8)gstate.getMaterialAmbientA(), }; - // Let's have two separate loops, one for non skinning and one for skinning. - if (!dec->skinInDecode && (vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) { - int numBoneWeights = vertTypeGetNumBoneWeights(vertType); - for (int i = lowerBound; i <= upperBound; i++) { - reader.Goto(i - lowerBound); - SimpleVertex &sv = sverts[i]; - if (vertType & GE_VTYPE_TC_MASK) { - reader.ReadUV(sv.uv); - } - - if (vertType & GE_VTYPE_COL_MASK) { - sv.color_32 = reader.ReadColor0_8888(); - } else { - memcpy(sv.color, defaultColor, 4); - } - - float nrm[3], pos[3]; - float bnrm[3], bpos[3]; - - if (vertType & GE_VTYPE_NRM_MASK) { - // Normals are generated during tessellation anyway, not sure if any need to supply - reader.ReadNrm(nrm); - } else { - nrm[0] = 0; - nrm[1] = 0; - nrm[2] = 1.0f; - } - reader.ReadPosAuto(pos); - - // Apply skinning transform directly - float weights[8]; - reader.ReadWeights(weights); - // Skinning - Vec3Packedf psum(0, 0, 0); - Vec3Packedf nsum(0, 0, 0); - for (int w = 0; w < numBoneWeights; w++) { - if (weights[w] != 0.0f) { - Vec3ByMatrix43(bpos, pos, gstate.boneMatrix + w * 12); - Vec3Packedf tpos(bpos); - psum += tpos * weights[w]; - - Norm3ByMatrix43(bnrm, nrm, gstate.boneMatrix + w * 12); - Vec3Packedf tnorm(bnrm); - nsum += tnorm * weights[w]; - } - } - sv.pos = psum; - sv.nrm = nsum; + for (int i = lowerBound; i <= upperBound; i++) { + reader.Goto(i - lowerBound); + SimpleVertex &sv = sverts[i]; + if (vertType & GE_VTYPE_TC_MASK) { + reader.ReadUV(sv.uv); + } else { + sv.uv[0] = 0.0f; // This will get filled in during tessellation + sv.uv[1] = 0.0f; } - } else { - for (int i = lowerBound; i <= upperBound; i++) { - reader.Goto(i - lowerBound); - SimpleVertex &sv = sverts[i]; - if (vertType & GE_VTYPE_TC_MASK) { - reader.ReadUV(sv.uv); - } else { - sv.uv[0] = 0.0f; // This will get filled in during tessellation - sv.uv[1] = 0.0f; - } - if (vertType & GE_VTYPE_COL_MASK) { - sv.color_32 = reader.ReadColor0_8888(); - } else { - memcpy(sv.color, defaultColor, 4); - } - if (vertType & GE_VTYPE_NRM_MASK) { - // Normals are generated during tessellation anyway, not sure if any need to supply - reader.ReadNrm((float *)&sv.nrm); - } else { - sv.nrm.x = 0.0f; - sv.nrm.y = 0.0f; - sv.nrm.z = 1.0f; - } - reader.ReadPosAuto((float *)&sv.pos); + if (vertType & GE_VTYPE_COL_MASK) { + sv.color_32 = reader.ReadColor0_8888(); + } else { + memcpy(sv.color, defaultColor, 4); } + if (vertType & GE_VTYPE_NRM_MASK) { + // Normals are generated during tessellation anyway, not sure if any need to supply + reader.ReadNrm((float *)&sv.nrm); + } else { + sv.nrm.x = 0.0f; + sv.nrm.y = 0.0f; + sv.nrm.z = 1.0f; + } + reader.ReadPosAuto((float *)&sv.pos); } // Okay, there we are! Return the new type (but keep the index bits) diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index eb66cb27a4..191fcf3ec3 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -132,15 +132,6 @@ LinkedShader::LinkedShader(GLRenderManager *render, VShaderID VSID, Shader *vs, queries.push_back({ &u_scaleX, "u_scaleX" }); queries.push_back({ &u_scaleY, "u_scaleY" }); -#ifdef USE_BONE_ARRAY - queries.push_back({ &u_bone, "u_bone" }); -#else - static constexpr const char * boneNames[8] = { "u_bone0", "u_bone1", "u_bone2", "u_bone3", "u_bone4", "u_bone5", "u_bone6", "u_bone7", }; - for (int i = 0; i < 8; i++) { - queries.push_back({ &u_bone[i], boneNames[i] }); - } -#endif - // Lighting, texturing queries.push_back({ &u_ambient, "u_ambient" }); queries.push_back({ &u_matambientalpha, "u_matambientalpha" }); diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h index ce5b2d551e..b9df2bef54 100644 --- a/GPU/GLES/ShaderManagerGLES.h +++ b/GPU/GLES/ShaderManagerGLES.h @@ -78,13 +78,6 @@ public: int u_rasterOffset; int u_minZmaxZ; -#ifdef USE_BONE_ARRAY - int u_bone; // array, size is numBones -#else - int u_bone[8]; -#endif - int numBones; - // Shader blending. int u_fbotex; int u_blendFixA;