unit emit_fetch; {$mode objfpc}{$H+} interface uses ps4_shader, ps4_pssl, spirv, srNode, srBitcast, srType, srTypes, srConst, srReg, srOp, srOpInternal, srOpUtils, srLayout, srVertLayout, srFragLayout, srVariable, srInput, srOutput, srUniform, srFlow; type TEmitFetch=class(TEmitFlow) // function GroupingVImm (regs:PPsrRegNode;rtype:TsrResourceType):TsrDataLayout; function TryShortVSharp(regs:PPsrRegNode;rtype:TsrResourceType):TsrDataLayout; function GroupingSharp (src :PPsrRegSlot;rtype:TsrResourceType):TsrDataLayout; // function get_sdst7(SDST:Byte):PsrRegSlot; function get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean; function get_sdst8(SSRC:Byte):PsrRegSlot; function get_ssrc8(SSRC:Byte):PsrRegSlot; function get_ssrc9(SSRC:Word):PsrRegSlot; function get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean; function get_vsrc8(VSRC:Byte):PsrRegSlot; function get_vdst8(VDST:Byte):PsrRegSlot; function get_sbase(SBASE,count:Byte;src:PPsrRegSlot):Boolean; function get_srsrc(SRSRC,count:Byte;src:PPsrRegSlot):Boolean; // function get_snapshot:TsrRegsSnapshot; // function fetch_ssrc8(SOFFSET:Word;rtype:TsrDataType):TsrRegNode; function fetch_ssrc9(SSRC:Word;rtype:TsrDataType):TsrRegNode; function fetch_ssrc9_pair(SSRC:Word;src:PPsrRegNode;rtype:TsrDataType):Boolean; function fetch_ssrc9_64(SSRC:Word;rtype:TsrDataType):TsrRegNode; function fetch_vsrc8(VSRC:Word;rtype:TsrDataType):TsrRegNode; function fetch_vdst8(VDST:Word;rtype:TsrDataType):TsrRegNode; function fetch_vdst8_64(VDST:Word;rtype:TsrDataType):TsrRegNode; // procedure OpCmpV(OpId:DWORD;dst0,dst1:PsrRegSlot;src0,src1:TsrRegNode); procedure OpCmpClass(dst0,dst1:PsrRegSlot;src0,src1:TsrRegNode); procedure OpCmpS(OpId:DWORD;dst:PsrRegSlot;src0,src1:TsrRegNode); procedure OpConvFloatToHalf2(dst:PsrRegSlot;src0,src1:TsrRegNode); // function AddInput(dst:PsrRegSlot;rtype:TsrDataType;itype:TpsslInputType;id:Byte=0):TsrRegNode; function AddInstance(dst:PsrRegSlot;id:Byte;step_rate:DWORD):TsrRegNode; function AddAncillary(dst:PsrRegSlot):TsrRegNode; function AddVertLayout(pLayout:TsrDataLayout;rtype:TsrDataType):TsrRegNode; function AddFragLayout(itype:TpsslInputType;rtype:TsrDataType;location:DWORD):TsrRegNode; function FetchLoad (pChain:TsrChain;rtype:TsrDataType):TsrRegNode; Procedure FetchStore(pChain:TsrChain;src:TsrRegNode); function FetchAtomic(pChain:TsrChain;OpId:DWORD;dtype:TsrDataType;src:TsrRegNode):TsrRegNode; procedure AddUserdata(dst:PsrRegSlot;offset_dw:Byte); function FetchChain(grp:TsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1;cflags:Byte=0):TsrRegNode; function MakeChain(pSlot:PsrRegSlot;grp:TsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1;cflags:Byte=0):TsrRegNode; Procedure AddVecInput(dst:PsrRegSlot;vtype,rtype:TsrDataType;itype:TpsslInputType;id:Byte); function AddPositionsInput(count:Byte):TsrVariable; function AddParametersInput(id,count:Byte):TsrVariable; function FetchUniformSimple(src:TsrDataLayout;pType:TsrType;GLC,SLC,degam:Boolean):TsrNode; function FetchImage(src:TsrDataLayout;info:TsrImageInfo):TsrNode; function FetchImageArray(src:TsrDataLayout;info:TsrImageInfo;array_count:DWORD):TsrNode; function FetchImageRuntimeArray(src:TsrDataLayout;info:TsrImageInfo):TsrNode; function FetchSampler(src:TsrDataLayout):TsrNode; function FetchOutput(etype:TpsslExportType;rtype:TsrDataType):TsrOutput; end; function GetInputRegNode(node:TsrRegNode):TsrInput; implementation function GetInputRegNode(node:TsrRegNode):TsrInput; var pSource:TsrNode; begin pSource:=GetSourceRegNode(node); Result:=pSource.specialize AsType; end; // Function GetRegPairOp(reg:TsrRegNode):TSpirvOp; var pair:TsrRegPair; begin Result:=nil; pair:=RegDown(reg).pWriter.specialize AsType; if (pair=nil) then Exit; Result:=pair.pWriter.specialize AsType; end; Function GetRegConst(reg:TsrRegNode):TsrConst; begin Result:=RegDown(reg).pWriter.specialize AsType; end; Function GetRegPairConst(reg:TsrRegNode):TsrConst; var pair:TsrRegPair; begin Result:=nil; pair:=RegDown(reg).pWriter.specialize AsType; if (pair=nil) then Exit; Result:=pair.pWriter.specialize AsType; end; function TEmitFetch.GroupingVImm(regs:PPsrRegNode;rtype:TsrResourceType):TsrDataLayout; var vsharp:TVSharpResource4; pop_1:array[0..1] of TSpirvOp; pop_2:array[0..1] of TSpirvOp; imms_p0:array[0..1] of TsrConst; imms_p1:array[0..1] of TsrConst; imms_p2:TsrConst; imms_p3:TsrConst; begin Result:=nil; if (rtype<>rtVSharp4) then Exit; imms_p2:=GetRegConst(regs[2]); imms_p3:=GetRegConst(regs[3]); if (imms_p2=nil) then Exit; if (imms_p3=nil) then Exit; pop_1[0]:=GetRegPairOp(regs[0]); pop_1[1]:=GetRegPairOp(regs[1]); //S_GETPC_B64 s[0:1] //S_ADD_U32 s0, #0x0000011C, s0 //S_ADDC_U32 s1, 0, s1 //S_MOV_B32 s2, 20 //S_MOV_B32 s3, #0x2000C004 if (pop_1[0]=nil) then Exit; if (pop_1[1]=nil) then Exit; if (pop_1[0].OpId<>srOpInternal.OpIAddExt) then Exit; if (pop_1[1].OpId<>srOpInternal.OpIAddExt) then Exit; //S_ADD_U32 imms_p0[0]:=GetRegConst(pop_1[0].ParamNode(0).AsReg); //const imms_p0[1]:=GetRegConst(pop_1[0].ParamNode(1).AsReg); //s0 //(src0+src1)+SCC pop_2[0]:=GetRegPairOp(pop_1[1].ParamNode(0).AsReg); //(src0+src1) pop_2[1]:=GetRegPairOp(pop_1[1].ParamNode(1).AsReg); //SCC if (pop_1[0]<>pop_2[1]) then Exit; //S_ADDC_U32 imms_p1[0]:=GetRegConst(pop_2[0].ParamNode(0).AsReg); imms_p1[1]:=GetRegConst(pop_2[0].ParamNode(1).AsReg); vsharp:=Default(TVSharpResource4); PQWORD(@vsharp)[0]:=imms_p0[0].AsInt32 + imms_p0[1].AsInt32; PDWORD(@vsharp)[1]:=PDWORD(@vsharp)[1] + imms_p1[0].AsInt32 + imms_p1[1].AsInt32; PDWORD(@vsharp)[2]:=imms_p2.AsInt32; PDWORD(@vsharp)[3]:=imms_p3.AsInt32; //print_vsharp(@vsharp); Result:=DataLayoutList.FetchImm(@vsharp,rtype); end; function TryDisableAnisoLod0(regs:PPsrRegNode;rtype:TsrResourceType):Boolean; var reg:TsrRegNode; pSelect:TSpirvOp; cond:TsrRegNode; pCmp:TSpirvOp; pCmp_param0:TsrRegNode; pCmp_param1:TsrRegNode; pImm:TsrConst; pBitField:TSpirvOp; pBitwiseAnd:TSpirvOp; begin Result:=False; if (rtype<>rtSSharp4) then Exit; reg:=RegDown(regs[0]); pSelect:=reg.pWriter.specialize AsType; if (pSelect=nil) then Exit; if (pSelect.OpId<>Op.OpSelect) then Exit; cond:=RegDown(pSelect.ParamNode(0).AsReg); if (cond=nil) then Exit; pCmp:=cond.pWriter.specialize AsType; if (pCmp=nil) then Exit; if (pCmp.OpId<>Op.OpIEqual) then Exit; pCmp_param0:=RegDown(pCmp.ParamNode(0).AsReg); pCmp_param1:=RegDown(pCmp.ParamNode(1).AsReg); if (pCmp_param0=nil) then Exit; if (pCmp_param1=nil) then Exit; reg:=nil; if pCmp_param0.pWriter.IsType(ntConst) then begin pImm:=pCmp_param0.pWriter.specialize AsType; if (pImm.AsUint32=0) then begin reg:=pCmp_param1; end; end; if (reg=nil) then if pCmp_param1.pWriter.IsType(ntConst) then begin pImm:=pCmp_param1.pWriter.specialize AsType; if (pImm.AsUint32=0) then begin reg:=pCmp_param0; end; end; if (reg=nil) then Exit; reg:=RegDown(reg); pBitField:=reg.pWriter.specialize AsType; if (pBitField.OpId<>Op.OpBitFieldUExtract) then Exit; pImm:=RegDown(pBitField.ParamNode(1).AsReg).pWriter.specialize AsType; if (pImm=nil) then Exit; if (pImm.AsUint32<>12) then Exit; pImm:=RegDown(pBitField.ParamNode(2).AsReg).pWriter.specialize AsType; if (pImm=nil) then Exit; if (pImm.AsUint32<>8) then Exit; reg:=RegDown(pSelect.ParamNode(1).AsReg); if (reg=nil) then Exit; pBitwiseAnd:=reg.pWriter.specialize AsType; if (pBitwiseAnd=nil) then Exit; if (pBitwiseAnd.OpId<>Op.OpBitwiseAnd) then Exit; pImm:=RegDown(pBitwiseAnd.ParamNode(0).AsReg).pWriter.specialize AsType; if (pImm<>nil) then begin if (pImm.AsUint32<>$FFFFF1FF) then Exit; end else begin pImm:=RegDown(pBitwiseAnd.ParamNode(1).AsReg).pWriter.specialize AsType; if (pImm=nil) then Exit; if (pImm.AsUint32<>$FFFFF1FF) then Exit; end; //final reg:=RegDown(pSelect.ParamNode(2).AsReg); if (reg=nil) then Exit; regs[0]:=reg; Result:=True; end; function TEmitFetch.TryShortVSharp(regs:PPsrRegNode;rtype:TsrResourceType):TsrDataLayout; var chain:TsrChains; reg:TsrRegNode; pImm:TsrConst; V2,V3:DWORD; begin Result:=nil; if (rtype<>rtVSharp4) then Exit; reg:=RegDown(regs[2]); pImm:=reg.AsConst; if (pImm=nil) then Exit; V2:=pImm.AsUint32; reg:=RegDown(regs[3]); pImm:=reg.AsConst; if (pImm=nil) then Exit; V3:=pImm.AsUint32; chain:=Default(TsrChains); chain[0]:=GetChainRegNode(regs[0]); chain[1]:=GetChainRegNode(regs[1]); Result:=DataLayoutList.Grouping(chain,rtVSharp2); if (Result<>nil) then begin Result.FData[2]:=V2; Result.FData[3]:=V3; end; end; function TEmitFetch.GroupingSharp(src:PPsrRegSlot;rtype:TsrResourceType):TsrDataLayout; type TsrRegs=array[0..7] of TsrRegNode; var regs:TsrRegs; chain:TsrChains; i,n:Byte; begin Result:=nil; chain:=Default(TsrChains); regs :=Default(TsrRegs); n:=GetResourceSizeDw(rtype); For i:=0 to n-1 do begin regs[i]:=RegDown(src[i]^.current); end; Result:=GroupingVImm(@regs,rtype); if (Result<>nil) then Exit; Result:=TryShortVSharp(@regs,rtype); if (Result<>nil) then Exit; //TODO: mark "disable_aniso" TryDisableAnisoLod0(@regs,rtype); For i:=0 to n-1 do begin chain[i]:=GetChainRegNode(regs[i]); end; Result:=DataLayoutList.Grouping(chain,rtype); end; // function TEmitFetch.get_sdst7(SDST:Byte):PsrRegSlot; begin Result:=RegsStory.get_sdst7(SDST); end; function TEmitFetch.get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean; begin Result:=RegsStory.get_sdst7_pair(SDST,dst); end; function TEmitFetch.get_sdst8(SSRC:Byte):PsrRegSlot; begin Result:=RegsStory.get_sdst8(SSRC); end; function TEmitFetch.get_ssrc8(SSRC:Byte):PsrRegSlot; begin Result:=RegsStory.get_ssrc8(SSRC); end; function TEmitFetch.get_ssrc9(SSRC:Word):PsrRegSlot; begin Result:=RegsStory.get_ssrc9(SSRC); end; function TEmitFetch.get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean; begin Result:=RegsStory.get_ssrc9_pair(SSRC,src); end; function TEmitFetch.get_vsrc8(VSRC:Byte):PsrRegSlot; begin Result:=RegsStory.get_vsrc8(VSRC); end; function TEmitFetch.get_vdst8(VDST:Byte):PsrRegSlot; begin Result:=RegsStory.get_vdst8(VDST); end; function TEmitFetch.get_sbase(SBASE,count:Byte;src:PPsrRegSlot):Boolean; begin Result:=RegsStory.get_sbase(SBASE,count,src); end; function TEmitFetch.get_srsrc(SRSRC,count:Byte;src:PPsrRegSlot):Boolean; begin Result:=RegsStory.get_srsrc(SRSRC,count,src); end; // function TEmitFetch.get_snapshot:TsrRegsSnapshot; begin Result:=RegsStory.get_snapshot; end; // function TEmitFetch.fetch_ssrc8(SOFFSET:Word;rtype:TsrDataType):TsrRegNode; Var src:PsrRegSlot; pConst:TsrConst; begin if is_const_ssrc8(SOFFSET) then begin pConst:=ConstList.Fetch_ssrc8_const(SOFFSET,0,rtype); Result:=NewImm(pConst); end else begin src:=RegsStory.get_ssrc8(SOFFSET); Assert(src^.Category<>cVectorArray,'TODO:fetch_ssrc8 cVectorArray'); Result:=MakeRead(src,rtype); end; Assert(Result<>nil,'fetch_ssrc8'); end; function TEmitFetch.fetch_ssrc9(SSRC:Word;rtype:TsrDataType):TsrRegNode; Var src:PsrRegSlot; pConst:TsrConst; begin if is_const_ssrc9(SSRC) then begin pConst:=ConstList.Fetch_ssrc9_const(SSRC,FSPI.INLINE32,rtype); Result:=NewImm(pConst); end else begin src:=RegsStory.get_ssrc9(SSRC); Assert(src^.Category<>cVectorArray,'TODO:fetch_ssrc9 cVectorArray'); Result:=MakeRead(src,rtype); end; Assert(Result<>nil,'fetch_ssrc9'); end; function TEmitFetch.fetch_ssrc9_pair(SSRC:Word;src:PPsrRegNode;rtype:TsrDataType):Boolean; Var pSlot:array[0..1] of PsrRegSlot; begin if is_const_ssrc9(SSRC) then begin src[0]:=NewImm(ConstList.Fetch_ssrc9_const(SSRC,FSPI.INLINE32,rtype)); src[1]:=NewImm(ConstList.Fetch(rtype,0)); Result:=True; end else begin pSlot[0]:=nil; pSlot[1]:=nil; Result:=RegsStory.get_ssrc9_pair(SSRC,pSlot); if not Result then Exit; src[0]:=MakeRead(pSlot[0],rtype); src[1]:=MakeRead(pSlot[1],rtype); end; end; function TEmitFetch.fetch_ssrc9_64(SSRC:Word;rtype:TsrDataType):TsrRegNode; var src:array[0..1] of TsrRegNode; dst:TsrRegNode; begin if not fetch_ssrc9_pair(SSRC,@src,dtUint32) then Assert(false); dst:=NewReg(dtVec2u); OpMakeCon(line,dst,@src); Result:=BitcastList.FetchRead(rtype,dst); end; function TEmitFetch.fetch_vsrc8(VSRC:Word;rtype:TsrDataType):TsrRegNode; var src:PsrRegSlot; begin src:=RegsStory.get_vsrc8(VSRC); Assert(src^.Category<>cVectorArray,'TODO:fetch_vsrc8 cVectorArray'); Result:=MakeRead(src,rtype); Assert(Result<>nil,'fetch_vsrc8'); end; function TEmitFetch.fetch_vdst8(VDST:Word;rtype:TsrDataType):TsrRegNode; var src:PsrRegSlot; begin src:=RegsStory.get_vdst8(VDST); Result:=MakeRead(src,rtype); Assert(Result<>nil,'fetch_vdst8'); end; function TEmitFetch.fetch_vdst8_64(VDST:Word;rtype:TsrDataType):TsrRegNode; var src:array[0..1] of TsrRegNode; begin src[0]:=fetch_vdst8(VDST+0,dtUint32); src[1]:=fetch_vdst8(VDST+1,dtUint32); if (src[0]=nil) or (src[1]=nil) then begin Assert(False); end; Result:=fetch64(@src,rtype); end; // procedure TEmitFetch.OpCmpV(OpId:DWORD;dst0,dst1:PsrRegSlot;src0,src1:TsrRegNode); Var tmp:TsrRegNode; exc:TsrRegNode; begin case OpId of Op.OpOrdered: begin //Op.OpOrdered -> (!isNan(S0) && !isNan(S1)) -> !(isNan(S0) || isNan(S1)) if (src0=src1) then begin tmp:=OpIsNanTo(src0); end else begin src0:=OpIsNanTo(src0); src1:=OpIsNanTo(src1); tmp:=OpOrTo(src0,src1); end; tmp:=OpNotTo(tmp); end; Op.OpUnordered: begin //Op.OpUnordered -> (isNan(S0) || isNan(S1)) if (src0=src1) then begin tmp:=OpIsNanTo(src0); end else begin src0:=OpIsNanTo(src0); src1:=OpIsNanTo(src1); tmp:=OpOrTo(src0,src1); end; end; else begin tmp:=NewReg(dtBool); _Op2(line,OpId,tmp,src0,src1); end; end; exc:=GetThreadBit(get_exec0,get_exec1,dtBool); exc:=OpLogicalAndTo(tmp,exc); SetThreadBit(dst0,dst1,exc); end; const fcSignalingNan = 1 shl 0; fcQuietNan = 1 shl 1; fcNegativeInfinity = 1 shl 2; fcNegativeNormal = 1 shl 3; fcNegativeDenorm = 1 shl 4; fcNegativeZero = 1 shl 5; fcPositiveZero = 1 shl 6; fcPositiveDenorm = 1 shl 7; fcPositiveNormal = 1 shl 8; fcPositiveInfinity = 1 shl 9; fcAny = (1 shl 10)-1; fcNaN = fcSignalingNan or fcQuietNan; fcInfinity = fcPositiveInfinity or fcNegativeInfinity; fcNegative = fcNegativeInfinity or fcNegativeNormal or fcNegativeDenorm or fcNegativeZero; fcPositive = fcPositiveZero or fcPositiveDenorm or fcPositiveNormal or fcPositiveInfinity; procedure TEmitFetch.OpCmpClass(dst0,dst1:PsrRegSlot;src0,src1:TsrRegNode); var rsl:TsrRegNode; ror:TsrRegNode; exc:TsrRegNode; msk:TsrConst; val:DWORD; function _test_group(val,mask:DWORD):Boolean; inline; var i:DWORD; begin i:=(val and mask); Result:=(i=0) or (i=mask); end; begin msk:=src1.AsConst; if (msk<>nil) then begin val:=msk.AsUint32; if (val and fcAny)=fcAny then begin ror:=NewImm_b(True); end else if _test_group(val,fcNaN ) or _test_group(val,fcInfinity) or _test_group(val,fcNegative) or _test_group(val,fcPositive) then begin ror:=nil; if (val and fcNaN)=fcNaN then begin rsl:=NewReg(dtBool); _Op1(line,Op.OpIsNan,rsl,src0); ror:=rsl; end; if (val and fcInfinity)=fcInfinity then begin rsl:=NewReg(dtBool); _Op1(line,Op.OpIsInf,rsl,src0); // if (ror=nil) then begin ror:=rsl; end else begin ror:=OpLogicalOrTo(ror,rsl); end; // end; if (val and fcNegative)=fcNegative then begin rsl:=NewReg(dtBool); _Op2(line,Op.OpFOrdLessThanEqual,rsl,src0,NewImm_s(dtFloat32,-0.0)); // if (ror=nil) then begin ror:=rsl; end else begin ror:=OpLogicalOrTo(ror,rsl); end; // end; if (val and fcPositive)=fcPositive then begin rsl:=NewReg(dtBool); _Op2(line,Op.OpFOrdGreaterThanEqual,rsl,src0,NewImm_s(dtFloat32,+0.0)); // if (ror=nil) then begin ror:=rsl; end else begin ror:=OpLogicalOrTo(ror,rsl); end; // end; if (ror=nil) then begin ror:=NewImm_b(False); end; end else begin Assert(false,'TODO: Unhandled mask V_CMP_CLASS_32:0x'+HexStr(val,2)); end; end else begin Assert(false,'TODO: Non const V_CMP_CLASS_32'); end; exc:=GetThreadBit(get_exec0,get_exec1,dtBool); exc:=OpLogicalAndTo(ror,exc); SetThreadBit(dst0,dst1,exc); end; procedure TEmitFetch.OpCmpS(OpId:DWORD;dst:PsrRegSlot;src0,src1:TsrRegNode); begin Op2(OpId,dtBool,dst,src0,src1); end; procedure TEmitFetch.OpConvFloatToHalf2(dst:PsrRegSlot;src0,src1:TsrRegNode); var rsl:array[0..1] of TsrRegNode; begin rsl[0]:=OpFToF(src0,dtHalf16); rsl[1]:=OpFToF(src1,dtHalf16); dst^.New(dtVec2h); OpMakeCon(line,dst^.current,@rsl); end; // function TEmitFetch.AddInput(dst:PsrRegSlot;rtype:TsrDataType;itype:TpsslInputType;id:Byte=0):TsrRegNode; var i:TsrInput; v:TsrVariable; r:TsrRegNode; begin i:=InputList.Fetch(rtype,itype,id); v:=i.pVar; r:=i.pReg; if (r=nil) then begin r:=dst^.New(rtype); i.pReg :=r; OpLoad(init_line,r,v); //one in any scope end else if (dst^.current<>r) then begin MakeCopy(dst,r); end; Result:=r; end; function TEmitFetch.AddInstance(dst:PsrRegSlot;id:Byte;step_rate:DWORD):TsrRegNode; var src:TsrRegNode; begin if (step_rate>1) then begin src:=AddInput(@RegsStory.FUnattach,dtUInt32,itVInstance,id); src:=OpIDivTo(src,step_rate); MakeCopy(dst,src); end else begin src:=AddInput(dst,dtUInt32,itVInstance,id); end; Result:=src; end; function TEmitFetch.AddAncillary(dst:PsrRegSlot):TsrRegNode; var src:array[0..2] of TsrRegNode; begin src[0]:=NewImm_q(dtUInt32,0); //vPrimType src[1]:=AddInput(@RegsStory.FUnattach,dtUInt32,itSampleId); src[2]:=AddInput(@RegsStory.FUnattach,dtUInt32,itLayer); OpPackAnc(dst,src[0],src[1],src[2]); //Render target array index[26:16], BuiltIn.Layer //Iterated sample number[11:8], BuiltIn.SampleId //Primitive type[1:0] 0..3 //IL_REGTYPE_PRIMTYPE vPrimType //The first component has sign bit = 1, this is a point. Values in other bits are undefined. //The second component has sign bit = 1, this is a line. Values in other bits are undefined. //PID ISID RTAI //01|234567|89AB|CDEF|0123456789A| //00|000000| |0000| | Result:=dst^.current; end; function TEmitFetch.AddVertLayout(pLayout:TsrDataLayout;rtype:TsrDataType):TsrRegNode; var i:TsrVertLayout; v:TsrVariable; dst:TsrRegNode; begin i:=VertLayoutList.Fetch(pLayout,rtype); v:=i.pVar; dst:=i.pReg; if (dst=nil) then begin dst:=NewReg(rtype); i.pReg:=dst; OpLoad(init_line,dst,v); //one in any scope end; Result:=dst; end; function TEmitFetch.AddFragLayout(itype:TpsslInputType;rtype:TsrDataType;location:DWORD):TsrRegNode; var i:TsrFragLayout; v:TsrVariable; dst:TsrRegNode; begin i:=FragLayoutList.Fetch(itype,location,rtype); v:=i.pVar; dst:=i.pReg; if (dst=nil) then begin dst:=NewReg(rtype); i.pReg:=dst; OpLoad(init_line,dst,v); //one in any scope end; Result:=dst; end; function TEmitFetch.FetchLoad(pChain:TsrChain;rtype:TsrDataType):TsrRegNode; begin Result:=nil; if (pChain=nil) then Exit; Result:=NewReg(rtype); pChain.FetchLoad(line,Result); end; Procedure TEmitFetch.FetchStore(pChain:TsrChain;src:TsrRegNode); begin if (pChain=nil) or (src=nil) then Exit; pChain.FetchStore(line,src); end; function TEmitFetch.FetchAtomic(pChain:TsrChain;OpId:DWORD;dtype:TsrDataType;src:TsrRegNode):TsrRegNode; var pLine:TSpirvOp; iScope,iMemorySemantics:Integer; begin if pChain.Parent.IsLocalDataShare then begin if (FExecutionModel=ExecutionModel.GLCompute) then begin //Workgroup iScope:=Scope.Workgroup; iMemorySemantics:=MemorySemantics.AcquireRelease or MemorySemantics.WorkgroupMemory; end else begin Writeln(stderr,'AtomicOP on Private memory?'); //private iScope:=Scope.Invocation; iMemorySemantics:=MemorySemantics.None; end; end else begin //Storage/uniform iScope:=Scope.Invocation; iMemorySemantics:=MemorySemantics.None; end; pLine:=AddSpirvOp(OpId); pLine.pDst :=NewReg(dtype); pLine.pType:=TypeList.Fetch(dtype); pLine.AddParam(pChain); //<-First pChain.AddLine(pLine); //<-back link //scope pLine.AddParam(NewImm_i(dtInt32,iScope)); //MemorySemantics pLine.AddParam(NewImm_i(dtInt32,iMemorySemantics)); //val pLine.AddParam(src); Result:=pLine.pDst; end; procedure TEmitFetch.AddUserdata(dst:PsrRegSlot;offset_dw:Byte); var lvl_0:TsrChainLvl_0; pLayout:TsrDataLayout; pChain:TsrChain; pReg:TsrRegNode; begin pLayout:=DataLayoutList.pRoot; lvl_0.offset:=offset_dw*4; lvl_0.size :=4; pChain:=pLayout.Fetch(@lvl_0,nil); pReg:=FetchLoad(pChain,dtUnknow); MakeCopy(dst,pReg); end; function TEmitFetch.FetchChain(grp:TsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1;cflags:Byte=0):TsrRegNode; var pChain:TsrChain; begin pChain:=grp.Fetch(lvl_0,lvl_1,cflags); Result:=FetchLoad(pChain,dtUnknow); end; function TEmitFetch.MakeChain(pSlot:PsrRegSlot;grp:TsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1;cflags:Byte=0):TsrRegNode; var pChain:TsrChain; pReg:TsrRegNode; begin pChain:=grp.Fetch(lvl_0,lvl_1,cflags); pReg:=FetchLoad(pChain,dtUnknow); MakeCopy(pSlot,pReg); Result:=pSlot^.current; end; Procedure TEmitFetch.AddVecInput(dst:PsrRegSlot;vtype,rtype:TsrDataType;itype:TpsslInputType;id:Byte); var rsl:TsrRegNode; begin rsl:=AddInput(@RegsStory.FUnattach,vtype,itype,0); OpExtract(init_line,dst^.New(rtype),rsl,id); end; function TEmitFetch.AddPositionsInput(count:Byte):TsrVariable; var i:TsrInput; t:TsrType; begin t:=TypeList.FetchArray(TypeList.Fetch(dtVec4f),count); i:=InputList.Fetch(t,itPositions,0); Result:=i.pVar; end; function TEmitFetch.AddParametersInput(id,count:Byte):TsrVariable; var i:TsrInput; t:TsrType; begin t:=TypeList.FetchArray(TypeList.Fetch(dtVec4f),count); i:=InputList.Fetch(t,itParameters,id); Result:=i.pVar; end; //// function TEmitFetch.FetchUniformSimple(src:TsrDataLayout;pType:TsrType;GLC,SLC,degam:Boolean):TsrNode; var u:TsrUniform; v:TsrVariable; r:TsrRegUniform; begin u:=UniformList.Fetch(src,pType,degam); // if (GLC) then begin u.Flags.Coherent:=True; end; // if (SLC) then begin u.Flags.Volatile:=True; end; // v:=u.pVar; r:=u.pReg; if (r.pLine=nil) then begin OpLoad(init_line,pType,r,v); //one in any scope end; Result:=r; end; function TEmitFetch.FetchImage(src:TsrDataLayout;info:TsrImageInfo):TsrNode; var pType:TsrType; begin pType:=TypeList.Fetch(info.dtype); pType:=TypeList.FetchImage(pType,info.tinfo); Result:=FetchUniformSimple(src,pType,info.GLC,info.SLC,info.degam); end; function TEmitFetch.FetchImageArray(src:TsrDataLayout;info:TsrImageInfo;array_count:DWORD):TsrNode; var pType:TsrType; begin pType:=TypeList.Fetch(info.dtype); pType:=TypeList.FetchImage(pType,info.tinfo); pType:=TypeList.FetchArray(pType,array_count); Result:=UniformList.Fetch(src,pType,info.degam); // if (info.GLC) then begin TsrUniform(Result).Flags.Coherent:=True; end; // if (info.SLC) then begin TsrUniform(Result).Flags.Volatile:=True; end; end; function TEmitFetch.FetchImageRuntimeArray(src:TsrDataLayout;info:TsrImageInfo):TsrNode; var pType:TsrType; begin pType:=TypeList.Fetch(info.dtype); pType:=TypeList.FetchImage(pType,info.tinfo); pType:=TypeList.FetchRuntimeArray(pType); Result:=UniformList.Fetch(src,pType,info.degam); // if (info.GLC) then begin TsrUniform(Result).Flags.Coherent:=True; end; // if (info.SLC) then begin TsrUniform(Result).Flags.Volatile:=True; end; end; function TEmitFetch.FetchSampler(src:TsrDataLayout):TsrNode; var pType:TsrType; begin pType:=TypeList.Fetch(dtTypeSampler); Result:=FetchUniformSimple(src,pType,False,False,False); end; function TEmitFetch.FetchOutput(etype:TpsslExportType;rtype:TsrDataType):TsrOutput; begin Result:=OutputList.Fetch(etype,rtype); end; end.