Type
{ Tform1 }
TGLZVector4fType = packed array[0..3] of Single;
TGLZVector4f = packed record
case Byte of
0: (V: TGLZVector4fType);
1: (X, Y, Z, W: Single);
//2: (AsVector3f : TGLZVector3f);
End;
Tform1 = Class(Tform)
Label1 : Tlabel;
Label2 : Tlabel;
Label3 : Tlabel;
Procedure Formcreate(Sender : Tobject);
Procedure Formshow(Sender : Tobject);
Private
Public
vt1,vt2 : TGLZVector4f;
Fs1,Fs2 : Single;
End;
Var
Form1 : Tform1;
Implementation
{$R *.lfm}
Const cSSE_MASK_NO_W : array [0..3] of UInt32 = ($FFFFFFFF, $FFFFFFFF, $FFFFFFFF, $00000000);
function CreateVector4f(Const aX,aY,aZ,aW : Single):TGLZVector4f;
begin
Result.X := AX;
Result.Y := AY;
Result.Z := AZ;
Result.W := AW;
end;
function Vector4fToString(aVector:TGLZVector4f) : String;
begin
Result := '(X: '+FloattoStrF(aVector.X,fffixed,5,5)+
' ,Y: '+FloattoStrF(aVector.Y,fffixed,5,5)+
' ,Z: '+FloattoStrF(aVector.Z,fffixed,5,5)+
' ,W: '+FloattoStrF(aVector.W,fffixed,5,5)+')';
End;
function NativeCombine2(Const V1, V2: TGLZVector4f;Const F1, F2: Single): TGLZVector4f;
begin
Result.X:=( V1.X*F1) + (V2.X*F2);
Result.Y:=( V1.Y*F1) + (V2.Y*F2);
Result.Z:=( V2.Z*F1) + (V2.Z*F2);
Result.W:=0;
end;
function SSECombine2(Const V1, V2: TGLZVector4f; Const F1,F2: Single): TGLZVector4f;assembler;
asm
movups xmm0,[V1]
movups xmm1, [V2]
movss xmm2, F1 //---> unit1.pas(97,15) Warning: Check size of memory operand "movss: memory-operand-size is 32 bits, but expected [128 bits]"
//movlps xmm2, F1 //---> unit1.pas(97,3) Error: Asm: [movlps xmmreg,xmmreg] invalid combination of opcode and operands
//movlps xmm3, F2 //--> NO WARNING, NO ERROR , with MOVSS xmm2, F1. But wrong result
movss xmm3, F2 //--> unit1.pas(99,15) Warning: Check size of memory operand "movss: memory-operand-size is 32 bits, but expected [128 bits]"
shufps xmm2, xmm2, $00 // replicate
shufps xmm3, xmm3, $00 // replicate
mulps xmm0, xmm2 // Self * F1
mulps xmm1, xmm3 // V2 * F2
addps xmm0, xmm1 // (Self * F1) + (V2 * F2)
andps xmm0, [RIP+cSSE_MASK_NO_W]
movups [RESULT], xmm0
end;
function AVXCombine2(Const V1, V2: TGLZVector4f;Const F1, F2: Single): TGLZVector4f;assembler;
asm
vmovups xmm0,[V1]
vmovups xmm1, [V2]
// vmovss xmm2, F1 //--> unit1.pas(118,3) Error: Asm: [vmovss xmmreg,xmmreg] invalid combination of opcode and operands
//vmovlps xmm2, F1 //--> unit1.pas(119,3) Error: Asm: [vmovlps xmmreg,xmmreg] invalid combination of opcode and operands
//vmovlps xmm3, F2 // Same error here, also with vmovss
//vmovups xmm3, F1 //--> unit1.pas(122,17) Warning: Check size of memory operand "vmovups: memory-operand-size is 32 bits, but expected [128 bits]"
//vmovups xmm3, F2 //--> Idem above
// ALL ABOVE GIVE WRONG RESULT
movss xmm3, [F1] //--> Using SSE instruction give good result but always warning
movss xmm3, [F2]
vshufps xmm2, xmm2, xmm2, $00 // replicate
vshufps xmm3, xmm3, xmm3, $00 // replicate
vmulps xmm0, xmm0, xmm2 // Self * F1
vmulps xmm1, xmm1, xmm3 // V2 * F2
vaddps xmm0, xmm0, xmm1 // (Self * F1) + (V2 * F2)
vandps xmm0, xmm0, [RIP+cSSE_MASK_NO_W]
vmovups [RESULT], xmm0
end;
{ Tform1 }
Procedure Tform1.Formcreate(Sender : Tobject);
Begin
vt1:= CreateVector4f(5.850,-15.480,8.512,1.5);
vt2:= CreateVector4f(1.558,6.512,4.525,1.0);
Fs1 := 1.5;
Fs2 := 5.5;
End;
Procedure Tform1.Formshow(Sender : Tobject);
Begin
Label1.Caption := Vector4fToString(NativeCombine2(Vt1,Vt2,Fs1, Fs2));
Label2.Caption := Vector4fToString(SSECombine2(Vt1,Vt2,Fs1, Fs2));
Label3.Caption := Vector4fToString(AVXCombine2(Vt1,Vt2,Fs1, Fs2));
End;