mirror of
https://github.com/red-prig/fpPS4.git
synced 2024-11-30 10:01:14 +00:00
330 lines
6.2 KiB
ObjectPascal
330 lines
6.2 KiB
ObjectPascal
unit emit_vbuf_load;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
sysutils,
|
|
ps4_pssl,
|
|
srType,
|
|
srReg,
|
|
srLayout,
|
|
emit_fetch,
|
|
srVBufInfo,
|
|
emit_vbuf_chain;
|
|
|
|
type
|
|
Tload_cache=record
|
|
info:TBuf_info;
|
|
v:TvarChain;
|
|
dst:PsrRegSlot;
|
|
elem_orig:TsrDataType;
|
|
elem_resl:TsrDataType;
|
|
elem_count:ptruint;
|
|
rsl:PsrRegNode;
|
|
elm:array[0..3] of PsrRegNode;
|
|
end;
|
|
|
|
TEmit_vbuf_load=class(TEmitFetch)
|
|
procedure buf_load(info:TBuf_info);
|
|
function convert_e(var lc:Tload_cache;src:PsrRegNode):PsrRegNode;
|
|
procedure make_load_cv_id(var lc:Tload_cache;i:Byte);
|
|
procedure make_load_ce_id(var lc:Tload_cache;i:Byte);
|
|
procedure make_load_uv_id(var lc:Tload_cache;i:Byte);
|
|
procedure make_load_ue_id(var lc:Tload_cache;i:Byte);
|
|
procedure make_load_zero(var lc:Tload_cache);
|
|
procedure make_load_one(var lc:Tload_cache);
|
|
procedure buf_load_cv(info:TBuf_info;v:TvarChain);
|
|
end;
|
|
|
|
implementation
|
|
|
|
procedure TEmit_vbuf_load.buf_load(info:TBuf_info);
|
|
var
|
|
v:TvarChain;
|
|
begin
|
|
v:=TEmit_vbuf_chain(TObject(Self)).get_chain(info);
|
|
|
|
if (v.vType=vcUniformVector) then
|
|
begin
|
|
//reset dst sel
|
|
info.dsel:=dst_sel_identity;
|
|
end;
|
|
|
|
buf_load_cv(info,v);
|
|
end;
|
|
|
|
function TEmit_vbuf_load.convert_e(var lc:Tload_cache;src:PsrRegNode):PsrRegNode;
|
|
begin
|
|
Result:=src;
|
|
if (lc.elem_resl<>lc.elem_orig) then
|
|
Case lc.info.NFMT of
|
|
BUF_NUM_FORMAT_UNORM : //Unsigned, normalized to range [0.0..1.0]; data/(1<<nbits-1)
|
|
begin
|
|
Result:=OpUToF(src,dtFloat32);
|
|
Result:=OpFMulToS(Result,1/lc.elem_orig.High);
|
|
end;
|
|
|
|
BUF_NUM_FORMAT_SNORM : //Signed, normalized to range [-1.0..1.0]; data/(1<<(nbits-1)-1) clamped
|
|
begin
|
|
Result:=OpSToF(src,dtFloat32);
|
|
Result:=OpFMulToS(Result,1/(lc.elem_orig.High shr 1));
|
|
Result:=OpFAddToS(Result,-1);
|
|
end;
|
|
|
|
BUF_NUM_FORMAT_USCALED : //Unsigned integer to float [0.0 .. (1<<nbits)-1]
|
|
begin
|
|
Result:=OpUToF(src,dtFloat32);
|
|
end;
|
|
|
|
BUF_NUM_FORMAT_SSCALED : //Signed integer to float [-(1<<(nbits-1)) ..(1<<(nbits-1))-1]
|
|
begin
|
|
Result:=OpSToF(src,dtFloat32);
|
|
end;
|
|
|
|
BUF_NUM_FORMAT_SNORM_NZ: //Signed, normalized to range [-1.0..1.0]; (data*2+1)/(1<<nbits-1)
|
|
begin
|
|
if (lc.info.GetElemSize=4) then
|
|
begin
|
|
Result:=OpSToF(src,dtFloat32);
|
|
Result:=OpFMulToS(Result,2);
|
|
Result:=OpFAddToS(Result,1);
|
|
Result:=OpFMulToS(Result,1/lc.elem_orig.High);
|
|
end else
|
|
begin
|
|
Result:=OpShlTo(src,1);
|
|
Result:=OpIAddTo(Result,1);
|
|
Result:=OpSToF(Result,dtFloat32);
|
|
Result:=OpFMulToS(Result,1/lc.elem_orig.High);
|
|
end;
|
|
end;
|
|
|
|
BUF_NUM_FORMAT_UINT :
|
|
begin
|
|
Result:=OpUToU(src,lc.elem_resl);
|
|
end;
|
|
|
|
BUF_NUM_FORMAT_SINT :
|
|
begin
|
|
Result:=OpSToS(src,lc.elem_resl);
|
|
end;
|
|
|
|
BUF_NUM_FORMAT_FLOAT :
|
|
begin
|
|
Result:=OpFToF(src,lc.elem_resl);
|
|
end;
|
|
|
|
end;
|
|
end;
|
|
|
|
procedure TEmit_vbuf_load.make_load_cv_id(var lc:Tload_cache;i:Byte);
|
|
var
|
|
rsl:PsrRegNode;
|
|
begin
|
|
rsl:=lc.rsl;
|
|
if (rsl=nil) then
|
|
begin
|
|
rsl:=FetchLoad(lc.v.data[0],lc.elem_orig.AsVector(lc.elem_count));
|
|
lc.rsl:=rsl;
|
|
end;
|
|
|
|
if (lc.elm[i]=nil) then
|
|
begin
|
|
|
|
if (lc.elem_count=1) then
|
|
begin
|
|
rsl:=convert_e(lc,rsl);
|
|
|
|
lc.elm[i]:=rsl;
|
|
end else
|
|
begin
|
|
lc.elm[i]:=NewReg(lc.elem_orig);
|
|
|
|
OpExtract(line,lc.elm[i],rsl,i);
|
|
|
|
lc.elm[i]:=convert_e(lc,lc.elm[i]);
|
|
end;
|
|
|
|
end;
|
|
|
|
MakeCopy(lc.dst,lc.elm[i]);
|
|
end;
|
|
|
|
procedure TEmit_vbuf_load.make_load_ce_id(var lc:Tload_cache;i:Byte);
|
|
var
|
|
orig,elm:PsrChain;
|
|
sum_d:PsrRegNode;
|
|
lvl_0:TsrChainLvl_0;
|
|
lvl_1:TsrChainLvl_1;
|
|
rsl:PsrRegNode;
|
|
begin
|
|
|
|
if (lc.elm[i]=nil) then
|
|
begin
|
|
orig:=lc.v.data[0];
|
|
sum_d:=orig^.pIndex;
|
|
|
|
if (i=0) then
|
|
begin
|
|
elm:=orig;
|
|
end else
|
|
begin
|
|
sum_d:=OpIAddTo(sum_d,i);
|
|
|
|
lvl_0.offset:=0;
|
|
lvl_0.size :=orig^.size;
|
|
|
|
lvl_1.pIndex:=sum_d;
|
|
lvl_1.stride:=orig^.stride;
|
|
|
|
elm:=lc.info.grp^.Fetch(@lvl_0,@lvl_1);
|
|
end;
|
|
|
|
rsl:=FetchLoad(elm,lc.elem_orig);
|
|
|
|
rsl:=convert_e(lc,rsl);
|
|
|
|
lc.elm[i]:=rsl;
|
|
end;
|
|
|
|
MakeCopy(lc.dst,lc.elm[i]);
|
|
end;
|
|
|
|
procedure TEmit_vbuf_load.make_load_uv_id(var lc:Tload_cache;i:Byte);
|
|
var
|
|
rsl,idx:PsrRegNode;
|
|
begin
|
|
|
|
rsl:=lc.rsl;
|
|
if (rsl=nil) then
|
|
begin
|
|
rsl:=NewReg(lc.elem_resl.AsVector(4));
|
|
idx:=lc.v.data[1];
|
|
|
|
OpImageRead(line,lc.v.data[0],rsl,idx);
|
|
|
|
lc.rsl:=rsl;
|
|
end;
|
|
|
|
if (lc.elm[i]=nil) then
|
|
begin
|
|
lc.dst^.New(line,lc.elem_resl);
|
|
OpExtract(line,lc.dst^.current,rsl,i);
|
|
|
|
lc.elm[i]:=lc.dst^.current;
|
|
end else
|
|
begin
|
|
MakeCopy(lc.dst,lc.elm[i]);
|
|
end;
|
|
end;
|
|
|
|
procedure TEmit_vbuf_load.make_load_ue_id(var lc:Tload_cache;i:Byte);
|
|
var
|
|
rsl,idx,sum_d:PsrRegNode;
|
|
begin
|
|
|
|
if (lc.elm[i]=nil) then
|
|
begin
|
|
idx:=lc.v.data[1];
|
|
|
|
if (i=0) then
|
|
begin
|
|
sum_d:=idx;
|
|
end else
|
|
begin
|
|
sum_d:=OpIAddTo(idx,i);
|
|
end;
|
|
|
|
rsl:=lc.dst^.New(line,lc.elem_resl);
|
|
|
|
OpImageRead(line,lc.v.data[0],rsl,sum_d);
|
|
|
|
lc.elm[i]:=rsl;
|
|
end else
|
|
begin
|
|
MakeCopy(lc.dst,lc.elm[i]);
|
|
end;
|
|
end;
|
|
|
|
procedure TEmit_vbuf_load.make_load_zero(var lc:Tload_cache);
|
|
begin
|
|
SetConst_i(lc.dst,lc.elem_resl,0);
|
|
end;
|
|
|
|
procedure TEmit_vbuf_load.make_load_one(var lc:Tload_cache);
|
|
begin
|
|
if (lc.elem_resl=dtFloat32) then
|
|
begin
|
|
SetConst_s(lc.dst,lc.elem_resl,1);
|
|
end else
|
|
begin
|
|
SetConst_i(lc.dst,lc.elem_resl,1);
|
|
end;
|
|
end;
|
|
|
|
procedure TEmit_vbuf_load.buf_load_cv(info:TBuf_info;v:TvarChain);
|
|
var
|
|
lc:Tload_cache;
|
|
|
|
i,d,count:Byte;
|
|
begin
|
|
|
|
if info.IsExtFormat then Assert(false,'TODO');
|
|
|
|
lc:=Default(Tload_cache);
|
|
lc.info :=info;
|
|
lc.v :=v;
|
|
lc.elem_resl :=info.GetResultType;
|
|
lc.elem_orig :=info.GetElemType;
|
|
lc.elem_count:=info.GetElemCount;
|
|
|
|
count:=info.count;
|
|
|
|
For i:=0 to count-1 do
|
|
begin
|
|
lc.dst:=get_vdst8(FSPI.MUBUF.VDATA+i);
|
|
if (lc.dst=nil) then Assert(false);
|
|
|
|
//0=0, 1=1, 4=R, 5=G, 6=B, 7=A
|
|
Case info.dsel[i] of
|
|
0:begin //0
|
|
make_load_zero(lc);
|
|
end;
|
|
1:begin //1
|
|
make_load_one(lc);
|
|
end;
|
|
4..7:
|
|
begin //RGBA
|
|
d:=info.dsel[i]-4;
|
|
|
|
if (d<lc.elem_count) then
|
|
begin
|
|
|
|
Case v.vType of
|
|
vcInvalid :make_load_zero(lc);
|
|
vcChainVector :make_load_cv_id(lc,d);
|
|
vcChainElement :make_load_ce_id(lc,d);
|
|
vcUniformVector :make_load_uv_id(lc,d);
|
|
vcUniformElement:make_load_ue_id(lc,d);
|
|
end;
|
|
|
|
end else
|
|
begin //as zero
|
|
make_load_zero(lc);
|
|
end;
|
|
|
|
end;
|
|
else
|
|
begin //as zero
|
|
make_load_zero(lc);
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
end.
|
|
|