Fixed JIT error with Conjugate/Inverse

These need to be compiler intrinsics since faux types aren't supported with self.
This commit is contained in:
Boondorl 2025-05-28 15:36:20 -04:00 committed by Ricardo Luís Vaz Silva
commit e7d0991798
8 changed files with 54 additions and 39 deletions

View file

@ -172,6 +172,8 @@ xx(Sum)
xx(Unit)
xx(Angle)
xx(PlusZ)
xx(Conjugate)
xx(Inverse)
xx(ToVector)
xx(Size)
xx(Push)

View file

@ -9063,7 +9063,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx)
else if (Self->IsQuaternion())
{
// Reuse vector built-ins for quaternion
if (MethodName == NAME_Length || MethodName == NAME_LengthSquared || MethodName == NAME_Unit)
if (MethodName == NAME_Length || MethodName == NAME_LengthSquared || MethodName == NAME_Unit || MethodName == NAME_Conjugate || MethodName == NAME_Inverse)
{
if (ArgList.Size() > 0)
{
@ -10361,6 +10361,9 @@ FxExpression *FxVectorBuiltin::Resolve(FCompileContext &ctx)
ValueType = TypeFloat64;
break;
case NAME_Conjugate:
case NAME_Inverse:
assert(Self->IsQuaternion());
case NAME_Unit:
ValueType = Self->ValueType;
break;
@ -10413,6 +10416,18 @@ ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build)
build->Emit(vecSize == 2 ? OP_DIVVF2_RR : vecSize == 3 ? OP_DIVVF3_RR : OP_DIVVF4_RR, to.RegNum, op.RegNum, len.RegNum);
len.Free(build);
}
else if (Function == NAME_Conjugate)
{
build->Emit(OP_CONJQ, to.RegNum, op.RegNum);
}
else if (Function == NAME_Inverse)
{
ExpEmit len(build, REGT_FLOAT);
build->Emit(OP_DOTV4_RR, len.RegNum, op.RegNum, op.RegNum);
build->Emit(OP_CONJQ, to.RegNum, op.RegNum);
build->Emit(OP_DIVVF4_RR, to.RegNum, to.RegNum, len.RegNum);
len.Free(build);
}
else if (Function == NAME_Angle)
{
build->Emit(OP_ATAN2, to.RegNum, op.RegNum + 1, op.RegNum);

View file

@ -1396,40 +1396,6 @@ DEFINE_ACTION_FUNCTION_NATIVE(_QuatStruct, SLerp, QuatSLerp)
ACTION_RETURN_QUAT(quat);
}
void QuatConjugate(
double x, double y, double z, double w,
DQuaternion* pquat
)
{
*pquat = DQuaternion(x, y, z, w).Conjugate();
}
DEFINE_ACTION_FUNCTION_NATIVE(_QuatStruct, Conjugate, QuatConjugate)
{
PARAM_SELF_STRUCT_PROLOGUE(DQuaternion);
DQuaternion quat;
QuatConjugate(self->X, self->Y, self->Z, self->W, &quat);
ACTION_RETURN_QUAT(quat);
}
void QuatInverse(
double x, double y, double z, double w,
DQuaternion* pquat
)
{
*pquat = DQuaternion(x, y, z, w).Inverse();
}
DEFINE_ACTION_FUNCTION_NATIVE(_QuatStruct, Inverse, QuatInverse)
{
PARAM_SELF_STRUCT_PROLOGUE(DQuaternion);
DQuaternion quat;
QuatInverse(self->X, self->Y, self->Z, self->W, &quat);
ACTION_RETURN_QUAT(quat);
}
PFunction * FindFunctionPointer(PClass * cls, int fn_name)
{
auto fn = dyn_cast<PFunction>(cls->FindSymbol(ENamedName(fn_name), true));

View file

@ -1617,6 +1617,11 @@ void FuncMULQV3(void *result, double ax, double ay, double az, double aw, double
*reinterpret_cast<DVector3*>(result) = DQuaternion(ax, ay, az, aw) * DVector3(bx, by, bz);
}
void FuncCONJQ(void* result, double x, double y, double z, double w)
{
*reinterpret_cast<DQuaternion*>(result) = DQuaternion(-x, -y, -z, w);
}
void JitCompiler::EmitMULQQ_RR()
{
auto stack = GetTemporaryVectorStackStorage();
@ -1661,6 +1666,25 @@ void JitCompiler::EmitMULQV3_RR()
cc.movsd(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16));
}
void JitCompiler::EmitCONJQ()
{
auto stack = GetTemporaryVectorStackStorage();
auto tmp = newTempIntPtr();
cc.lea(tmp, stack);
auto call = CreateCall<void, void*, double, double, double, double>(FuncCONJQ);
call->setArg(0, tmp);
call->setArg(1, regF[B + 0]);
call->setArg(2, regF[B + 1]);
call->setArg(3, regF[B + 2]);
call->setArg(4, regF[B + 3]);
cc.movsd(regF[A + 0], asmjit::x86::qword_ptr(tmp, 0));
cc.movsd(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8));
cc.movsd(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16));
cc.movsd(regF[A + 3], asmjit::x86::qword_ptr(tmp, 24));
}
/////////////////////////////////////////////////////////////////////////////
// Pointer math.

View file

@ -1908,6 +1908,13 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret)
reinterpret_cast<DQuaternion&>(reg.f[A]) = q1 * q2;
}
NEXTOP;
OP(CONJQ):
ASSERTF(a + 3); ASSERTF(B + 3);
{
const DQuaternion& q = reinterpret_cast<DQuaternion&>(reg.f[B]);
reinterpret_cast<DQuaternion&>(reg.f[A]) = q.Conjugate();
}
NEXTOP;
OP(ADDA_RR):
ASSERTA(a); ASSERTA(B); ASSERTD(C);
c = reg.d[C];

View file

@ -281,6 +281,7 @@ xx(EQV4_K, beqv4, CVRK, NOP, 0, 0) // this will never be used.
// Quaternion math
xx(MULQQ_RR, mulqq, RVRVRV, NOP, 0, 0) // qA = qB * qC
xx(MULQV3_RR, mulqv3, RVRVRV, NOP, 0, 0) // qA = qB * vC
xx(CONJQ, conjq, RVRVRV, NOP, 0, 0) // qA = qB.Conjugate
// Pointer math.
xx(ADDA_RR, add, RPRPRI, NOP, 0, 0) // pA = pB + dkC

View file

@ -292,11 +292,11 @@ public:
return TVector3(r.X, r.Y, r.Z);
}
TQuaternion<vec_t> Conjugate()
TQuaternion<vec_t> Conjugate() const
{
return TQuaternion(-X, -Y, -Z, +W);
}
TQuaternion<vec_t> Inverse()
TQuaternion<vec_t> Inverse() const
{
return Conjugate() / LengthSquared();
}

View file

@ -977,11 +977,11 @@ struct QuatStruct native unsafe(internal)
native static Quat NLerp(Quat from, Quat to, double t);
native static Quat FromAngles(double yaw, double pitch, double roll);
native static Quat AxisAngle(Vector3 xyz, double angle);
native Quat Conjugate();
native Quat Inverse();
// native double Length();
// native double LengthSquared();
// native Quat Unit();
// native Quat Conjugate();
// native Quat Inverse();
}
struct ScriptSavedPos