mirror of
https://github.com/red-prig/fpPS4.git
synced 2024-11-27 08:31:07 +00:00
198 lines
3.7 KiB
ObjectPascal
198 lines
3.7 KiB
ObjectPascal
unit emit_EXP;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
sysutils,
|
|
spirv,
|
|
ps4_pssl,
|
|
srNodes,
|
|
srLabel,
|
|
srTypes,
|
|
srReg,
|
|
srVariable,
|
|
srOutput,
|
|
srOp,
|
|
srOpUtils,
|
|
SprvEmit,
|
|
emit_op;
|
|
|
|
type
|
|
TEmit_EXP=object(TEmitOp)
|
|
procedure _emit_EXP;
|
|
end;
|
|
|
|
implementation
|
|
|
|
procedure TEmit_EXP._emit_EXP;
|
|
Var
|
|
exc:PsrRegNode;
|
|
node:PSpirvOp;
|
|
pOpBlock:PsrOpBlock;
|
|
|
|
dout:PsrVariable;
|
|
dst:PsrRegNode;
|
|
src:array[0..3] of PsrRegNode;
|
|
rsl:array[0..3] of PsrRegNode;
|
|
rtype:TsrDataType;
|
|
f,i,p:Byte;
|
|
|
|
begin
|
|
//if (VM<>0) and (EXEC<>0) = set pixel else (if DONE=1) discard pixel /(PS only)
|
|
|
|
pOpBlock:=nil;
|
|
if (FSPI.EXP.VM<>0) and (FSPI.EXP.DONE<>0) then
|
|
begin
|
|
pOpBlock:=AllocBlockOp;
|
|
pOpBlock^.SetInfo(btOther,FCursor.Adr,FCursor.Adr);
|
|
PushBlockOp(line,pOpBlock,nil);
|
|
|
|
exc:=MakeRead(@FRegsStory.EXEC[0],dtBool);
|
|
node:=AddSpirvOp(OpMakeExp);
|
|
node^.AddParam(ntReg,exc); //<-fetch read
|
|
end;
|
|
|
|
//before
|
|
if (TpsslExportType(FSPI.EXP.TGT)=etNull) //only set kill mask
|
|
or (FSPI.EXP.EN=0) then //nop
|
|
begin
|
|
if (pOpBlock<>nil) then //is pushed
|
|
begin
|
|
FMain^.PopBlock;
|
|
end;
|
|
Exit;
|
|
end;
|
|
|
|
pOpBlock:=AllocBlockOp; //down
|
|
pOpBlock^.SetInfo(btOther,FCursor.Adr,FCursor.Adr);
|
|
PushBlockOp(line,pOpBlock,nil);
|
|
|
|
//output
|
|
|
|
src[0]:=nil;
|
|
src[1]:=nil;
|
|
src[2]:=nil;
|
|
src[3]:=nil;
|
|
|
|
f:=FSPI.EXP.EN;
|
|
|
|
if (FSPI.EXP.COMPR=0) then //float32
|
|
begin
|
|
|
|
p:=PopCnt(f);
|
|
|
|
if (p=1) then
|
|
begin
|
|
Case f of
|
|
$1:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC0,dtFloat32);
|
|
$2:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC1,dtFloat32);
|
|
$4:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC2,dtFloat32);
|
|
$8:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC3,dtFloat32);
|
|
else
|
|
Assert(false);
|
|
end;
|
|
dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),dtFloat32); //output in FSPI.EXP.TGT
|
|
emit_OpStore(line,dout,src[0]);
|
|
end else
|
|
begin
|
|
|
|
Case p of
|
|
2:rtype:=dtVec2f;
|
|
3:rtype:=dtVec3f;
|
|
4:rtype:=dtVec4f;
|
|
else
|
|
Assert(false,IntToStr(p));
|
|
end;
|
|
|
|
i:=0;
|
|
if (f and $1<>0) then
|
|
begin
|
|
src[i]:=fetch_vsrc8(FSPI.EXP.VSRC0,dtFloat32);
|
|
Inc(i);
|
|
end;
|
|
if (f and $2<>0) then
|
|
begin
|
|
src[i]:=fetch_vsrc8(FSPI.EXP.VSRC1,dtFloat32);
|
|
Inc(i);
|
|
end;
|
|
if (f and $4<>0) then
|
|
begin
|
|
src[i]:=fetch_vsrc8(FSPI.EXP.VSRC2,dtFloat32);
|
|
Inc(i);
|
|
end;
|
|
if (f and $8<>0) then
|
|
begin
|
|
src[i]:=fetch_vsrc8(FSPI.EXP.VSRC3,dtFloat32);
|
|
Inc(i);
|
|
end;
|
|
|
|
dst:=emit_OpMakeVec(line,rtype,p,@src);
|
|
dst^.mark_read;
|
|
|
|
dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),rtype); //output in FSPI.EXP.TGT
|
|
emit_OpStore(line,dout,dst);
|
|
end;
|
|
|
|
end else
|
|
begin //half16
|
|
Case f of
|
|
3,
|
|
$F:
|
|
begin
|
|
fetch_vsrc8_vec2h(FSPI.EXP.VSRC0,src[0],src[1]);
|
|
fetch_vsrc8_vec2h(FSPI.EXP.VSRC1,src[2],src[3]);
|
|
end;
|
|
$C:
|
|
begin
|
|
fetch_vsrc8_vec2h(FSPI.EXP.VSRC2,src[0],src[1]);
|
|
fetch_vsrc8_vec2h(FSPI.EXP.VSRC3,src[2],src[3]);
|
|
end;
|
|
else
|
|
Assert(false);
|
|
end;
|
|
|
|
if FUseOutput16 then
|
|
begin
|
|
dst:=emit_OpMakeVec(line,dtVec4h,4,@src);
|
|
dst^.mark_read;
|
|
|
|
rtype:=dtVec4h;
|
|
end else
|
|
begin
|
|
rsl[0]:=NewReg(dtFloat32);
|
|
rsl[1]:=NewReg(dtFloat32);
|
|
rsl[2]:=NewReg(dtFloat32);
|
|
rsl[3]:=NewReg(dtFloat32);
|
|
|
|
_emit_Op1(line,Op.OpFConvert,rsl[0],src[0]);
|
|
_emit_Op1(line,Op.OpFConvert,rsl[1],src[1]);
|
|
_emit_Op1(line,Op.OpFConvert,rsl[2],src[2]);
|
|
_emit_Op1(line,Op.OpFConvert,rsl[3],src[3]);
|
|
|
|
rsl[0]^.mark_read;
|
|
rsl[1]^.mark_read;
|
|
rsl[2]^.mark_read;
|
|
rsl[3]^.mark_read;
|
|
|
|
dst:=emit_OpMakeVec(line,dtVec4f,4,@rsl);
|
|
dst^.mark_read;
|
|
|
|
rtype:=dtVec4f;
|
|
end;
|
|
|
|
dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),rtype); //output in FSPI.EXP.TGT
|
|
emit_OpStore(line,dout,dst);
|
|
end;
|
|
|
|
if (pOpBlock<>nil) then //is pushed
|
|
begin
|
|
FMain^.PopBlock;
|
|
FMain^.PopBlock;
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|