From e7d0991798144b02133c1c03eb823e35fdfc31f8 Mon Sep 17 00:00:00 2001 From: Boondorl Date: Wed, 28 May 2025 15:36:20 -0400 Subject: [PATCH] Fixed JIT error with Conjugate/Inverse These need to be compiler intrinsics since faux types aren't supported with self. --- src/common/engine/namedef.h | 2 ++ src/common/scripting/backend/codegen.cpp | 17 +++++++++- src/common/scripting/interface/vmnatives.cpp | 34 -------------------- src/common/scripting/jit/jit_math.cpp | 24 ++++++++++++++ src/common/scripting/vm/vmexec.h | 7 ++++ src/common/scripting/vm/vmops.h | 1 + src/common/utility/quaternion.h | 4 +-- wadsrc/static/zscript/engine/base.zs | 4 +-- 8 files changed, 54 insertions(+), 39 deletions(-) diff --git a/src/common/engine/namedef.h b/src/common/engine/namedef.h index df4c574ec..5e8c9a711 100644 --- a/src/common/engine/namedef.h +++ b/src/common/engine/namedef.h @@ -172,6 +172,8 @@ xx(Sum) xx(Unit) xx(Angle) xx(PlusZ) +xx(Conjugate) +xx(Inverse) xx(ToVector) xx(Size) xx(Push) diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index b9f1aa54c..82d82d893 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -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); diff --git a/src/common/scripting/interface/vmnatives.cpp b/src/common/scripting/interface/vmnatives.cpp index 1b4cdb746..48d4ac1dc 100644 --- a/src/common/scripting/interface/vmnatives.cpp +++ b/src/common/scripting/interface/vmnatives.cpp @@ -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(cls->FindSymbol(ENamedName(fn_name), true)); diff --git a/src/common/scripting/jit/jit_math.cpp b/src/common/scripting/jit/jit_math.cpp index 24328b9d3..dd50d071f 100644 --- a/src/common/scripting/jit/jit_math.cpp +++ b/src/common/scripting/jit/jit_math.cpp @@ -1617,6 +1617,11 @@ void FuncMULQV3(void *result, double ax, double ay, double az, double aw, double *reinterpret_cast(result) = DQuaternion(ax, ay, az, aw) * DVector3(bx, by, bz); } +void FuncCONJQ(void* result, double x, double y, double z, double w) +{ + *reinterpret_cast(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(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. diff --git a/src/common/scripting/vm/vmexec.h b/src/common/scripting/vm/vmexec.h index 0d5737d25..5a9cb8cc3 100644 --- a/src/common/scripting/vm/vmexec.h +++ b/src/common/scripting/vm/vmexec.h @@ -1908,6 +1908,13 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) reinterpret_cast(reg.f[A]) = q1 * q2; } NEXTOP; + OP(CONJQ): + ASSERTF(a + 3); ASSERTF(B + 3); + { + const DQuaternion& q = reinterpret_cast(reg.f[B]); + reinterpret_cast(reg.f[A]) = q.Conjugate(); + } + NEXTOP; OP(ADDA_RR): ASSERTA(a); ASSERTA(B); ASSERTD(C); c = reg.d[C]; diff --git a/src/common/scripting/vm/vmops.h b/src/common/scripting/vm/vmops.h index 9280b746c..fa89d532a 100644 --- a/src/common/scripting/vm/vmops.h +++ b/src/common/scripting/vm/vmops.h @@ -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 diff --git a/src/common/utility/quaternion.h b/src/common/utility/quaternion.h index 9f2af2619..17c88e7bf 100644 --- a/src/common/utility/quaternion.h +++ b/src/common/utility/quaternion.h @@ -292,11 +292,11 @@ public: return TVector3(r.X, r.Y, r.Z); } - TQuaternion Conjugate() + TQuaternion Conjugate() const { return TQuaternion(-X, -Y, -Z, +W); } - TQuaternion Inverse() + TQuaternion Inverse() const { return Conjugate() / LengthSquared(); } diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index 63e315649..c57db2952 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -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