perf(hex8): prepare guarded private four-column paired tangent packet

This commit is contained in:
KOKO\Mimi
2026-10-14 20:12:20 +09:00
parent b474d127d8
commit 9b8e53dcfd
6 changed files with 498 additions and 5 deletions
@@ -0,0 +1,53 @@
#include "hex8_pair_simd.h"
#include "hex8_pair_arithmetic.h"
#if defined(FESA_HEX8_PAIR_AVX2) && defined(_MSC_VER) && defined(_M_X64)
#include <float.h>
#include <intrin.h>
#include <xmmintrin.h>
#endif
namespace fesa::hex8_internal {
void EvaluateMaterialPacketScalar(const MaterialPacketInput& input,
PairPacket* output) {
for (std::size_t lane = 0; lane < output->size(); ++lane) {
const auto first = MultiplyPair(input.deviatoric_left[lane],
input.deviatoric_right[lane]);
const auto second = MultiplyPair(input.shear_left[lane],
input.shear_right[lane]);
const auto third = MultiplyPair(input.tensor_left[lane],
input.gradient_dot[lane]);
const auto material = AddPair(AddPair(first, second), third);
(*output)[lane] = AddPair(input.accumulated[lane],
MultiplyPair(material, input.weight));
}
}
MaterialPacketEvaluator SelectMaterialPacketEvaluator() {
#if defined(FESA_HEX8_PAIR_AVX2) && defined(_MSC_VER) && defined(_M_X64)
static const bool hardware_supported = [] {
int info[4]{};
__cpuid(info, 0);
if (info[0] < 7) return false;
__cpuidex(info, 1, 0);
constexpr int required = (1 << 12) | (1 << 26) | (1 << 27) | (1 << 28);
if ((info[2] & required) != required) return false;
if ((_xgetbv(0) & 6U) != 6U) return false;
__cpuidex(info, 7, 0);
return (info[1] & (1 << 5)) != 0;
}();
if (!hardware_supported || !math_internal::ArithmeticEnvironmentSupported())
return EvaluateMaterialPacketScalar;
if ((_mm_getcsr() & 0x1f80U) != 0x1f80U)
return EvaluateMaterialPacketScalar;
unsigned int control = 0;
if (_controlfp_s(&control, 0, 0) != 0 ||
(control & _MCW_EM) != _MCW_EM)
return EvaluateMaterialPacketScalar;
return EvaluateMaterialPacketAvx2;
#else
return EvaluateMaterialPacketScalar;
#endif
}
} // namespace fesa::hex8_internal