FPPS4/spirv/emit_exp.pas

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.