module; #include #include #include #include #include #include export module Crafter.Math:Matrix; import :BasicTypes; import :Vector; import :Misc; namespace Crafter { export template class Matrix { public: typedef typename std::conditional<(sizeof(T)* collumSize*repeats > 32 && (std::same_as || std::same_as || std::same_as || std::same_as)), __m512i, typename std::conditional<(sizeof(T)* collumSize*repeats > 16 && (std::same_as || std::same_as || std::same_as || std::same_as)), __m256i, typename std::conditional<(sizeof(T)* collumSize*repeats <= 16 && (std::same_as || std::same_as || std::same_as || std::same_as)), __m128i, typename std::conditional<(collumSize*repeats > 16 && std::same_as), __m512h, typename std::conditional<(collumSize*repeats > 8 && std::same_as), __m256h, typename std::conditional<(collumSize*repeats <= 8 && std::same_as), __m128h, typename std::conditional<(collumSize*repeats > 8 && std::same_as), __m512, typename std::conditional<(collumSize*repeats > 4 && std::same_as), __m256, typename std::conditional<(collumSize*repeats <= 4 && std::same_as), __m128, typename std::conditional<(collumSize*repeats > 4 && std::same_as), __m512d, typename std::conditional<(collumSize*repeats > 2 && std::same_as), __m256d, __m128d >::type>::type>::type>::type>::type>::type>::type>::type>::type>::type>::type collum_type; collum_type c[rowSize]; Matrix() { } Matrix(__m128 c0, __m128 c1, __m128 c2, __m128 c3) requires(collumSize == 4 && rowSize == 4 && repeats == 1 && std::same_as) { c[0] = c0; c[1] = c1; c[2] = c2; c[3] = c3; } Matrix( float x0, float y0, float z0, float w0, float x1, float y1, float z1, float w1, float x2, float y2, float z2, float w2, float x3, float y3, float z3, float w3 ) requires(collumSize == 4 && rowSize == 4 && repeats == 1 && std::same_as) { c[0] = _mm_set_ps(x3, x2, x1, x0); c[1] = _mm_set_ps(y3, y2, y1, y0); c[2] = _mm_set_ps(z3, z2, z1, z0); c[3] = _mm_set_ps(w3, w2, w1, w0); } Vector operator*(Vector b) const requires(collumSize == 4 && rowSize == 4 && repeats == 1 && std::same_as) { __m128 result = _mm_mul_ps(reinterpret_cast<__m128>(c[0]), reinterpret_cast<__m128>(b.v)); result = _mm_fmadd_ps(reinterpret_cast<__m128>(c[1]), reinterpret_cast<__m128>(b.v), result); result = _mm_fmadd_ps(reinterpret_cast<__m128>(c[2]), reinterpret_cast<__m128>(b.v), result); result = _mm_fmadd_ps(reinterpret_cast<__m128>(c[3]), reinterpret_cast<__m128>(b.v), result); return Vector(result); } // static Matrix Scaling(float x, float y, float z) requires(collums == 4 && (rowSize == 3 || rowSize == 4) && vectorSize == 1 && std::same_as) { // return Matrix( // _mm_set_ps(0, 0, 0, x), // _mm_set_ps(0, 0, y, 0), // _mm_set_ps(0, z, 0, 0), // _mm_set_ps(1, 0, 0, 0) // ); // } // static Matrix Translation(float x, float y, float z) requires(collums == 4 && (rowSize == 3 || rowSize == 4) && vectorSize == 1 && std::same_as) { // return Matrix( // _mm_set_ps(0, 0, 0, 1), // _mm_set_ps(0, 0, 1, 0), // _mm_set_ps(0, 1, 0, 0), // _mm_set_ps(1, z, y, x) // ); // } // // static Matrix Rotation(float x, float y, float z) requires(collums == 4 && (rowSize == 3 || rowSize == 4) && vectorSize == 1 && std::same_as) { // // return Matrix( // // _mm_set_ps(0, 0, 0, 1), // // _mm_set_ps(0, 0, 1, 0), // // _mm_set_ps(0, 1, 0, 0), // // _mm_set_ps(1, z, y, x) // // ); // // } // static Matrix Idenity() requires(collums == 4 && (rowSize == 3 || rowSize == 4) && vectorSize == 1 && std::same_as) { // return Matrix( // _mm_set_ps(0, 0, 0, 1), // _mm_set_ps(0, 0, 1, 0), // _mm_set_ps(0, 1, 0, 0), // _mm_set_ps(1, 0, 0, 0) // ); // } // static Matrix Projection(float FovAngleY, float AspectRatio, float NearZ, float FarZ) requires(collums == 4 && (rowSize == 3 || rowSize == 4) && vectorSize == 1 && std::same_as) { // float SinFov; // float CosFov; // XMScalarSinCos(&SinFov, &CosFov, 0.5f * FovAngleY); // float fRange = FarZ / (NearZ - FarZ); // // Note: This is recorded on the stack // float Height = CosFov / SinFov; // __m128 rMem = { // Height / AspectRatio, // Height, // fRange, // fRange * NearZ // }; // // Copy from memory to SSE register // __m128 vValues = rMem; // __m128 vTemp = _mm_setzero_ps(); // // Copy x only // vTemp = _mm_move_ss(vTemp, vValues); // // Height / AspectRatio,0,0,0 // Matrix M; // M.r[0] = vTemp; // // 0,Height,0,0 // vTemp = vValues; // vTemp = _mm_and_ps(vTemp, g_XMMaskY.v); // M.r[1] = vTemp; // // x=fRange,y=-fRange * NearZ,0,-1.0f // vTemp = _mm_setzero_ps(); // vValues = _mm_shuffle_ps(vValues, g_XMNegIdentityR3.v, _MM_SHUFFLE(3, 2, 3, 2)); // // 0,0,fRange,-1.0f // vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(3, 0, 0, 0)); // M.r[2] = vTemp; // // 0,0,fRange * NearZ,0.0f // vTemp = _mm_shuffle_ps(vTemp, vValues, _MM_SHUFFLE(2, 1, 0, 0)); // M.r[3] = vTemp; // return M; // } // template // Vector operator*(Vector b) const requires(collums == 4 && vectorRowSize == 4 && rowSize >= 4 && vectorSize == 1 && std::same_as) { // //std::cout << Vector(allX).ToString() << std::endl; // // __m128 result = _mm_permute_ps(b.v, 0b00000000); // // result = _mm_fmadd_ps(result, r[0], r[3]); // // __m128 allY = _mm_permute_ps(b.v, 0b10101010); // // result = _mm_fmadd_ps(allY, r[1], result); // // __m128 allZ = _mm_permute_ps(b.v, 0b01010101); // // return Vector(_mm_fmadd_ps(allZ, r[2], result)); // return Vector(1, 2, 3, 4); // } // Matrix operator*(Matrix b) const requires(collums == 4 && rowSize == 4 && vectorSize == 1 && std::same_as) { // Matrix result; // result.r[0] = _mm_permute_ps(b.r[0], 0b00000000); // result.r[1] = _mm_fmadd_ps(_mm_permute_ps(b.r[1], 0b00000000), reinterpret_cast<__m128>(r[1]), reinterpret_cast<__m128>(result.r[0])); // result.r[1] = _mm_permute_ps(b.r[1], 0b00000000); // result.r[2] = _mm_permute_ps(b.r[2], 0b00000000); // result.r[3] = _mm_permute_ps(b.r[3], 0b00000000); // // result.r[0] = _mm_fmadd_ps(allY, reinterpret_cast<__m128>(r[1]), reinterpret_cast<__m128>(result.r[0])); // // result.r[0] = _mm_fmadd_ps(allZ, reinterpret_cast<__m128>(r[2]), reinterpret_cast<__m128>(result.r[0])); // // result.r[0] = _mm_fmadd_ps(allW, reinterpret_cast<__m128>(r[3]), reinterpret_cast<__m128>(result.r[0])); // Float4x4 store; // result.Store(&store); // std::cout << std::format("{}", store) << std::endl; // return result; // } // void Store(Float4x4* store) const requires(collums == 4 && rowSize == 4 && vectorSize == 1 && std::same_as) { // _mm_storeu_ps(store->r1, reinterpret_cast<__m128>(r[0])); // _mm_storeu_ps(store->r2, reinterpret_cast<__m128>(r[1])); // _mm_storeu_ps(store->r3, reinterpret_cast<__m128>(r[2])); // _mm_storeu_ps(store->r4, reinterpret_cast<__m128>(r[3])); // } // // VectorVector operator*(VectorVector b) requires(collums == 4 && rowSize == 4 && vectorSize == 4 && std::same_as) { // // __m512 result = _mm512_permute_ps(b.v, 0b11111111); // // result = _mm512_fmadd_ps(result, reinterpret_cast<__m512>(r[0]), reinterpret_cast<__m512>(r[3])); // // __m512 allY = _mm512_permute_ps(b.v, 0b10101010); // // result = _mm512_fmadd_ps(allY, reinterpret_cast<__m512>(r[1]), result); // // __m512 allZ = _mm512_permute_ps(b.v, 0b01010101); // // return VectorVector(_mm512_fmadd_ps(allZ, reinterpret_cast<__m512>(r[2]), result)); // // } // // m4x4float Transpose() const { // // // x.x,x.y,y.x,y.y // // __m128 vTemp1 = _mm_shuffle_ps(r[0], r[1], _MM_SHUFFLE(1, 0, 1, 0)); // // // x.z,x.w,y.z,y.w // // __m128 vTemp3 = _mm_shuffle_ps(r[0], r[1], _MM_SHUFFLE(3, 2, 3, 2)); // // // z.x,z.y,w.x,w.y // // __m128 vTemp2 = _mm_shuffle_ps(r[2], r[3], _MM_SHUFFLE(1, 0, 1, 0)); // // // z.z,z.w,w.z,w.w // // __m128 vTemp4 = _mm_shuffle_ps(r[2], r[3], _MM_SHUFFLE(3, 2, 3, 2)); // // return m4x4float( // // _mm_shuffle_ps(vTemp1, vTemp2, _MM_SHUFFLE(2, 0, 2, 0)), // // _mm_shuffle_ps(vTemp1, vTemp2, _MM_SHUFFLE(3, 1, 3, 1)), // // _mm_shuffle_ps(vTemp3, vTemp4, _MM_SHUFFLE(2, 0, 2, 0)), // // _mm_shuffle_ps(vTemp3, vTemp4, _MM_SHUFFLE(3, 1, 3, 1)) // // ); // // } // // m4x4float operator*(m4x4float b) const { // // __m256 t0 = _mm256_castps128_ps256(r[0]); // // t0 = _mm256_insertf128_ps(t0, r[1], 1); // // __m256 t1 = _mm256_castps128_ps256(r[2]); // // t1 = _mm256_insertf128_ps(t1, r[3], 1); // // __m256 u0 = _mm256_castps128_ps256(b.r[0]); // // u0 = _mm256_insertf128_ps(u0, b.r[1], 1); // // __m256 u1 = _mm256_castps128_ps256(b.r[2]); // // u1 = _mm256_insertf128_ps(u1, b.r[3], 1); // // __m256 a0 = _mm256_shuffle_ps(t0, t0, _MM_SHUFFLE(0, 0, 0, 0)); // // __m256 a1 = _mm256_shuffle_ps(t1, t1, _MM_SHUFFLE(0, 0, 0, 0)); // // __m256 b0 = _mm256_permute2f128_ps(u0, u0, 0x00); // // __m256 c0 = _mm256_mul_ps(a0, b0); // // __m256 c1 = _mm256_mul_ps(a1, b0); // // a0 = _mm256_shuffle_ps(t0, t0, _MM_SHUFFLE(1, 1, 1, 1)); // // a1 = _mm256_shuffle_ps(t1, t1, _MM_SHUFFLE(1, 1, 1, 1)); // // b0 = _mm256_permute2f128_ps(u0, u0, 0x11); // // __m256 c2 = _mm256_fmadd_ps(a0, b0, c0); // // __m256 c3 = _mm256_fmadd_ps(a1, b0, c1); // // a0 = _mm256_shuffle_ps(t0, t0, _MM_SHUFFLE(2, 2, 2, 2)); // // a1 = _mm256_shuffle_ps(t1, t1, _MM_SHUFFLE(2, 2, 2, 2)); // // __m256 b1 = _mm256_permute2f128_ps(u1, u1, 0x00); // // __m256 c4 = _mm256_mul_ps(a0, b1); // // __m256 c5 = _mm256_mul_ps(a1, b1); // // a0 = _mm256_shuffle_ps(t0, t0, _MM_SHUFFLE(3, 3, 3, 3)); // // a1 = _mm256_shuffle_ps(t1, t1, _MM_SHUFFLE(3, 3, 3, 3)); // // b1 = _mm256_permute2f128_ps(u1, u1, 0x11); // // __m256 c6 = _mm256_fmadd_ps(a0, b1, c4); // // __m256 c7 = _mm256_fmadd_ps(a1, b1, c5); // // t0 = _mm256_add_ps(c2, c6); // // t1 = _mm256_add_ps(c3, c7); // // return m4x4float( // // _mm256_castps256_ps128(t0), // // _mm256_extractf128_ps(t0, 1), // // _mm256_castps256_ps128(t1), // // _mm256_extractf128_ps(t1, 1) // // ); // // } void Store(Crafter::Float4x4& store) const { _mm_storeu_ps(store.c1, c[0]); _mm_storeu_ps(store.c2, c[1]); _mm_storeu_ps(store.c3, c[2]); _mm_storeu_ps(store.c4, c[3]); } }; } template <> struct std::formatter> : std::formatter { auto format(const Crafter::Matrix& obj, format_context& ctx) const { Crafter::Float4x4 store; obj.Store(store); return std::formatter::format(std::format("{}", store), ctx); } };