Registriert seit: 5. Aug 2011
188 Beiträge
|
Verbesserungsvorschläge für Vector3 Class
18. Mai 2019, 02:10
Delphi-Version: 10.2 Tokyo
Ich hatte/habe Probleme eine simple, effiziente Vector3-Klasse zu finden, die außerdem auch zugriff via [] erlaubt. Habe also heute meine eigene geschrieben, habe ein paar Fragen dazu.
1) Ist es möglich Heap/Stack in Delphi immer 16 Byte zu alignen, dass ich movaps anstatt movups nutzen kann? Heap whs. via custom allocator, Stack finde ich gar keine Lösung zu.
2) Um movups überhaupt zu verwenden, musste ich 128 bit (Values: array[0..3] of Single) allocaten. Alternativ hätte ich movq/movss nutzen können, jetzt stellt sich mir allgemein die Frage was schneller ist und ob man das als extrem unschön ansehen sollte dass ich 4 anstatt 3 Singles habe. Ich sehe halt das Problem, wenn man davon ausgeht dass es 3 Werte sind und SizeOf(TVector3) macht man überrascht sein könnte.
3) Kann man das mit dem property access "[]" so wie ich es gemacht habe verbesser? Ich habe extra keinen Index check, ich rede eher von anderen Methoden, wie ich es z.B. aus c++ gewöhnt war mit operator [] überschreiben.
4) In c++ hätte ich die Vectors als const referenz übergeben. Also hier ja dann eigtl. const var? Wie geht das?
5) Allgemeine verbesserungen
Weiteres: Ich habe hier entnommen, dass ab Ryzen oder Skylake keine Performance-Unterschiede mehr sind zwischen movups/movaps (und bei neuren Prozessoren whs.).
Danke für die Hilfe!
Delphi-Quellcode:
unit UnitVector3;
interface
type TVector3 = record
private
FValues: array[0..3] of Single;
function GetValue(AIndex: Integer): Single; inline;
procedure SetValue(AIndex: Integer; AValue: Single); inline;
public
// properties
property X: Single read FValues[0] write FValues[0];
property Y: Single read FValues[1] write FValues[1];
property Z: Single read FValues[2] write FValues[2];
property Values[AIndex: Integer]: Single read GetValue write SetValue; default;
// funcs
class function Create( const AX, AY, AZ: Single): TVector3; inline; static;
procedure SetNormalize;
function Normalize: TVector3;
function Length: Single;
function LengthSquared: Single;
function Length2D: Single;
function LengthSquared2D: Single;
function Dot( const B: TVector3): Single;
function Cross( const B: TVector3): TVector3;
function Distance( const B: TVector3): Single;
function DistanceSquared( const B: TVector3): Single;
// operators
class operator Negative( const A: TVector3): TVector3; inline;
class operator Positive( const A: TVector3): TVector3; inline;
class operator Equal( const A, B: TVector3): Boolean; inline;
class operator NotEqual( const A, B: TVector3): Boolean; inline;
// Vector mit Vector
class operator Add( const A, B: TVector3): TVector3;
class operator Subtract( const A, B: TVector3): TVector3;
class operator Multiply( const A, B: TVector3): TVector3;
class operator Divide( const A, B: TVector3): TVector3;
// Vector mit Single
class operator Add( const A: TVector3; const B: Single): TVector3;
class operator Subtract( const A: TVector3; const B: Single): TVector3;
class operator Multiply( const A: TVector3; const B: Single): TVector3;
class operator Divide( const A: TVector3; const B: Single): TVector3;
// Single mit Vector
class operator Add( const A: Single; const B: TVector3): TVector3;
class operator Subtract( const A: Single; const B: TVector3): TVector3;
class operator Multiply( const A: Single; const B: TVector3): TVector3;
class operator Divide( const A: Single; const B: TVector3): TVector3;
end;
implementation
{ TVector3 }
class operator TVector3.Add( const A, B: TVector3): TVector3; assembler;
asm
movups xmm0, [A]
movups xmm1, [B]
addps xmm0, xmm1
movups [Result], xmm0
end;
class operator TVector3.Add( const A: TVector3; const B: Single): TVector3; assembler;
asm
movups xmm0, [A]
movss xmm1, [B]
shufps xmm1, xmm1, 0
addps xmm0, xmm1
movups [Result], xmm0
end;
class operator TVector3.Add( const A: Single; const B: TVector3): TVector3; assembler;
asm
movups xmm0, [B]
movss xmm1, [A]
shufps xmm1, xmm1, 0
addps xmm0, xmm1
movups [Result], xmm0
end;
class function TVector3.Create( const AX, AY, AZ: Single): TVector3;
begin
Result.X := AX;
Result.Y := AY;
Result.Z := AZ;
end;
function TVector3.Cross( const B: TVector3): TVector3; assembler;
asm
movups xmm0, [Self]
movups xmm1, [B]
movaps xmm2, xmm0
movaps xmm3, xmm1
shufps xmm0, xmm0, $C9
shufps xmm1, xmm1, $D2
mulps xmm0, xmm1
shufps xmm2, xmm2, $D2
shufps xmm3, xmm3, $C9
mulps xmm2, xmm3
subps xmm0, xmm2
movups [Result], xmm0
end;
function TVector3.Distance( const B: TVector3): Single; assembler;
asm
movups xmm0, [Self]
movups xmm1, [B]
subps xmm0, xmm1
dpps xmm0, xmm0, $71
sqrtps xmm0, xmm0
movss [Result], xmm0
end;
function TVector3.DistanceSquared( const B: TVector3): Single; assembler;
asm
movups xmm0, [Self]
movups xmm1, [B]
subps xmm0, xmm1
dpps xmm0, xmm0, $71
movss [Result], xmm0
end;
class operator TVector3.Divide( const A: Single; const B: TVector3): TVector3; assembler;
asm
movups xmm0, [B]
movss xmm1, [A]
shufps xmm1, xmm1, 0
divps xmm0, xmm1
movups [Result], xmm0
end;
function TVector3.Dot( const B: TVector3): Single; assembler;
asm
movups xmm0, [Self]
movups xmm1, [B]
dpps xmm0, xmm1, $71
movss [Result], xmm0
end;
class operator TVector3.Divide( const A: TVector3; const B: Single): TVector3; assembler;
asm
movups xmm0, [A]
movss xmm1, [B]
shufps xmm1, xmm1, 0
divps xmm0, xmm1
movups [Result], xmm0
end;
class operator TVector3.Divide( const A, B: TVector3): TVector3; assembler;
asm
movups xmm0, [A]
movups xmm1, [B]
divps xmm0, xmm1
movups [Result], xmm0
end;
class operator TVector3.Equal( const A, B: TVector3): Boolean;
begin
Result := (A.X = B.X) and (A.Y = B.Y) and (A.Z = B.Z);
end;
function TVector3.GetValue(AIndex: Integer): Single;
begin
Result := FValues[AIndex];
end;
function TVector3.Length: Single; assembler;
asm
movups xmm0, [Self]
dpps xmm0, xmm0, $71
sqrtps xmm0, xmm0
movss [Result], xmm0
end;
function TVector3.Length2D: Single; assembler;
asm
movups xmm0, [Self]
dpps xmm0, xmm0, $31
sqrtps xmm0, xmm0
movss [Result], xmm0
end;
function TVector3.LengthSquared: Single; assembler;
asm
movups xmm0, [Self]
dpps xmm0, xmm0, $71
movss [Result], xmm0
end;
function TVector3.LengthSquared2D: Single; assembler;
asm
movups xmm0, [Self]
dpps xmm0, xmm0, $31
movss [Result], xmm0
end;
class operator TVector3.Multiply( const A: Single; const B: TVector3): TVector3; assembler;
asm
movups xmm0, [B]
movss xmm1, [A]
shufps xmm1, xmm1, 0
mulps xmm0, xmm1
movups [Result], xmm0
end;
class operator TVector3.Multiply( const A: TVector3; const B: Single): TVector3; assembler;
asm
movups xmm0, [A]
movss xmm1, [B]
shufps xmm1, xmm1, 0
mulps xmm0, xmm1
movups [Result], xmm0
end;
class operator TVector3.Multiply( const A, B: TVector3): TVector3; assembler;
asm
movups xmm0, [A]
movups xmm1, [B]
mulps xmm0, xmm1
movups [Result], xmm0
end;
class operator TVector3.Negative( const A: TVector3): TVector3;
begin
Result.X := -A.X;
Result.Y := -A.Y;
Result.Z := -A.Z;
end;
function TVector3.Normalize: TVector3; assembler;
asm
movups xmm0, [Self]
movaps xmm1, xmm0
dpps xmm0, xmm0, $7F
rsqrtps xmm0, xmm0
mulps xmm0, xmm1
movups [Result], xmm0
end;
class operator TVector3.NotEqual( const A, B: TVector3): Boolean;
begin
Result := (A.X <> B.X) or (A.Y <> B.Y) or (A.Z <> B.Z);
end;
class operator TVector3.Positive( const A: TVector3): TVector3;
begin
Result := A;
end;
procedure TVector3.SetNormalize; assembler;
asm
movups xmm0, [Self]
movaps xmm1, xmm0
dpps xmm0, xmm0, $7F
rsqrtps xmm0, xmm0
mulps xmm0, xmm1
movups [Self], xmm0
end;
procedure TVector3.SetValue(AIndex: Integer; AValue: Single);
begin
FValues[AIndex] := AValue;
end;
class operator TVector3.Subtract( const A: Single; const B: TVector3): TVector3; assembler;
asm
movups xmm0, [B]
movss xmm1, [A]
shufps xmm1, xmm1, 0
subps xmm0, xmm1
movups [Result], xmm0
end;
class operator TVector3.Subtract( const A: TVector3; const B: Single): TVector3; assembler;
asm
movups xmm0, [A]
movss xmm1, [B]
shufps xmm1, xmm1, 0
subps xmm0, xmm1
movups [Result], xmm0
end;
class operator TVector3.Subtract( const A, B: TVector3): TVector3; assembler;
asm
movups xmm0, [A]
movups xmm1, [B]
subps xmm0, xmm1
movups [Result], xmm0
end;
end.
Geändert von Lyan (18. Mai 2019 um 03:06 Uhr)
|