// From https://github.com/chadaustin/Web-Benchmarks/blob/master/skinning_test_no_simd.cpp // Modifications: // 1. Run for a fixed # of iterations, so the total runtime is the benchmark // 2. Not have so much stuff on the stack in main() // // compiled in cygwin with: // g++ -Wall -O2 -o skinning_test_no_simd skinning_test_no_simd.cpp #include #include #include #include #include #include #include #include struct CalBase4 { float x, y, z, w; void set(float _x, float _y, float _z, float _w) { x = _x; y = _y; z = _z; w = _w; } }; struct CalVector4 : CalBase4 { CalVector4() { x = 0.0f; y = 0.0f; z = 0.0f; w = 0.0f; } CalVector4(float x, float y, float z, float w = 0.0f) { this->x = x; this->y = y; this->z = z; this->w = w; } void setAsVector(float x, float y, float z) { this->x = x; this->y = y; this->z = z; w = 0.0f; } }; struct CalPoint4 : CalBase4 { CalPoint4() { x = 0.0f; y = 0.0f; z = 0.0f; w = 1.0f; } CalPoint4(float x, float y, float z, float w = 1.0f) { this->x = x; this->y = y; this->z = z; this->w = w; } void setAsPoint(float x, float y, float z) { x = this->x; y = this->y; z = this->z; w = 1.0f; } }; // 3x3 transform matrix plus a translation 3-vector (stored in the w components // of the rows. struct BoneTransform { CalVector4 rowx; CalVector4 rowy; CalVector4 rowz; }; struct Influence { Influence() { boneId = -1; weight = 0.0f; lastInfluenceForThisVertex = 0; } Influence(unsigned b, float w, bool last) { boneId = b; weight = w; lastInfluenceForThisVertex = last ? 1 : 0; } unsigned boneId; float weight; unsigned lastInfluenceForThisVertex; }; struct Vertex { CalPoint4 position; CalVector4 normal; }; inline void ScaleMatrix(BoneTransform& result, const BoneTransform& mat, const float s) { result.rowx.x = s * mat.rowx.x; result.rowx.y = s * mat.rowx.y; result.rowx.z = s * mat.rowx.z; result.rowx.w = s * mat.rowx.w; result.rowy.x = s * mat.rowy.x; result.rowy.y = s * mat.rowy.y; result.rowy.z = s * mat.rowy.z; result.rowy.w = s * mat.rowy.w; result.rowz.x = s * mat.rowz.x; result.rowz.y = s * mat.rowz.y; result.rowz.z = s * mat.rowz.z; result.rowz.w = s * mat.rowz.w; } inline void AddScaledMatrix(BoneTransform& result, const BoneTransform& mat, const float s) { result.rowx.x += s * mat.rowx.x; result.rowx.y += s * mat.rowx.y; result.rowx.z += s * mat.rowx.z; result.rowx.w += s * mat.rowx.w; result.rowy.x += s * mat.rowy.x; result.rowy.y += s * mat.rowy.y; result.rowy.z += s * mat.rowy.z; result.rowy.w += s * mat.rowy.w; result.rowz.x += s * mat.rowz.x; result.rowz.y += s * mat.rowz.y; result.rowz.z += s * mat.rowz.z; result.rowz.w += s * mat.rowz.w; } inline void TransformPoint(CalVector4& result, const BoneTransform& m, const CalBase4& v) { result.x = m.rowx.x * v.x + m.rowx.y * v.y + m.rowx.z * v.z + m.rowx.w; result.y = m.rowy.x * v.x + m.rowy.y * v.y + m.rowy.z * v.z + m.rowy.w; result.z = m.rowz.x * v.x + m.rowz.y * v.y + m.rowz.z * v.z + m.rowz.w; } inline void TransformVector(CalVector4& result, const BoneTransform& m, const CalBase4& v) { result.x = m.rowx.x * v.x + m.rowx.y * v.y + m.rowx.z * v.z; result.y = m.rowy.x * v.x + m.rowy.y * v.y + m.rowy.z * v.z; result.z = m.rowz.x * v.x + m.rowz.y * v.y + m.rowz.z * v.z; } void calculateVerticesAndNormals_x87( const BoneTransform* boneTransforms, int vertexCount, const Vertex* vertices, const Influence* influences, CalVector4* output_vertex ) { BoneTransform total_transform; // calculate all submesh vertices while (vertexCount--) { ScaleMatrix(total_transform, boneTransforms[influences->boneId], influences->weight); while (!influences++->lastInfluenceForThisVertex) { AddScaledMatrix(total_transform, boneTransforms[influences->boneId], influences->weight); } TransformPoint(output_vertex[0], total_transform, vertices->position); TransformVector(output_vertex[1], total_transform, vertices->normal); ++vertices; output_vertex += 2; } } int main (int argc, char*argv[]) { const int N=atoi(argv[1]); const int M=atoi(argv[2]); Vertex *v = new Vertex[N]; Influence *i = new Influence[N]; for (int k = 0; k < N; ++k) { v[k].position.setAsPoint(1.0f, 2.0f, 3.0f); v[k].normal.setAsVector(0.0f, 0.0f, 1.0f); i[k].boneId = 0; i[k].weight = 1.0f; i[k].lastInfluenceForThisVertex = true; } BoneTransform bt; memset(&bt, 0, sizeof(bt)); CalVector4 *output = new CalVector4[N * 2]; for (unsigned j = 0; j < M; j++) calculateVerticesAndNormals_x87(&bt, N, v, i, output); float sum = 0; for (unsigned j = 0; j < N * 2; ++j) { sum += (output[j].x + output[j].y + output[j].z + output[j].w); } printf("blah=%f\n", sum); }