mirror of https://github.com/red-prig/fpPS4.git
385 lines
6.8 KiB
Plaintext
385 lines
6.8 KiB
Plaintext
unit emit_EXP;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
sysutils,
|
|
ps4_pssl,
|
|
si_ci_vi_merged_enum,
|
|
srCFGCursor,
|
|
srCFGParser,
|
|
srConfig,
|
|
srFlow,
|
|
srType,
|
|
srReg,
|
|
srOutput,
|
|
srOp,
|
|
srOpInternal,
|
|
emit_fetch;
|
|
|
|
type
|
|
Tdst_sel=array[0..3] of Byte;
|
|
|
|
TEmit_EXP=class(TEmitFetch)
|
|
procedure emit_EXP;
|
|
function get_export_type(TGT:Byte):TsrDataType;
|
|
function is_bindless(TGT:Byte):Boolean;
|
|
function get_export_sel(TGT:Byte):Tdst_sel;
|
|
procedure fetch_vsrc8_vec2h(VSRC:Word;var dst0,dst1:TsrRegNode);
|
|
procedure shuffle(dst_sel:Tdst_sel;rtype:TsrDataType;src:PPsrRegNode;count:Byte);
|
|
end;
|
|
|
|
implementation
|
|
|
|
const
|
|
COLOR_COUNT:array[0..31] of Byte=(
|
|
0, //COLOR_INVALID
|
|
1, //COLOR_8
|
|
1, //COLOR_16
|
|
2, //COLOR_8_8
|
|
1, //COLOR_32
|
|
2, //COLOR_16_16
|
|
3, //COLOR_10_11_11
|
|
3, //COLOR_11_11_10
|
|
4, //COLOR_10_10_10_2
|
|
4, //COLOR_2_10_10_10
|
|
4, //COLOR_8_8_8_8
|
|
2, //COLOR_32_32
|
|
4, //COLOR_16_16_16_16
|
|
3, //COLOR_RESERVED_13 //32_32_32
|
|
4, //COLOR_32_32_32_32
|
|
0, //COLOR_RESERVED_15
|
|
3, //COLOR_5_6_5
|
|
4, //COLOR_1_5_5_5
|
|
4, //COLOR_5_5_5_1
|
|
4, //COLOR_4_4_4_4
|
|
2, //COLOR_8_24
|
|
2, //COLOR_24_8
|
|
3, //COLOR_X24_8_32_FLOAT
|
|
0, //COLOR_RESERVED_23
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0
|
|
);
|
|
|
|
const
|
|
z=0;
|
|
|
|
dst_sel_ident:Tdst_sel=(4,5,6,7);
|
|
|
|
shader_swizzle_map:array[1..4,SWAP_STD..SWAP_ALT_REV] of Tdst_sel=(
|
|
(
|
|
(4,z,z,z),
|
|
(z,4,z,z),
|
|
(z,z,4,z),
|
|
(z,z,z,4)
|
|
),(
|
|
(4,5,z,z),
|
|
(4,z,z,5),
|
|
(5,4,z,z),
|
|
(5,z,z,4)
|
|
),(
|
|
(4,5,6,z),
|
|
(4,5,z,6),
|
|
(6,5,4,z),
|
|
(6,5,z,4)
|
|
),(
|
|
(4,5,6,7),
|
|
(6,5,4,7),
|
|
(7,6,5,4),
|
|
(5,6,7,4)
|
|
)
|
|
);
|
|
|
|
function TEmit_EXP.get_export_type(TGT:Byte):TsrDataType;
|
|
begin
|
|
Result:=dtFloat32;
|
|
case TpsslExportType(TGT) of
|
|
etMrt0..etMrt7:
|
|
begin
|
|
if is_bindless(TGT) then
|
|
begin
|
|
Result:=dtFloat32;
|
|
end else
|
|
case (FExportInfo[TGT].NUMBER_TYPE and 7) of
|
|
NUMBER_UINT:Result:=dtUint32;
|
|
NUMBER_SINT:Result:=dtInt32;
|
|
else;
|
|
end;
|
|
end;
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
function TEmit_EXP.is_bindless(TGT:Byte):Boolean;
|
|
begin
|
|
Result:=False;
|
|
case TpsslExportType(TGT) of
|
|
etMrt0..etMrt7:
|
|
begin
|
|
Result:=COLOR_COUNT[FExportInfo[TGT].FORMAT and 31]=0;
|
|
end;
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
function TEmit_EXP.get_export_sel(TGT:Byte):Tdst_sel;
|
|
var
|
|
i:Byte;
|
|
begin
|
|
Result:=dst_sel_ident;
|
|
case TpsslExportType(TGT) of
|
|
etMrt0..etMrt7:
|
|
begin
|
|
if is_bindless(TGT) then
|
|
begin
|
|
Result:=dst_sel_ident;
|
|
end else
|
|
begin
|
|
i:=COLOR_COUNT[FExportInfo[TGT].FORMAT and 31];
|
|
//
|
|
Result:=shader_swizzle_map[i,FExportInfo[TGT].COMP_SWAP and 3];
|
|
end;
|
|
end;
|
|
else;
|
|
end;
|
|
end;
|
|
|
|
procedure TEmit_EXP.fetch_vsrc8_vec2h(VSRC:Word;var dst0,dst1:TsrRegNode);
|
|
var
|
|
pSlot:PsrRegSlot;
|
|
dst:TsrRegNode;
|
|
begin
|
|
pSlot:=RegsStory.get_vsrc8(VSRC);
|
|
|
|
dst:=MakeRead(pSlot,dtVec2h);
|
|
Assert(dst<>nil,'fetch_vsrc8_vec2h');
|
|
|
|
dst0:=NewReg(dtHalf16);
|
|
dst1:=NewReg(dtHalf16);
|
|
|
|
OpExtract(line,dst0,dst,0);
|
|
OpExtract(line,dst1,dst,1);
|
|
end;
|
|
|
|
procedure TEmit_EXP.shuffle(dst_sel:Tdst_sel;rtype:TsrDataType;src:PPsrRegNode;count:Byte);
|
|
var
|
|
i:Byte;
|
|
dst:array[0..3] of TsrRegNode;
|
|
begin
|
|
For i:=0 to count-1 do
|
|
begin
|
|
|
|
case dst_sel[i] of
|
|
0:dst[i]:=NewImm_i(rtype.Child,0);
|
|
//1?
|
|
|
|
4:dst[i]:=src[0];
|
|
5:dst[i]:=src[1];
|
|
6:dst[i]:=src[2];
|
|
7:dst[i]:=src[3];
|
|
else;
|
|
Assert(False);
|
|
end;
|
|
|
|
end;
|
|
//
|
|
For i:=0 to count-1 do
|
|
begin
|
|
src[i]:=dst[i];
|
|
end;
|
|
end;
|
|
|
|
procedure TEmit_EXP.emit_EXP;
|
|
Var
|
|
exc:TsrRegNode;
|
|
node:TSpirvOp;
|
|
parent,pOpBlock:TsrOpBlock;
|
|
|
|
dout:TsrOutput;
|
|
dst:TsrRegNode;
|
|
src:array[0..3] of TsrRegNode;
|
|
rtype:TsrDataType;
|
|
f,i,p:DWORD;
|
|
|
|
dst_sel:Tdst_sel;
|
|
|
|
push_count:DWORD;
|
|
begin
|
|
//if (VM<>0) and (EXEC<>0) = set pixel else (if DONE=1) discard pixel /(PS only)
|
|
|
|
push_count:=0;
|
|
|
|
parent:=nil;
|
|
if (FSPI.EXP.VM<>0) and (FSPI.EXP.DONE<>0) then
|
|
begin
|
|
parent:=AllocBlockOp;
|
|
parent.SetInfo(btOther);
|
|
|
|
PushBlockOp(line,parent,Default(TsrCursor));
|
|
Inc(push_count);
|
|
|
|
exc:=GetThreadBit(get_exec0,get_exec1,dtBool);
|
|
node:=AddSpirvOp(srOpInternal.OpMakeExp);
|
|
node.AddParam(exc); //<-fetch read
|
|
end;
|
|
|
|
//before
|
|
if (TpsslExportType(FSPI.EXP.TGT)=etNull) or //only set kill mask
|
|
(FSPI.EXP.EN=0){ or //nop
|
|
is_bindless(FSPI.EXP.TGT)} then //not binded
|
|
begin
|
|
|
|
While (push_count<>0) do
|
|
begin
|
|
Main.PopBlock;
|
|
Dec(push_count);
|
|
end;
|
|
|
|
Exit;
|
|
end;
|
|
|
|
pOpBlock:=AllocBlockOp; //down
|
|
pOpBlock.SetInfo(btOther);
|
|
|
|
PushBlockOp(line,pOpBlock,Default(TsrCursor));
|
|
Inc(push_count);
|
|
|
|
if (parent<>nil) then
|
|
begin
|
|
parent .pElse:=pOpBlock; //if->else
|
|
pOpBlock.pIf :=parent; //else->if
|
|
end;
|
|
|
|
//output
|
|
|
|
src[0]:=nil;
|
|
src[1]:=nil;
|
|
src[2]:=nil;
|
|
src[3]:=nil;
|
|
|
|
f:=FSPI.EXP.EN;
|
|
|
|
if (FSPI.EXP.COMPR=0) then //float32,int32,uint32
|
|
begin
|
|
|
|
p:=PopCnt(f);
|
|
|
|
if (p=1) then
|
|
begin
|
|
//scalar
|
|
|
|
rtype:=get_export_type(FSPI.EXP.TGT);
|
|
|
|
Case f of
|
|
$1:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC0,rtype);
|
|
$2:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC1,rtype);
|
|
$4:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC2,rtype);
|
|
$8:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC3,rtype);
|
|
else
|
|
Assert(false,'FSPI.EXP.COMPR='+HexStr(f,1));
|
|
end;
|
|
|
|
//shuffle ???
|
|
|
|
dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),rtype); //output in FSPI.EXP.TGT
|
|
dout.FetchStore(line,src[0]);
|
|
end else
|
|
begin
|
|
//vector
|
|
|
|
rtype:=get_export_type(FSPI.EXP.TGT);
|
|
|
|
rtype:=rtype.AsVector(p);
|
|
|
|
i:=0;
|
|
if (f and $1<>0) then
|
|
begin
|
|
src[i]:=fetch_vsrc8(FSPI.EXP.VSRC0,rtype.Child);
|
|
Inc(i);
|
|
end;
|
|
if (f and $2<>0) then
|
|
begin
|
|
src[i]:=fetch_vsrc8(FSPI.EXP.VSRC1,rtype.Child);
|
|
Inc(i);
|
|
end;
|
|
if (f and $4<>0) then
|
|
begin
|
|
src[i]:=fetch_vsrc8(FSPI.EXP.VSRC2,rtype.Child);
|
|
Inc(i);
|
|
end;
|
|
if (f and $8<>0) then
|
|
begin
|
|
src[i]:=fetch_vsrc8(FSPI.EXP.VSRC3,rtype.Child);
|
|
Inc(i);
|
|
end;
|
|
|
|
dst_sel:=get_export_sel(FSPI.EXP.TGT);
|
|
|
|
shuffle(dst_sel,rtype,@src,p);
|
|
|
|
dst:=OpMakeVec(line,rtype,@src);
|
|
|
|
dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),rtype); //output in FSPI.EXP.TGT
|
|
dout.FetchStore(line,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,'FSPI.EXP.COMPR='+HexStr(f,1));
|
|
end;
|
|
|
|
if Config.UseOutput16 then
|
|
begin
|
|
rtype:=dtVec4h;
|
|
end else
|
|
begin
|
|
src[0]:=OpFToF(src[0],dtFloat32);
|
|
src[1]:=OpFToF(src[1],dtFloat32);
|
|
src[2]:=OpFToF(src[2],dtFloat32);
|
|
src[3]:=OpFToF(src[3],dtFloat32);
|
|
|
|
rtype:=dtVec4f;
|
|
end;
|
|
|
|
dst_sel:=get_export_sel(FSPI.EXP.TGT);
|
|
|
|
shuffle(dst_sel,rtype,@src,4);
|
|
|
|
dst:=OpMakeVec(line,rtype,@src);
|
|
|
|
dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),rtype); //output in FSPI.EXP.TGT
|
|
dout.FetchStore(line,dst);
|
|
end;
|
|
|
|
While (push_count<>0) do
|
|
begin
|
|
Main.PopBlock;
|
|
Dec(push_count);
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|