Skip to content

Commit

Permalink
Implement FVector ZScript for Actor Scale
Browse files Browse the repository at this point in the history
  • Loading branch information
MrRaveYard authored and coelckers committed Jun 12, 2022
1 parent d862bf4 commit f9bf6f9
Show file tree
Hide file tree
Showing 21 changed files with 321 additions and 42 deletions.
2 changes: 2 additions & 0 deletions src/common/engine/namedef.h
Expand Up @@ -115,6 +115,8 @@ xx(State)
xx(Fixed)
xx(Vector2)
xx(Vector3)
xx(FVector2)
xx(FVector3)
xx(let)

xx(Min)
Expand Down
10 changes: 10 additions & 0 deletions src/common/engine/serializer.h
Expand Up @@ -326,6 +326,16 @@ inline FSerializer &Serialize(FSerializer &arc, const char *key, DVector2 &p, DV
return arc.Array<double>(key, &p[0], def? &(*def)[0] : nullptr, 2, true);
}

inline FSerializer& Serialize(FSerializer& arc, const char* key, FVector3& p, FVector3* def)
{
return arc.Array<float>(key, &p[0], def ? &(*def)[0] : nullptr, 3, true);
}

inline FSerializer& Serialize(FSerializer& arc, const char* key, FVector2& p, FVector2* def)
{
return arc.Array<float>(key, &p[0], def ? &(*def)[0] : nullptr, 2, true);
}

template<class T>
inline FSerializer &Serialize(FSerializer &arc, const char *key, TAngle<T> &p, TAngle<T> *def)
{
Expand Down
30 changes: 21 additions & 9 deletions src/common/scripting/backend/codegen.cpp
Expand Up @@ -1688,6 +1688,13 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx)
delete this;
return x;
}
else if ((basex->IsVector2() && IsVector2()) || (basex->IsVector3() && IsVector3()))
{
auto x = basex;
basex = nullptr;
delete this;
return x;
}
// todo: pointers to class objects.
// All other types are only compatible to themselves and have already been handled above by the equality check.
// Anything that falls through here is not compatible and must print an error.
Expand Down Expand Up @@ -2764,7 +2771,7 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx)
else if (left->IsVector() && right->IsVector())
{
// a vector2 can be added to or subtracted from a vector 3 but it needs to be the right operand.
if (left->ValueType == right->ValueType || (left->ValueType == TypeVector3 && right->ValueType == TypeVector2))
if (left->ValueType == right->ValueType || (left->IsVector3() && right->IsVector2()))
{
ValueType = left->ValueType;
}
Expand Down Expand Up @@ -2857,8 +2864,9 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build)
if (IsVector())
{
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
build->Emit(right->ValueType == TypeVector2? OP_ADDV2_RR : OP_ADDV3_RR, to.RegNum, op1.RegNum, op2.RegNum);
if (left->ValueType == TypeVector3 && right->ValueType == TypeVector2 && to.RegNum != op1.RegNum)

build->Emit(right->IsVector2() ? OP_ADDV2_RR : OP_ADDV3_RR, to.RegNum, op1.RegNum, op2.RegNum);
if (left->IsVector3() && right->IsVector2() && to.RegNum != op1.RegNum)
{
// must move the z-coordinate
build->Emit(OP_MOVEF, to.RegNum + 2, op1.RegNum + 2);
Expand Down Expand Up @@ -2890,7 +2898,7 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build)
if (IsVector())
{
assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT);
build->Emit(right->ValueType == TypeVector2 ? OP_SUBV2_RR : OP_SUBV3_RR, to.RegNum, op1.RegNum, op2.RegNum);
build->Emit(right->IsVector2() ? OP_SUBV2_RR : OP_SUBV3_RR, to.RegNum, op1.RegNum, op2.RegNum);
return to;
}
else if (ValueType->GetRegType() == REGT_FLOAT)
Expand Down Expand Up @@ -3093,11 +3101,11 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build)
int op;
if (op2.Konst)
{
op = Operator == '*' ? (ValueType == TypeVector2 ? OP_MULVF2_RK : OP_MULVF3_RK) : (ValueType == TypeVector2 ? OP_DIVVF2_RK : OP_DIVVF3_RK);
op = Operator == '*' ? (IsVector2() ? OP_MULVF2_RK : OP_MULVF3_RK) : (IsVector2() ? OP_DIVVF2_RK : OP_DIVVF3_RK);
}
else
{
op = Operator == '*' ? (ValueType == TypeVector2 ? OP_MULVF2_RR : OP_MULVF3_RR) : (ValueType == TypeVector2 ? OP_DIVVF2_RR : OP_DIVVF3_RR);
op = Operator == '*' ? (IsVector2() ? OP_MULVF2_RR : OP_MULVF3_RR) : (IsVector2() ? OP_DIVVF2_RR : OP_DIVVF3_RR);
}
op1.Free(build);
op2.Free(build);
Expand Down Expand Up @@ -9067,13 +9075,13 @@ ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build)
ExpEmit op = Self->Emit(build);
if (Function == NAME_Length)
{
build->Emit(Self->ValueType == TypeVector2 ? OP_LENV2 : OP_LENV3, to.RegNum, op.RegNum);
build->Emit(Self->ValueType == TypeVector2 || Self->ValueType == TypeFVector2 ? OP_LENV2 : OP_LENV3, to.RegNum, op.RegNum);
}
else
{
ExpEmit len(build, REGT_FLOAT);
build->Emit(Self->ValueType == TypeVector2 ? OP_LENV2 : OP_LENV3, len.RegNum, op.RegNum);
build->Emit(Self->ValueType == TypeVector2 ? OP_DIVVF2_RR : OP_DIVVF3_RR, to.RegNum, op.RegNum, len.RegNum);
build->Emit(Self->ValueType == TypeVector2 || Self->ValueType == TypeFVector2 ? OP_LENV2 : OP_LENV3, len.RegNum, op.RegNum);
build->Emit(Self->ValueType == TypeVector2 || Self->ValueType == TypeFVector2 ? OP_DIVVF2_RR : OP_DIVVF3_RR, to.RegNum, op.RegNum, len.RegNum);
len.Free(build);
}
op.Free(build);
Expand Down Expand Up @@ -10734,6 +10742,10 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build)
FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p)
:FxExpression(EFX_LocalVariableDeclaration, p)
{
// Local FVector isn't different from Vector
if (type == TypeFVector2) type = TypeVector2;
else if (type == TypeFVector3) type = TypeVector3;

ValueType = type;
VarFlags = varflags;
Name = name;
Expand Down
4 changes: 3 additions & 1 deletion src/common/scripting/backend/codegen.h
Expand Up @@ -336,7 +336,9 @@ class FxExpression
bool IsFloat() const { return ValueType->isFloat(); }
bool IsInteger() const { return ValueType->isNumeric() && ValueType->isIntCompatible(); }
bool IsPointer() const { return ValueType->isPointer(); }
bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; };
bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3 || ValueType == TypeFVector2 || ValueType == TypeFVector3; };
bool IsVector2() const { return ValueType == TypeVector2 || ValueType == TypeFVector2; };
bool IsVector3() const { return ValueType == TypeVector3 || ValueType == TypeFVector3; };
bool IsBoolCompat() const { return ValueType->isScalar(); }
bool IsObject() const { return ValueType->isObjectPointer(); }
bool IsArray() const { return ValueType->isArray() || (ValueType->isPointer() && ValueType->toPointer()->PointedType->isArray()); }
Expand Down
53 changes: 53 additions & 0 deletions src/common/scripting/core/types.cpp
Expand Up @@ -61,6 +61,8 @@ PPointer *TypeFont;
PStateLabel *TypeStateLabel;
PStruct *TypeVector2;
PStruct *TypeVector3;
PStruct* TypeFVector2;
PStruct* TypeFVector3;
PStruct *TypeColorStruct;
PStruct *TypeStringStruct;
PPointer *TypeNullPtr;
Expand Down Expand Up @@ -347,6 +349,28 @@ void PType::StaticInit()
TypeVector3->RegCount = 3;


TypeFVector2 = new PStruct(NAME_FVector2, nullptr);
TypeFVector2->AddField(NAME_X, TypeFloat32);
TypeFVector2->AddField(NAME_Y, TypeFloat32);
TypeTable.AddType(TypeFVector2, NAME_Struct);
TypeFVector2->loadOp = OP_LFV2;
TypeFVector2->storeOp = OP_SFV2;
TypeFVector2->moveOp = OP_MOVEV2;
TypeFVector2->RegType = REGT_FLOAT;
TypeFVector2->RegCount = 2;

TypeFVector3 = new PStruct(NAME_FVector3, nullptr);
TypeFVector3->AddField(NAME_X, TypeFloat32);
TypeFVector3->AddField(NAME_Y, TypeFloat32);
TypeFVector3->AddField(NAME_Z, TypeFloat32);
// allow accessing xy as a vector2
TypeFVector3->Symbols.AddSymbol(Create<PField>(NAME_XY, TypeFVector2, VARF_Transient, 0));
TypeTable.AddType(TypeFVector3, NAME_Struct);
TypeFVector3->loadOp = OP_LFV3;
TypeFVector3->storeOp = OP_SFV3;
TypeFVector3->moveOp = OP_MOVEV3;
TypeFVector3->RegType = REGT_FLOAT;
TypeFVector3->RegCount = 3;

Namespaces.GlobalNamespace->Symbols.AddSymbol(Create<PSymbolType>(NAME_sByte, TypeSInt8));
Namespaces.GlobalNamespace->Symbols.AddSymbol(Create<PSymbolType>(NAME_Byte, TypeUInt8));
Expand All @@ -366,6 +390,8 @@ void PType::StaticInit()
Namespaces.GlobalNamespace->Symbols.AddSymbol(Create<PSymbolType>(NAME_State, TypeState));
Namespaces.GlobalNamespace->Symbols.AddSymbol(Create<PSymbolType>(NAME_Vector2, TypeVector2));
Namespaces.GlobalNamespace->Symbols.AddSymbol(Create<PSymbolType>(NAME_Vector3, TypeVector3));
Namespaces.GlobalNamespace->Symbols.AddSymbol(Create<PSymbolType>(NAME_FVector2, TypeFVector2));
Namespaces.GlobalNamespace->Symbols.AddSymbol(Create<PSymbolType>(NAME_FVector3, TypeFVector3));
}


Expand Down Expand Up @@ -2321,6 +2347,33 @@ PStruct *NewStruct(FName name, PTypeBase *outer, bool native)
PPrototype::PPrototype(const TArray<PType *> &rettypes, const TArray<PType *> &argtypes)
: ArgumentTypes(argtypes), ReturnTypes(rettypes)
{
for (int i = 0; i < ArgumentTypes.Size(); ++i)
{
auto& type = ArgumentTypes[i];

if (type == TypeFVector2)
{
type = TypeVector2;
}
else if (type == TypeFVector3)
{
type = TypeVector3;
}
}

for (int i = 0; i < ReturnTypes.Size(); ++i)
{
auto& type = ReturnTypes[i];

if (type == TypeFVector2)
{
type = TypeVector2;
}
else if (type == TypeFVector3)
{
type = TypeVector3;
}
}
}

//==========================================================================
Expand Down
6 changes: 4 additions & 2 deletions src/common/scripting/core/types.h
Expand Up @@ -612,8 +612,10 @@ extern PSound *TypeSound;
extern PColor *TypeColor;
extern PTextureID *TypeTextureID;
extern PSpriteID *TypeSpriteID;
extern PStruct *TypeVector2;
extern PStruct *TypeVector3;
extern PStruct* TypeVector2;
extern PStruct* TypeVector3;
extern PStruct* TypeFVector2;
extern PStruct* TypeFVector3;
extern PStruct *TypeColorStruct;
extern PStruct *TypeStringStruct;
extern PStatePointer *TypeState;
Expand Down
20 changes: 14 additions & 6 deletions src/common/scripting/frontend/zcc_compile.cpp
Expand Up @@ -2026,7 +2026,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
do
{
auto type = DetermineType(c->Type(), f, f->Name, t, false, false);
if (type->isContainer() && type != TypeVector2 && type != TypeVector3)
if (type->isContainer() && type != TypeVector2 && type != TypeVector3 && type != TypeFVector2 && type != TypeFVector3)
{
// structs and classes only get passed by pointer.
type = NewPointer(type);
Expand All @@ -2036,6 +2036,14 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
Error(f, "The return type of a function cannot be a dynamic array");
break;
}
else if (type == TypeFVector2)
{
type = TypeVector2;
}
else if (type == TypeFVector3)
{
type = TypeVector3;
}
// TBD: disallow certain types? For now, let everything pass that isn't an array.
rets.Push(type);
t = static_cast<decltype(t)>(t->SiblingNext);
Expand Down Expand Up @@ -2222,16 +2230,16 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
else if (type->GetRegType() != REGT_NIL)
{
if (p->Flags & ZCC_Out) flags |= VARF_Out;
if (type == TypeVector2)
if (type == TypeVector2 || type == TypeFVector2)
{
elementcount = 2;
}
else if (type == TypeVector3)
else if (type == TypeVector3 || type == TypeFVector3)
{
elementcount = 3;
}
}
if (type->GetRegType() == REGT_NIL && type != TypeVector2 && type != TypeVector3)
if (type->GetRegType() == REGT_NIL && type != TypeVector2 && type != TypeVector3 && type != TypeFVector2 && type != TypeFVector3)
{
Error(p, "Invalid type %s for function parameter", type->DescriptiveName());
}
Expand Down Expand Up @@ -2268,13 +2276,13 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool
if (x != nullptr)
{
// Vectors need special treatment because they use more than one entry in the Defaults and do not report as actual constants
if (type == TypeVector2 && x->ExprType == EFX_VectorValue && static_cast<FxVectorValue *>(x)->isConstVector(2))
if ((type == TypeVector2 || type == TypeFVector2) && x->ExprType == EFX_VectorValue && static_cast<FxVectorValue *>(x)->isConstVector(2))
{
auto vx = static_cast<FxVectorValue *>(x);
vmval[0] = static_cast<FxConstant *>(vx->xyz[0])->GetValue().GetFloat();
vmval[1] = static_cast<FxConstant *>(vx->xyz[1])->GetValue().GetFloat();
}
else if (type == TypeVector3 && x->ExprType == EFX_VectorValue && static_cast<FxVectorValue *>(x)->isConstVector(3))
else if ((type == TypeVector3 || type == TypeFVector3) && x->ExprType == EFX_VectorValue && static_cast<FxVectorValue *>(x)->isConstVector(3))
{
auto vx = static_cast<FxVectorValue *>(x);
vmval[0] = static_cast<FxConstant *>(vx->xyz[0])->GetValue().GetFloat();
Expand Down
4 changes: 2 additions & 2 deletions src/common/scripting/jit/jit.cpp
Expand Up @@ -304,12 +304,12 @@ void JitCompiler::SetupSimpleFrame()
{
cc.mov(regA[rega++], x86::ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, a)));
}
else if (type == TypeVector2)
else if (type == TypeVector2 || type == TypeFVector2)
{
cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f)));
cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f)));
}
else if (type == TypeVector3)
else if (type == TypeVector3 || type == TypeFVector3)
{
cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f)));
cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f)));
Expand Down
48 changes: 48 additions & 0 deletions src/common/scripting/jit/jit_load.cpp
Expand Up @@ -325,6 +325,54 @@ void JitCompiler::EmitLV3_R()
cc.movsd(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16));
}

void JitCompiler::EmitLFV2()
{
EmitNullPointerThrow(B, X_READ_NIL);
auto tmp = newTempIntPtr();
cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], konstd[C]));
cc.movss(regF[A], asmjit::x86::qword_ptr(tmp));
cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 4));
cc.cvtss2sd(regF[A], regF[A]);
cc.cvtss2sd(regF[A + 1], regF[A + 1]);
}

void JitCompiler::EmitLFV2_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
auto tmp = newTempIntPtr();
cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C]));
cc.movss(regF[A], asmjit::x86::qword_ptr(tmp));
cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8));
cc.cvtss2sd(regF[A], regF[A]);
cc.cvtss2sd(regF[A + 1], regF[A + 1]);
}

void JitCompiler::EmitLFV3()
{
EmitNullPointerThrow(B, X_READ_NIL);
auto tmp = newTempIntPtr();
cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], konstd[C]));
cc.movss(regF[A], asmjit::x86::qword_ptr(tmp));
cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8));
cc.movss(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16));
cc.cvtss2sd(regF[A], regF[A]);
cc.cvtss2sd(regF[A + 1], regF[A + 1]);
cc.cvtss2sd(regF[A + 2], regF[A + 2]);
}

void JitCompiler::EmitLFV3_R()
{
EmitNullPointerThrow(B, X_READ_NIL);
auto tmp = newTempIntPtr();
cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C]));
cc.movss(regF[A], asmjit::x86::qword_ptr(tmp));
cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8));
cc.movss(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16));
cc.cvtss2sd(regF[A], regF[A]);
cc.cvtss2sd(regF[A + 1], regF[A + 1]);
cc.cvtss2sd(regF[A + 2], regF[A + 2]);
}

static void SetString(FString *to, char **from)
{
*to = *from;
Expand Down

0 comments on commit f9bf6f9

Please sign in to comment.