diff --git a/spirv/SprvEmit.pas b/spirv/SprvEmit.pas index 349d74d9..c59799fd 100644 --- a/spirv/SprvEmit.pas +++ b/spirv/SprvEmit.pas @@ -6,1009 +6,131 @@ interface uses sysutils, + classes, + spirv, si_ci_vi_merged_registers, ps4_pssl, srAllocator, - srNodes, - srBitcast, - srLabel, - srCFG, - srParser, + srLiteral, + srType, srTypes, - srConst, srReg, srOp, - srOpUtils, - srCap, - srRefId, - srDecorate, - srLayout, - srVertLayout, - srFragLayout, - srBuffer, - srVariable, srInput, - srOutput, - srUniform, - spirv; + srLayout, + srFlow, + emit_fetch, + // + emit_post, + emit_alloc, + emit_print, + emit_bin; type - TLocalSize=packed record - x,y,z:DWORD; + TSprvEmit=class(TEmitFetch) + + function NewMain:PSpirvFunc; + + Destructor Destroy; override; + Constructor Create; + + procedure SetUserData(pData:Pointer); + Procedure InitVs(RSRC2:TSPI_SHADER_PGM_RSRC2_VS;instance:Byte); + Procedure InitPs(RSRC2:TSPI_SHADER_PGM_RSRC2_PS;ENA:TSPI_PS_INPUT_ENA); + Procedure InitCs(RSRC2:TCOMPUTE_PGM_RSRC2;NTX:TCOMPUTE_NUM_THREAD_X;NTY:TCOMPUTE_NUM_THREAD_Y;NTZ:TCOMPUTE_NUM_THREAD_Z); + + procedure emit_spi; override; + + Procedure PostStage; + Procedure AllocStage; + Procedure Print; + Procedure SaveToStream(Stream:TStream); end; - PSprvEmit=^TSprvEmit; - TSprvEmit=object - - FAllocator:TsrAllocator; - - FCodeHeap:TsrCodeHeap; - FCursor:TsrCursor; - - FLocalSize:TLocalSize; - - FExecutionModel:Word; - - FRegsStory:TsrRegsStory; - FVolatileID:SizeUint; - - FInputs:TsrInputList; - FDataLayouts:TsrDataLayoutList; - FVertLayouts:TsrVertLayoutList; - FFragLayouts:TsrFragLayoutList; - FBuffers:TsrBufferList; - - FOutputs:TsrOutputList; - FVariables:TsrVariableList; - FUniforms:TsrUniformList; - FCacheOps:TsrCacheOpList; - - FConsts:TsrConstList; - FBitcast:TsrBitcastList; - - FSpirvIdAlloc:TsrRefIdAlloc; - FSpirvTypes:TsrTypeList; - FSpirvFuncs:TsrFuncList; - FSpirvCaps:TsrCapList; - - FDebugInfo:TsrDebugInfoList; - FDecorates:TsrDecorateList; - - FMain:PSpirvFunc; - FInitLine:PsrOpBlock; - - FGLSL_std_450:PSpirvOp; - - FHeader:TsrOpBlockSimple; - - FSPI:TSPI; - - FPrintAsm:Boolean; - FUseVertexInput:Boolean; - FUseTexelBuffer:Boolean; - FUseOutput16:Boolean; - - function Alloc(Size:ptruint):Pointer; - - procedure SetPtr(base:Pointer;bType:TsrBlockType); - function Parse(base:Pointer):Byte; - function NextParse:Byte; - function IsFinalize:Boolean; - function FindLabel(Adr:TSrcAdr):PsrLabel; - function CheckBlockBeg:Boolean; - function CheckBlockEnd:Boolean; - procedure Finalize; - - function NewLabelOp:PSpirvOp; - function NewMain:PSpirvFunc; - - procedure AddCap(ID:DWORD); - - function AllocBlockOp:PsrOpBlock; - function NewBlockOp(Snap:TsrRegsSnapshot):PsrOpBlock; - function InsertBlockOp(pLine:PspirvOp;pChild:PsrOpBlock):PspirvOp; - Procedure PushBlockOp(pLine:PspirvOp;pOpBlock:PsrOpBlock;pLBlock:PsrCFGBlock); - function PopBlockOp:Boolean; - - function NewSpirvOp(OpId:DWORD):PSpirvOp; - function AddSpirvOp(OpId:DWORD):PSpirvOp; - function AddSpirvOp(pLine:PspirvOp;OpId:DWORD):PSpirvOp; - function AddSpirvOp(pLine,pNew:PspirvOp):PSpirvOp; - function line:PSpirvOp; - function init_line:PSpirvOp; - procedure PostLink(ntype:TsrNodeType;Data:Pointer); - procedure PostReg(pReg:PsrRegNode); - - function NewRefId:PsrRefId; - function NewVariable:PsrVariable; - - function AddInput(dst:PsrRegSlot;rtype:TsrDataType;itype:TpsslInputType;id:Byte=0):PsrRegNode; - function AllocDescVar(p:Pointer;_ntype:TsrNodeType;rtype:TsrDataType):PsrVariable; - function AddVertLayout(pLayout:PsrDataLayout;rtype:TsrDataType):PsrRegNode; - function AddFragLayout(itype:TpsslInputType;rtype:TsrDataType;location:DWORD):PsrRegNode; - function FetchLoad(pChain:PsrChain;rtype:TsrDataType):PsrRegNode; - Procedure FetchStore(pChain:PsrChain;src:PsrRegNode); - procedure AddUserdata(dst:PsrRegSlot;offset_dw:Byte); - function FetchChain(grp:PsrDataLayout;offset,size:DWORD;ext:PsrChainExt):PsrRegNode; - function MakeChain(pSlot:PsrRegSlot;grp:PsrDataLayout;offset,size:PtrUint;ext:PsrChainExt):PsrRegNode; - Procedure AddVecInput(dst:PsrRegSlot;vtype,rtype:TsrDataType;itype:TpsslInputType;id:Byte); - function FetchUniform(src:PsrDataLayout;pType:PsrType):PsrRegNode; - function FetchImage(src:PsrDataLayout;dtype:TsrDataType;info:TsrTypeImageInfo):PsrRegNode; - function FetchSampler(src:PsrDataLayout):PsrRegNode; - function FetchOutput(etype:TpsslExportType;rtype:TsrDataType):PsrVariable; - - Procedure Init; - procedure SetUserData(pData:Pointer); - Procedure InitVs(RSRC2:TSPI_SHADER_PGM_RSRC2_VS;instance:Byte); - Procedure InitPs(RSRC2:TSPI_SHADER_PGM_RSRC2_PS;ENA:TSPI_PS_INPUT_ENA); - Procedure InitCs(RSRC2:TCOMPUTE_PGM_RSRC2;NTX:TCOMPUTE_NUM_THREAD_X;NTY:TCOMPUTE_NUM_THREAD_Y;NTZ:TCOMPUTE_NUM_THREAD_Z); - - Function NewReg(rtype:TsrDataType):PsrRegNode; - Function FetchReg(pConst:PsrConst):PsrRegNode; - Procedure SetConst(pSlot:PsrRegSlot;pConst:PsrConst); - Procedure SetConst(pSlot:PsrRegSlot;dtype:TsrDataType;value:QWORD); - - function fetch_soffset(SOFFSET:Word;rtype:TsrDataType):PsrRegNode; - function fetch_ssrc9(SSRC:Word;rtype:TsrDataType):PsrRegNode; - function fetch_ssrc9_pair(src:PPsrRegNode;SSRC:Word;rtype:TsrDataType):Boolean; - function fetch_vsrc8(VSRC:Word;rtype:TsrDataType):PsrRegNode; - function fetch_vdst8(VDST:Word;rtype:TsrDataType):PsrRegNode; - procedure fetch_vsrc8_vec2h(VSRC:Word;var dst0,dst1:PsrRegNode); - - procedure _MakeCopy(dst:PsrRegSlot;src:PsrRegNode); - procedure MakeCopy(dst:PsrRegSlot;src:PsrRegNode); - - function GroupingSharp(src:PPsrRegSlot;rtype:TsrResourceType):PsrDataLayout; - - procedure PrepTypeSlot(pSlot:PsrRegSlot;rtype:TsrDataType); - - function MakeRead(pSlot:PsrRegSlot;rtype:TsrDataType):PsrRegNode; - - procedure LoadPrepType(node:PsrRegNode;p:PspirvOp;rtype:TsrDataType); - procedure RegPrepType(node:PsrRegNode;rtype:TsrDataType); - - procedure _emit_spi; - end; - -function RegDown(node:PsrRegNode):PsrRegNode; -function RegDownSlot(node:PsrRegNode):PsrRegNode; - -Procedure mark_read(const node:TOpParamSingle); -Procedure mark_write(const node:TOpParamSingle); - -function GetChainRegNode(node:PsrRegNode):PsrChain; -function GetSourceRegNode(node:PsrRegNode):TOpParamSingle; -function GetInputRegNode(node:PsrRegNode):PsrInput; - implementation uses - srVolatile, - emit_op, emit_SOP1, - emit_SOP2, emit_SOPC, emit_SOPP, - emit_SOPK, emit_VOP1, - emit_VOP2, - emit_VOP3, emit_VOPC, + emit_VOP3, + //emit_DS, emit_MUBUF, emit_MTBUF, emit_EXP, emit_VINTRP, - emit_SMRD, emit_MIMG, - emit_DS; - -function TSprvEmit.Alloc(Size:ptruint):Pointer; -begin - Result:=FAllocator.Alloc(Size); -end; - -procedure TSprvEmit.SetPtr(base:Pointer;bType:TsrBlockType); -begin - if (FCursor.Adr.get_pc=base) then Exit; - FCursor:=FCodeHeap.FetchByPtr(base,bType); -end; - -function TSprvEmit.Parse(base:Pointer):Byte; -begin - SetPtr(base,btMain); - FMain^.FTop.SetCFGBlock(FCursor.pBlock); - While (CheckBlockBeg) do; - repeat - Result:=NextParse; - Case Result of - 0:; - 1:Break; - else - Break; - end; - until false; -end; - -function TSprvEmit.NextParse:Byte; -var - FLevel:DWORD; -begin - if (FCursor.pCode=nil) then Exit(2); - if (FCursor.pBlock=nil) then Exit(3); - if (FMain=nil) then Exit(4); - if (FMain^.pBlock=nil) then Exit(5); - - - if FPrintAsm then - begin - Write(HexStr(FCursor.OFFSET_DW*4,4)); - FLevel:=0; - if (FMain<>nil) then - if (FMain^.pBlock<>nil) then - begin - FLevel:=FMain^.pBlock^.FLevel; - end; - Write(Space(FLevel+1)); - end; - - Result:=FCursor.Next(FSPI); - if (Result>1) then Exit; - - if FPrintAsm then - begin - print_spi(FSPI); - end; - - _emit_spi; - - While (CheckBlockBeg) do; - While (CheckBlockEnd) do; - - Result:=0; - if IsFinalize then - begin - Finalize; - Result:=1; - end; - -end; - -function TSprvEmit.IsFinalize:Boolean; -begin - Result:=False; - if (FMain^.pBlock^.pParent=nil) then - if FCursor.pBlock^.IsEndOf(FCursor.Adr) then - begin - Result:=True; - end; -end; - -function TSprvEmit.FindLabel(Adr:TSrcAdr):PsrLabel; -begin - Result:=nil; - if (FCursor.pCode=nil) then Exit; - Result:=FCursor.pCode^.FindLabel(Adr); -end; - -function TSprvEmit.CheckBlockBeg:Boolean; -var - pLBlock:PsrCFGBlock; - pOpLabel:array[0..3] of PspirvOp; - pOpBlock:PsrOpBlock; - pOpChild:PsrOpBlock; - adr:TSrcAdr; - Info:TsrBlockInfo; -begin - Result:=False; - adr:=FCursor.Adr; - if (FindLabel(adr)=nil) then Exit; - - pLBlock:=FCursor.pBlock^.FindBlock(adr); - if (pLBlock<>nil) then - Case pLBlock^.bType of - btLoop: - begin - TEmitVolatile(Self).make_copy_all; - - Info:=Default(TsrBlockInfo); - Info.b_adr:=pLBlock^.pBLabel^.Adr; - Info.e_adr:=pLBlock^.pELabel^.Adr; - Info.bType:=btLoop; - - pOpLabel[0]:=NewLabelOp; //continue - pOpLabel[1]:=NewLabelOp; //end - pOpLabel[2]:=NewLabelOp; //cond - pOpLabel[3]:=NewLabelOp; //start - - pOpLabel[0]^.Adr:=Info.b_adr; - pOpLabel[1]^.Adr:=Info.e_adr; - pOpLabel[2]^.Adr:=Info.e_adr; - pOpLabel[3]^.Adr:=Info.b_adr; - - pOpBlock:=NewBlockOp(FRegsStory.get_snapshot); - pOpBlock^.SetLabels(pOpLabel[0],pOpLabel[1],pOpLabel[2]); - pOpBlock^.SetInfo(Info); - - PushBlockOp(line,pOpBlock,pLBlock); - - TEmitOp(Self).emit_OpBranch(line,pOpLabel[0]); - AddSpirvOp(line,pOpLabel[0]); //continue loop - - TEmitOp(Self).emit_OpLoopMerge(line,pOpLabel[1],pOpLabel[2]); - TEmitOp(Self).emit_OpBranch(line,pOpLabel[3]); - AddSpirvOp(line,pOpLabel[3]); - - //down group - Info.bType:=btOther; - pOpChild:=AllocBlockOp; - pOpChild^.SetInfo(Info); - PushBlockOp(line,pOpChild,nil); - end; - btAdr, - btAdrBranch: //skip - begin - adr:=pLBlock^.pELabel^.Adr; - FCursor.Adr:=adr; - end; - else; - end; - -end; - -function TSprvEmit.CheckBlockEnd:Boolean; -begin - Result:=False; - if (FMain=nil) then Exit; - if (FMain^.pBlock=nil) then Exit; - - if (FMain^.pBlock^.pParent<>nil) and - FMain^.pBlock^.IsEndOf(FCursor.Adr) then - begin - Result:=PopBlockOp; - end; -end; - -procedure TSprvEmit.Finalize; -begin - if (FMain=nil) then Exit; - - if (FMain^.pBlock<>nil) then - While (FMain^.pBlock^.pParent<>nil) do - begin - PopBlockOp; - end; - - AddSpirvOp(Op.OpFunctionEnd); -end; + emit_SMRD, + emit_SOPK, + emit_SOP2, + emit_VOP2; //%void = OpTypeVoid; //%f_void = OpTypeFunction %void; //%f_main = OpFunction %void None %f_void; //%l_main = OpLabel; -function TSprvEmit.NewLabelOp:PSpirvOp; -Var - node:PSpirvOp; -begin - node:=NewSpirvOp(Op.OpLabel); - node^.dst.SetParam(ntRefId,NewRefId); - Result:=node; -end; - function TSprvEmit.NewMain:PSpirvFunc; var tvoid,tftype:PsrType; node:PspirvOp; begin - FMain:=Alloc(SizeOf(TSpirvFunc)); - FMain^.Init('main',@Alloc); - FMain^.mark_read; + Main:=Alloc(SizeOf(TSpirvFunc)); + Main^.Init('main',Self); + Main^.mark_read(nil); //depended itself //OpTypeVoid - tvoid:=FSpirvTypes.Fetch(dtTypeVoid); + tvoid:=TypeList.Fetch(dtTypeVoid); //OpTypeFunction - tftype:=FSpirvTypes.FetchFunction(tvoid); + tftype:=TypeList.FetchFunction(tvoid); //OpFunction - node:=@FMain^.FTop.dummy; + node:=@Main^.pTop^.dummy; node^.OpId:=Op.OpFunction; - node^.dst_type:=tvoid; - node^.dst.SetParam(ntFunc,FMain); //self + node^.pType:=tvoid; + node^.pDst :=Main; //self node^.AddLiteral(FunctionControl.None,'None'); - node^.AddParam(ntType,tftype); + node^.AddParam(tftype); //OpLabel - node:=NewLabelOp; - FMain^.AddSpirvOp(node); + node:=NewLabelOp(True); + Main^.AddSpirvOp(node); - Result:=FMain; + Result:=Main; end; -procedure TSprvEmit.AddCap(ID:DWORD); +Destructor TSprvEmit.Destroy; begin - FSpirvCaps.Add(ID); + Allocator.Free; + inherited; end; -function TSprvEmit.AllocBlockOp:PsrOpBlock; +Constructor TSprvEmit.Create; begin - Result:=Alloc(SizeOf(TsrOpBlock)); - Result^.Alloc:=@Alloc; - Result^.dummy.pParent:=Result; - Result^.Push_head(@Result^.dummy); -end; + InitLists; -function TSprvEmit.NewBlockOp(Snap:TsrRegsSnapshot):PsrOpBlock; -begin - Result:=AllocBlockOp; - Result^.Regs.pSnap :=Alloc(SizeOf(TsrRegsSnapshot)); - Result^.Regs.pSnap^:=Snap; - Result^.Regs.FVolMark:=vmNone; - Result^.Cond.FUseCont:=false; -end; + FuncList.Insert(NewMain); -function TSprvEmit.InsertBlockOp(pLine:PspirvOp;pChild:PsrOpBlock):PspirvOp; -begin - pLine:=AddSpirvOp(pLine,OpBlock); - pLine^.dst.SetParam(ntBlock,pChild); - pChild^.pParent:=pLine^.pParent; - pChild^.pUpLine:=pLine; - pChild^.FLevel :=pLine^.pParent^.FLevel+1; - Result:=pLine; -end; + SetConst_b(get_vcc0 ,false); //0 + SetConst_b(get_vcc1 ,false); //0 + SetConst_b(get_exec0,true ); //1 + SetConst_b(get_exec1,false); //0 -Procedure TSprvEmit.PushBlockOp(pLine:PspirvOp;pOpBlock:PsrOpBlock;pLBlock:PsrCFGBlock); -var - node:PSpirvOp; -begin - pOpBlock^.FCursor:=FCursor; //prev - - node:=AddSpirvOp(pLine,OpBlock); - node^.dst.SetParam(ntBlock,pOpBlock); - pOpBlock^.pUpLine:=node; - FMain^.PushBlock(pOpBlock); - - if (pLBlock<>nil) then - begin - FCursor.pBlock:=pLBlock; //push - end; -end; - -procedure UpdateVolMark(pBlock:PsrOpBlock); -var - pLine:PspirvOp; - pChild:PsrOpBlock; -begin - if (pBlock=nil) then Exit; - if (pBlock^.Regs.FVolMark<>vmNone) then Exit; - pLine:=pBlock^.line; - if (pLine=nil) then Exit; - if (pLine^.OpId<>OpBlock) then Exit; - pChild:=pLine^.dst.AsBlock; - if (pChild=nil) then Exit; - Case pChild^.Block.bType of - btAdr, - btAdrBranch, - btOther:; - else - Exit; - end; - pBlock^.Regs.FVolMark:=pChild^.Regs.FVolMark; -end; - -function TSprvEmit.PopBlockOp:Boolean; -var - pOpBlock:PsrOpBlock; - pOpChild:PsrOpBlock; - pOpLabel:array[0..2] of PspirvOp; - - branch_up:Boolean; - - procedure pop_cond; - begin - Assert(pOpLabel[1]<>nil); - - Case pOpBlock^.Regs.FVolMark of - vmNone:TEmitVolatile(Self).build_volatile_cur(pOpBlock^.Regs.pSnap); - vmEnd :TEmitVolatile(Self).build_volatile_dis(pOpBlock^.Regs.pSnap); - else; - end; - - if not is_term_op(line) then - begin - TEmitOp(Self).emit_OpBranch(line,pOpLabel[1]); - end; - - AddSpirvOp(line,pOpLabel[1]); //end - end; - - procedure pop_loop; - begin - //add OpLoopMerge continue - - Assert(pOpLabel[0]<>nil); - Assert(pOpLabel[1]<>nil); - Assert(pOpLabel[2]<>nil); - - Case pOpBlock^.Regs.FVolMark of - vmNone:TEmitVolatile(Self).build_volatile_old(pOpBlock^.Regs.pSnap); - else; - end; - - if pOpBlock^.Cond.FUseCont then //use continue - begin - - if not is_term_op(line) then - begin - TEmitOp(Self).emit_OpBranch(line,pOpLabel[1]); //break - end; - - AddSpirvOp(line,pOpLabel[2]); //OpLoopMerge end - - pOpChild:=AllocBlockOp; - pOpChild^.SetInfo(btOther,FCursor.Adr,FCursor.Adr); - PushBlockOp(line,pOpChild,nil); - TEmitOp(Self).emit_OpBranch(line,pOpLabel[0]); //continue - FMain^.PopBlock; - - AddSpirvOp(line,pOpLabel[1]); //end - - end else //dont used continue - begin - - if not is_term_op(line) then - begin - AddSpirvOp(line,NewLabelOp); //devide - end; - - AddSpirvOp(line,pOpLabel[2]); //OpLoopMerge end - - pOpChild:=AllocBlockOp; - pOpChild^.SetInfo(btOther,FCursor.Adr,FCursor.Adr); - PushBlockOp(line,pOpChild,nil); - TEmitOp(Self).emit_OpBranch(line,pOpLabel[1]); //break - FMain^.PopBlock; - - AddSpirvOp(line,pOpLabel[1]); //end - - end; - - end; - - procedure pop_else; - begin - if (pOpLabel[1]<>nil) then - begin - if not is_term_op(line) then - begin - TEmitOp(Self).emit_OpBranch(line,pOpLabel[1]); - end; - AddSpirvOp(line,pOpLabel[1]); - end; - end; - -begin - Result:=False; - if (FMain=nil) then Exit; - - branch_up:=False; - - repeat - - pOpBlock:=FMain^.pBlock; - if (pOpBlock=nil) then Exit; - - UpdateVolMark(pOpBlock); - - pOpLabel[0]:=pOpBlock^.Labels.pBegOp; - pOpLabel[1]:=pOpBlock^.Labels.pEndOp; - pOpLabel[2]:=pOpBlock^.Labels.pMrgOp; - - Case pOpBlock^.Block.bType of - btCond: - begin - pop_cond; - branch_up:=False; - end; - btLoop: - begin - pop_loop; - branch_up:=False; - end; - else - pop_else; - end; - - Case pOpBlock^.Block.bType of - btAdr: - begin - FCursor:=pOpBlock^.FCursor; - end; - btAdrBranch: - begin - FCursor:=pOpBlock^.FCursor; - branch_up:=True; - end; - btOther:; //nop - else - begin - FCursor.PopBlock; - end; - end; - - Result:=FMain^.PopBlock; - - until (not branch_up) or (not Result); - -end; - -function TSprvEmit.NewSpirvOp(OpId:DWORD):PSpirvOp; -begin - Result:=Alloc(SizeOf(TSpirvOp)); - Result^.adr :=FCursor.Adr; - Result^.OpId :=OpId; -end; - -function TSprvEmit.AddSpirvOp(OpId:DWORD):PSpirvOp; -begin - Result:=AddSpirvOp(line,OpId); -end; - -function TSprvEmit.AddSpirvOp(pLine:PspirvOp;OpId:DWORD):PSpirvOp; -begin - Result:=InsSpirvOp(pLine,NewSpirvOp(OpId)); -end; - -function TSprvEmit.AddSpirvOp(pLine,pNew:PspirvOp):PSpirvOp; -begin - Result:=InsSpirvOp(pLine,pNew); -end; - -function TSprvEmit.line:PSpirvOp; -begin - Result:=nil; - if (FMain<>nil) then - begin - Result:=FMain^.line; - end; -end; - -function TSprvEmit.init_line:PSpirvOp; -begin - Assert(FInitLine<>nil); - if (FInitLine^.dummy.pParent=nil) then - begin - FInitLine^.Alloc:=@Alloc; - FInitLine^.dummy.pParent:=FInitLine; - FInitLine^.Push_head(@FInitLine^.dummy); - end; - Result:=FInitLine^.line; - Assert(Result<>nil); -end; - -procedure TSprvEmit.PostLink(ntype:TsrNodeType;Data:Pointer); -var - node:PspirvOp; -begin - node:=line; - if (node=nil) or (node^.OpId<>OpLinks) then - begin - node:=AddSpirvOp(OpLinks); - end; - node^.AddParam(ntype,Data); -end; - -procedure TSprvEmit.PostReg(pReg:PsrRegNode); -begin - PostLink(ntReg,pReg); -end; - -function TSprvEmit.NewRefId:PsrRefId; -begin - Result:=Alloc(SizeOf(TsrRefId)); -end; - -function TSprvEmit.NewVariable:PsrVariable; -begin - Result:=Alloc(SizeOf(TsrVariable)); - FVariables.Push_tail(Result); -end; - -function TSprvEmit.AddInput(dst:PsrRegSlot;rtype:TsrDataType;itype:TpsslInputType;id:Byte=0):PsrRegNode; -var - i:PsrInput; - v:PsrVariable; - r:PsrRegNode; -begin - i:=FInputs.Fetch(itype,id); - v:=i^.pVar; - r:=i^.pReg; - - if (v=nil) then - begin - v:=NewVariable; - v^.dtype:=rtype; - v^.pSource.SetParam(ntInput,i); - i^.pVar:=v; - end; - - if (r=nil) then - begin - r:=dst^.New(line,rtype); - i^.pReg :=r; - v^.mark_read; - TEmitOp(Self).emit_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 TSprvEmit.AllocDescVar(p:Pointer;_ntype:TsrNodeType;rtype:TsrDataType):PsrVariable; -var - d:PsrDescriptor; -begin - Result:=nil; - if (p=nil) then Exit; - d:=p; - if (d^.pVar=nil) then - begin - d^.pVar:=NewVariable; - d^.pVar^.dtype:=rtype; - d^.pVar^.pSource.SetParam(_ntype,p); - end; - Result:=d^.pVar; -end; - -function TSprvEmit.AddVertLayout(pLayout:PsrDataLayout;rtype:TsrDataType):PsrRegNode; -var - i:PsrVertLayout; - v:PsrVariable; - dst:PsrRegNode; -begin - i:=FVertLayouts.Fetch(pLayout); - v:=AllocDescVar(i,ntVertLayout,rtype); - dst:=i^.pReg; - if (dst=nil) then - begin - dst:=NewReg(rtype); - i^.pReg:=dst; - v^.mark_read; - TEmitOp(Self).emit_OpLoad(init_line,dst,v); //one in any scope - end; - Result:=dst; -end; - -function TSprvEmit.AddFragLayout(itype:TpsslInputType;rtype:TsrDataType;location:DWORD):PsrRegNode; -var - i:PsrFragLayout; - v:PsrVariable; - dst:PsrRegNode; -begin - i:=FFragLayouts.Fetch(itype,location); - v:=AllocDescVar(i,ntFragLayout,rtype); - dst:=i^.pReg; - if (dst=nil) then - begin - dst:=NewReg(rtype); - i^.pReg:=dst; - v^.mark_read; - TEmitOp(Self).emit_OpLoad(init_line,dst,v); //one in any scope - end; - Result:=dst; -end; - -function TSprvEmit.FetchLoad(pChain:PsrChain;rtype:TsrDataType):PsrRegNode; -var - dtype:TsrDataType; - src:TOpParamSingle; -begin - Result:=nil; - if (pChain=nil) then Exit; - - dtype:=pChain^.GetRegType; - if (dtype=dtUnknow) and (rtype<>dtUnknow) then - begin - dtype:=rtype; - pChain^.SetRegType(dtype); - end; - - Result:=pChain^.rSlot.New(line,dtype); - pChain^.mark_read; - - src:=Default(TOpParamSingle); - src.SetParam(ntChain,pChain); - TEmitOp(Self).emit_OpLoad(line,FSpirvTypes.Fetch(dtype),Result,src); - - if not CompareType(dtype,rtype) then - begin - MakeCopy(@FRegsStory.FUnattach,Result); - Result:=FRegsStory.FUnattach.current; - Result^.dtype:=rtype; - end; -end; - -Procedure TSprvEmit.FetchStore(pChain:PsrChain;src:PsrRegNode); -var - dtype:TsrDataType; - dst:TOpParamSingle; - pReg:PsrRegNode; -begin - if (pChain=nil) or (src=nil) then Exit; - - dtype:=pChain^.GetRegType; - if (dtype=dtUnknow) and (src^.dtype<>dtUnknow) then - begin - dtype:=src^.dtype; - pChain^.SetRegType(dtype); - end; - - pReg:=pChain^.rSlot.New(line,dtype); - pReg^.mark_read; - pChain^.mark_write; - - dst:=Default(TOpParamSingle); - dst.SetParam(ntChain,pChain); - TEmitOp(Self).emit_OpStore(line,dst,pReg); - pReg^.pLine:=line; //update line - - pReg^.SetReg(src); -end; - -procedure TSprvEmit.AddUserdata(dst:PsrRegSlot;offset_dw:Byte); -var - pLayout:PsrDataLayout; - pChain:PsrChain; - pReg:PsrRegNode; -begin - pLayout:=FDataLayouts.Fetch(nil,0,rtBufPtr2); - pChain:=pLayout^.Fetch(offset_dw*4,4,nil); - pReg:=FetchLoad(pChain,dtUnknow); - MakeCopy(dst,pReg); -end; - -function TSprvEmit.FetchChain(grp:PsrDataLayout;offset,size:DWORD;ext:PsrChainExt):PsrRegNode; -var - pChain:PsrChain; -begin - pChain:=grp^.Fetch(offset,size,ext); - Result:=FetchLoad(pChain,dtUnknow); -end; - -function TSprvEmit.MakeChain(pSlot:PsrRegSlot;grp:PsrDataLayout;offset,size:PtrUint;ext:PsrChainExt):PsrRegNode; -var - pChain:PsrChain; - pReg:PsrRegNode; -begin - pChain:=grp^.Fetch(offset,size,ext); - pReg:=FetchLoad(pChain,dtUnknow); - MakeCopy(pSlot,pReg); - Result:=pSlot^.current; -end; - -Procedure TSprvEmit.AddVecInput(dst:PsrRegSlot;vtype,rtype:TsrDataType;itype:TpsslInputType;id:Byte); -var - rsl:PsrRegNode; -begin - rsl:=AddInput(@FRegsStory.FUnattach,vtype,itype,0); - rsl^.mark_read; - dst^.New(line,rtype); - TEmitOp(Self).emit_OpCompExtract(init_line,dst^.current,rsl,id); -end; - -//// - -function TSprvEmit.FetchUniform(src:PsrDataLayout;pType:PsrType):PsrRegNode; -var - pUniform:PsrUniform; - v:PsrVariable; - dst:PsrRegNode; - p:TOpParamSingle; -begin - pUniform:=FUniforms.Fetch(src,pType); - v:=AllocDescVar(pUniform,ntUniform,pType^.dtype); - if (v^.pType=nil) then - begin - v^.pType:=FSpirvTypes.FetchPointer(pType,pUniform^.FStorage); - end; - - dst:=pUniform^.pReg; - if (dst=nil) then - begin - dst:=NewReg(pType^.dtype); - pUniform^.pReg:=dst; - v^.mark_read; - pType^.mark_read; - p.SetParam(ntVar,v); - TEmitOp(Self).emit_OpLoad(init_line,pType,dst,p); //one in any scope - end; - Result:=dst; -end; - -function TSprvEmit.FetchImage(src:PsrDataLayout;dtype:TsrDataType;info:TsrTypeImageInfo):PsrRegNode; -var - pType:PsrType; -begin - pType:=FSpirvTypes.FetchImage(FSpirvTypes.Fetch(dtype),info); - Result:=FetchUniform(src,pType); -end; - -function TSprvEmit.FetchSampler(src:PsrDataLayout):PsrRegNode; -var - pType:PsrType; -begin - pType:=FSpirvTypes.Fetch(dtTypeSampler); - Result:=FetchUniform(src,pType); -end; - -function TSprvEmit.FetchOutput(etype:TpsslExportType;rtype:TsrDataType):PsrVariable; -var - o:PsrOutput; -begin - o:=FOutputs.Fetch(etype); - if (o^.pVar=nil) then - begin - o^.pVar:=NewVariable; - o^.pVar^.dtype:=rtype; - o^.pVar^.pSource.SetParam(ntOutput,o); - end; - o^.pVar^.mark_read; - Result:=o^.pVar; -end; - -Procedure TSprvEmit.Init; -begin - FillChar(Self,SizeOf(TSprvEmit),0); - - FUseVertexInput:=True; - - FRegsStory .Init(@Alloc); - FOutputs .Init; - FCodeHeap .Alloc:=@Alloc; - FInputs .Init(@Alloc); - FDataLayouts.Init(@Alloc); - FVertLayouts.Init(@Alloc); - FFragLayouts.Alloc:=@Alloc; - FBuffers .Init(@Alloc); - FUniforms .Alloc:=@Alloc; - FCacheOps .Alloc:=@Alloc; - FConsts .Alloc:=@Alloc; - FBitcast .pRoot:=@Self; - FSpirvTypes .Alloc:=@Alloc; - FSpirvCaps .Alloc:=@Alloc; - - FDebugInfo .Init(@Alloc); - FDecorates .Init(@Alloc); - - FHeader .Init(@Alloc); - - FSpirvFuncs.Insert(NewMain); - - SetConst(@FRegsStory.VCC[0] ,dtBool,0); - SetConst(@FRegsStory.VCC[1] ,dtBool,0); - SetConst(@FRegsStory.EXEC[0],dtBool,1); - SetConst(@FRegsStory.EXEC[1],dtBool,0); - - FInitLine:=AllocBlockOp; - FInitLine^.SetInfo(btOther,FCursor.Adr,FCursor.Adr); - PushBlockOp(line,FInitLine,nil); - FMain^.PopBlock; + InitFlow; end; procedure TSprvEmit.SetUserData(pData:Pointer); begin - FDataLayouts.SetUserData(pData); + DataLayoutList.SetUserData(pData); end; Procedure TSprvEmit.InitVs(RSRC2:TSPI_SHADER_PGM_RSRC2_VS;instance:Byte); var p:Byte; begin - Init; - FExecutionModel:=ExecutionModel.Vertex; //sgrp @@ -1016,14 +138,14 @@ begin if (RSRC2.USER_SGPR<>0) then For p:=p to RSRC2.USER_SGPR-1 do begin - AddUserdata(@FRegsStory.SGRP[p],p); + AddUserdata(@RegsStory.SGRP[p],p); end; p:=RSRC2.USER_SGPR; if (RSRC2.SO_EN<>0) or (RSRC2.OC_LDS_EN<>0) then begin - AddInput(@FRegsStory.SGRP[p],dtUint32,itVsState); + AddInput(@RegsStory.SGRP[p],dtUint32,itVsState); p:=p+1; //s_vs_state // stream_id[1:0], is_offchip[2], @@ -1033,7 +155,7 @@ begin if (RSRC2.SO_EN<>0) then begin - AddInput(@FRegsStory.SGRP[p],dtUint32,itWriteIndex); + AddInput(@RegsStory.SGRP[p],dtUint32,itWriteIndex); p:=p+1; //s_so_write_index // streamout_write_index[31:0] @@ -1041,7 +163,7 @@ begin if (RSRC2.SO_BASE0_EN<>0) then begin - AddInput(@FRegsStory.SGRP[p],dtUint32,itOffset,0); + AddInput(@RegsStory.SGRP[p],dtUint32,itOffset,0); p:=p+1; //s_so_base_offset0 // streamout_offset0[31:0] @@ -1049,7 +171,7 @@ begin if (RSRC2.SO_BASE1_EN<>0) then begin - AddInput(@FRegsStory.SGRP[p],dtUint32,itOffset,1); + AddInput(@RegsStory.SGRP[p],dtUint32,itOffset,1); p:=p+1; //s_so_base_offset1 // streamout_offset1[31:0] @@ -1057,7 +179,7 @@ begin if (RSRC2.SO_BASE2_EN<>0) then begin - AddInput(@FRegsStory.SGRP[p],dtUint32,itOffset,2); + AddInput(@RegsStory.SGRP[p],dtUint32,itOffset,2); p:=p+1; //s_so_base_offset2 // streamout_offset2[31:0] @@ -1065,7 +187,7 @@ begin if (RSRC2.SO_BASE3_EN<>0) then begin - AddInput(@FRegsStory.SGRP[p],dtUint32,itOffset,3); + AddInput(@RegsStory.SGRP[p],dtUint32,itOffset,3); p:=p+1; //s_so_base_offset3 // streamout_offset3[31:0] @@ -1075,7 +197,7 @@ begin if (RSRC2.DISPATCH_DRAW_EN<>0) then begin - AddInput(@FRegsStory.SGRP[p],dtUint32,itWaveId); + AddInput(@RegsStory.SGRP[p],dtUint32,itWaveId); p:=p+1; //s_wave_id // wave_id [11:0] (dispatch draw term) @@ -1083,7 +205,7 @@ begin if (RSRC2.SCRATCH_EN<>0) then begin - AddInput(@FRegsStory.SGRP[p],dtUint32,itScratch); + AddInput(@RegsStory.SGRP[p],dtUint32,itScratch); p:=p+1; //s_scratch // scratch offset (in bytes) @@ -1091,26 +213,26 @@ begin //vgrp p:=1; - AddInput(@FRegsStory.VGRP[0],dtUint32,itVIndex); + AddInput(@RegsStory.VGRP[0],dtUint32,itVIndex); if (instance>=1) then begin - AddInput(@FRegsStory.VGRP[p],dtUint32,itVInstance,1); + AddInput(@RegsStory.VGRP[p],dtUint32,itVInstance,1); p:=p+1; end; if (instance>=2) then begin - AddInput(@FRegsStory.VGRP[p],dtUint32,itVInstance,2); + AddInput(@RegsStory.VGRP[p],dtUint32,itVInstance,2); p:=p+1; end; if (instance>=3) then begin - AddInput(@FRegsStory.VGRP[p],dtUint32,itVInstance,0); + AddInput(@RegsStory.VGRP[p],dtUint32,itVInstance,0); end; - AddCap(Capability.Shader); + AddCapability(Capability.Shader); end; @@ -1118,8 +240,6 @@ Procedure TSprvEmit.InitPs(RSRC2:TSPI_SHADER_PGM_RSRC2_PS;ENA:TSPI_PS_INPUT_ENA) var p:Byte; begin - Init; - FExecutionModel:=ExecutionModel.Fragment; //sgrp @@ -1127,12 +247,12 @@ begin if (RSRC2.USER_SGPR<>0) then For p:=p to RSRC2.USER_SGPR-1 do begin - AddUserdata(@FRegsStory.SGRP[p],p); + AddUserdata(@RegsStory.SGRP[p],p); end; p:=RSRC2.USER_SGPR; begin - AddInput(@FRegsStory.SGRP[p],dtUint32,itPsState); + AddInput(@RegsStory.SGRP[p],dtUint32,itPsState); p:=p+1; //s_ps_state // {bc_optimize, prim_mask[14:0], @@ -1141,7 +261,7 @@ begin if (RSRC2.WAVE_CNT_EN<>0) then begin - AddInput(@FRegsStory.SGRP[p],dtUint32,itWaveCnt); + AddInput(@RegsStory.SGRP[p],dtUint32,itWaveCnt); p:=p+1; //(s_wave_cnt) // {ps_wave_id[9:0], ps_strap_id, @@ -1150,7 +270,7 @@ begin if (RSRC2.SCRATCH_EN<>0) then begin - AddInput(@FRegsStory.SGRP[p],dtUint32,itScratch); + AddInput(@RegsStory.SGRP[p],dtUint32,itScratch); p:=p+1; //s_scratch // scratch offset (in bytes) @@ -1160,125 +280,112 @@ begin p:=0; if (ENA.PERSP_SAMPLE_ENA<>0) then begin - AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspSample,0); + AddInput(@RegsStory.VGRP[p],dtFloat32,itPerspSample,0); p:=p+1; - AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspSample,1); + AddInput(@RegsStory.VGRP[p],dtFloat32,itPerspSample,1); p:=p+1; end; if (ENA.PERSP_CENTER_ENA<>0) then begin - AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspCenter,0); + AddInput(@RegsStory.VGRP[p],dtFloat32,itPerspCenter,0); p:=p+1; - AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspCenter,1); + AddInput(@RegsStory.VGRP[p],dtFloat32,itPerspCenter,1); p:=p+1; end; if (ENA.PERSP_CENTROID_ENA<>0) then begin - AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspCentroid,0); + AddInput(@RegsStory.VGRP[p],dtFloat32,itPerspCentroid,0); p:=p+1; - AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspCentroid,1); + AddInput(@RegsStory.VGRP[p],dtFloat32,itPerspCentroid,1); p:=p+1; end; if (ENA.PERSP_PULL_MODEL_ENA<>0) then begin - AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspW,0); + AddInput(@RegsStory.VGRP[p],dtFloat32,itPerspW,0); p:=p+1; - AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspW,1); + AddInput(@RegsStory.VGRP[p],dtFloat32,itPerspW,1); p:=p+1; - AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspW,2); + AddInput(@RegsStory.VGRP[p],dtFloat32,itPerspW,2); p:=p+1; end; if (ENA.LINEAR_SAMPLE_ENA<>0) then begin - AddInput(@FRegsStory.VGRP[p],dtFloat32,itLinearSample,0); + AddInput(@RegsStory.VGRP[p],dtFloat32,itLinearSample,0); p:=p+1; - AddInput(@FRegsStory.VGRP[p],dtFloat32,itLinearSample,1); + AddInput(@RegsStory.VGRP[p],dtFloat32,itLinearSample,1); p:=p+1; end; if (ENA.LINEAR_CENTER_ENA<>0) then begin - AddInput(@FRegsStory.VGRP[p],dtFloat32,itLinearCenter,0); + AddInput(@RegsStory.VGRP[p],dtFloat32,itLinearCenter,0); p:=p+1; - AddInput(@FRegsStory.VGRP[p],dtFloat32,itLinearCenter,1); + AddInput(@RegsStory.VGRP[p],dtFloat32,itLinearCenter,1); p:=p+1; end; if (ENA.LINEAR_CENTROID_ENA<>0) then begin - AddInput(@FRegsStory.VGRP[p],dtFloat32,itLinearCentroid,0); + AddInput(@RegsStory.VGRP[p],dtFloat32,itLinearCentroid,0); p:=p+1; - AddInput(@FRegsStory.VGRP[p],dtFloat32,itLinearCentroid,1); + AddInput(@RegsStory.VGRP[p],dtFloat32,itLinearCentroid,1); p:=p+1; end; if (ENA.POS_X_FLOAT_ENA<>0) then begin - AddVecInput(@FRegsStory.VGRP[p],dtVec4f,dtFloat32,itFloatPos,0); + AddVecInput(@RegsStory.VGRP[p],dtVec4f,dtFloat32,itFloatPos,0); p:=p+1; end; if (ENA.POS_Y_FLOAT_ENA<>0) then begin - AddVecInput(@FRegsStory.VGRP[p],dtVec4f,dtFloat32,itFloatPos,1); + AddVecInput(@RegsStory.VGRP[p],dtVec4f,dtFloat32,itFloatPos,1); p:=p+1; end; if (ENA.POS_Z_FLOAT_ENA<>0) then begin - AddVecInput(@FRegsStory.VGRP[p],dtVec4f,dtFloat32,itFloatPos,2); + AddVecInput(@RegsStory.VGRP[p],dtVec4f,dtFloat32,itFloatPos,2); p:=p+1; end; if (ENA.POS_W_FLOAT_ENA<>0) then begin - AddVecInput(@FRegsStory.VGRP[p],dtVec4f,dtFloat32,itFloatPos,3); + AddVecInput(@RegsStory.VGRP[p],dtVec4f,dtFloat32,itFloatPos,3); p:=p+1; end; if (ENA.FRONT_FACE_ENA<>0) then begin - AddInput(@FRegsStory.VGRP[p],dtBool,itFrontFace); + AddInput(@RegsStory.VGRP[p],dtBool,itFrontFace); p:=p+1; end; if (ENA.ANCILLARY_ENA<>0) then begin - SetConst(@FRegsStory.VGRP[p],dtUint32,2); - //AddInput(@FRegsStory.VGRP[p],dtUint32,itAncillary); + AddAncillary(@RegsStory.VGRP[p]); p:=p+1; - //Render target array index[26:16], BuiltIn.Layer - //Iterated sample number[11:8], BuiltIn.SampleId - //Primitive type[1:0] 0..3 - - //POINT 00 - //LINE 01 - //TRI 10 - //RECT 11 - - //PID ISID RTAI - //01|234567|89AB|CDEF|0123456789A| - //10|000000| |0000|00000000000| end; if (ENA.SAMPLE_COVERAGE_ENA<>0) then begin - AddInput(@FRegsStory.VGRP[p],dtUint32,itSampleCoverage); + AddInput(@RegsStory.VGRP[p],dtUint32,itSampleCoverage); p:=p+1; end; if (ENA.POS_FIXED_PT_ENA<>0) then begin - AddInput(@FRegsStory.VGRP[p],dtUint32,itPosFixed); + AddInput(@RegsStory.VGRP[p],dtUint32,itPosFixed); p:=p+1; //Per-pixel fixed point position Y[31:16], X[15:0] end; - AddCap(Capability.Shader); + AddCapability(Capability.Shader); end; @@ -1286,42 +393,40 @@ Procedure TSprvEmit.InitCs(RSRC2:TCOMPUTE_PGM_RSRC2;NTX:TCOMPUTE_NUM_THREAD_X;NT var p:Byte; begin - Init; - FExecutionModel:=ExecutionModel.GLCompute; p:=0; if (RSRC2.USER_SGPR<>0) then For p:=p to RSRC2.USER_SGPR-1 do begin - AddUserdata(@FRegsStory.SGRP[p],p); + AddUserdata(@RegsStory.SGRP[p],p); end; p:=RSRC2.USER_SGPR; if (RSRC2.TGID_X_EN<>0) then begin - AddVecInput(@FRegsStory.SGRP[p],dtVec3u,dtUint32,itTgid,0); + AddVecInput(@RegsStory.SGRP[p],dtVec3u,dtUint32,itTgid,0); p:=p+1; //(s_tgid_x) threadgroup_id0[31:0] computePgmRsrc2.tgid_x_en;tgid_x_en(1) //gl_WorkGroupID end; if (RSRC2.TGID_Y_EN<>0) then begin - AddVecInput(@FRegsStory.SGRP[p],dtVec3u,dtUint32,itTgid,1); + AddVecInput(@RegsStory.SGRP[p],dtVec3u,dtUint32,itTgid,1); p:=p+1; //(s_tgid_y) threadgroup_id1[31:0] computePgmRsrc2.tgid_y_en;tgid_y_en(1) //gl_WorkGroupID end; if (RSRC2.TGID_Z_EN<>0) then begin - AddVecInput(@FRegsStory.SGRP[p],dtVec3u,dtUint32,itTgid,2); + AddVecInput(@RegsStory.SGRP[p],dtVec3u,dtUint32,itTgid,2); p:=p+1; //(s_tgid_z) threadgroup_id2[31:0] computePgmRsrc2.tgid_z_en;tgid_z_en(1) //gl_WorkGroupID end; if (RSRC2.TG_SIZE_EN<>0) then begin - AddInput(@FRegsStory.SGRP[p],dtUint32,itTgSize); + AddInput(@RegsStory.SGRP[p],dtUint32,itTgSize); p:=p+1; //(s_tg_size) //gl_NumWorkGroups ??? {first_wave, 14’b0, @@ -1331,7 +436,7 @@ begin if (RSRC2.SCRATCH_EN<>0) then begin - AddInput(@FRegsStory.SGRP[p],dtUint32,itScratch); + AddInput(@RegsStory.SGRP[p],dtUint32,itScratch); p:=p+1; //s_scratch // scratch offset (in bytes) @@ -1340,21 +445,21 @@ begin //vgrp p:=0; begin - AddVecInput(@FRegsStory.VGRP[p],dtVec3u,dtUint32,itThreadId,0); + AddVecInput(@RegsStory.VGRP[p],dtVec3u,dtUint32,itThreadId,0); p:=p+1; //(v_thread_id_x) Thread ID in group 0 //gl_LocalInvocationID end; if (RSRC2.TIDIG_COMP_CNT>=1) then begin - AddVecInput(@FRegsStory.VGRP[p],dtVec3u,dtUint32,itThreadId,1); + AddVecInput(@RegsStory.VGRP[p],dtVec3u,dtUint32,itThreadId,1); p:=p+1; //(v_thread_id_y) Thread ID in group 1 //gl_LocalInvocationID end; if (RSRC2.TIDIG_COMP_CNT>=2) then begin - AddVecInput(@FRegsStory.VGRP[p],dtVec3u,dtUint32,itThreadId,2); + AddVecInput(@RegsStory.VGRP[p],dtVec3u,dtUint32,itThreadId,2); p:=p+1; //(v_thread_id_z) Thread ID in group 2 //gl_LocalInvocationID end; @@ -1367,418 +472,62 @@ begin if (FLocalSize.y=0) then FLocalSize.y:=1; if (FLocalSize.z=0) then FLocalSize.z:=1; - AddCap(Capability.Shader); -end; - -Function TSprvEmit.NewReg(rtype:TsrDataType):PsrRegNode; -begin - Result:=FRegsStory.FUnattach.New(line,rtype); -end; - -Function TSprvEmit.FetchReg(pConst:PsrConst):PsrRegNode; -begin - if (pConst=nil) then Exit(nil); - Result:=NewReg(pConst^.key.dtype); - Result^.SetConst(pConst); - Result^.mark_read; -end; - -Procedure TSprvEmit.SetConst(pSlot:PsrRegSlot;pConst:PsrConst); -var - dst:PsrRegNode; -begin - dst:=pSlot^.New(line,pConst^.key.dtype); - dst^.SetConst(pConst); - - dst^.mark_read; - PostReg(dst); //post processing -end; - -Procedure TSprvEmit.SetConst(pSlot:PsrRegSlot;dtype:TsrDataType;value:QWORD); -begin - SetConst(pSlot,FConsts.Fetch(dtype,value)); -end; - -function TSprvEmit.fetch_soffset(SOFFSET:Word;rtype:TsrDataType):PsrRegNode; -Var - src:PsrRegSlot; - pConst:PsrConst; -begin - if is_const_ssrc8(SOFFSET) then - begin - pConst:=FConsts.Fetch_ssrc8_const(SOFFSET,0,rtype); - Result:=FetchReg(pConst); - end else - begin - src:=FRegsStory.get_ssrc8(SOFFSET); - Result:=MakeRead(src,rtype); - end; -end; - - -function TSprvEmit.fetch_ssrc9(SSRC:Word;rtype:TsrDataType):PsrRegNode; -Var - src:PsrRegSlot; - pConst:PsrConst; -begin - if is_const_ssrc9(SSRC) then - begin - pConst:=FConsts.Fetch_ssrc9_const(SSRC,FSPI.INLINE32,rtype); - Result:=FetchReg(pConst); - end else - begin - src:=FRegsStory.get_ssrc9(SSRC); - Result:=MakeRead(src,rtype); - end; -end; - -function TSprvEmit.fetch_ssrc9_pair(src:PPsrRegNode;SSRC:Word;rtype:TsrDataType):Boolean; -Var - pSlot:array[0..1] of PsrRegSlot; -begin - if is_const_ssrc9(SSRC) then - begin - src[0]:=FetchReg(FConsts.Fetch_ssrc9_const(SSRC,FSPI.INLINE32,rtype)); - src[1]:=FetchReg(FConsts.Fetch(dtUnknow,0)); - Result:=True; - end else - begin - pSlot[0]:=nil; - pSlot[1]:=nil; - Result:=FRegsStory.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 TSprvEmit.fetch_vsrc8(VSRC:Word;rtype:TsrDataType):PsrRegNode; -var - src:PsrRegSlot; -begin - src:=FRegsStory.get_vsrc8(VSRC); - Result:=MakeRead(src,rtype); -end; - -function TSprvEmit.fetch_vdst8(VDST:Word;rtype:TsrDataType):PsrRegNode; -var - src:PsrRegSlot; -begin - src:=FRegsStory.get_vdst8(VDST); - Result:=MakeRead(src,rtype); -end; - -procedure TSprvEmit.fetch_vsrc8_vec2h(VSRC:Word;var dst0,dst1:PsrRegNode); -var - pSlot:PsrRegSlot; - dst:PsrRegNode; -begin - pSlot:=FRegsStory.get_vsrc8(VSRC); - - dst:=MakeRead(pSlot,dtVec2h); - dst^.mark_read; - - dst0:=NewReg(dtHalf16); - dst1:=NewReg(dtHalf16); - - dst0^.mark_read; - dst1^.mark_read; - - TEmitOp(Self).emit_OpCompExtract(line,dst0,dst,0); - TEmitOp(Self).emit_OpCompExtract(line,dst1,dst,1); -end; - -procedure TSprvEmit._MakeCopy(dst:PsrRegSlot;src:PsrRegNode); -var - node:PsrRegNode; -begin - node:=dst^.New(line,src^.dtype); - node^.SetReg(src); - - dst^.current^.mark_read; - PostReg(dst^.current); //post processing -end; - -procedure TSprvEmit.MakeCopy(dst:PsrRegSlot;src:PsrRegNode); -begin - src^.mark_read; - _MakeCopy(dst,src); -end; - -function GetChainRegNode(node:PsrRegNode):PsrChain; -var - pOp:PSpirvOp; -begin - Result:=nil; - node:=RegDown(node); - pOp:=node^.AsOp; - if (pOp=nil) then Exit; - if (pOp^.OpId<>Op.OpLoad) then Exit; - Result:=pOp^.pParam.pHead^.AsChain; -end; - -function GetSourceRegNode(node:PsrRegNode):TOpParamSingle; -var - pOp:PSpirvOp; - pVar:PsrVariable; -begin - Result:=Default(TOpParamSingle); - node:=RegDown(node); - pOp:=node^.AsOp; - if (pOp=nil) then Exit; - if (pOp^.OpId<>Op.OpLoad) then Exit; - pVar:=pOp^.pParam.pHead^.AsVar; - if (pVar=nil) then Exit; - Result:=pVar^.pSource; -end; - -function GetInputRegNode(node:PsrRegNode):PsrInput; -var - pSource:TOpParamSingle; -begin - pSource:=GetSourceRegNode(node); - Result:=pSource.AsInput; + AddCapability(Capability.Shader); end; // -function TSprvEmit.GroupingSharp(src:PPsrRegSlot;rtype:TsrResourceType):PsrDataLayout; +procedure TSprvEmit.emit_spi; var - i,n:Byte; - chain:TsrChains; -begin - Result:=nil; - chain:=Default(TsrChains); - n:=GetResourceSizeDw(rtype); - For i:=0 to n-1 do - begin - chain[i]:=GetChainRegNode(src[i]^.current); - end; - Result:=FDataLayouts.Grouping(chain,rtype); -end; - -procedure TSprvEmit.PrepTypeSlot(pSlot:PsrRegSlot;rtype:TsrDataType); -var - node:PsrRegNode; -begin - if (pSlot=nil) then Exit; - if (pSlot^.current=nil) then - begin - pSlot^.New(line,rtype); //Unresolve - Exit; - end; - - if (rtype=dtUnknow) then Exit; - - node:=pSlot^.current; - if (node^.dtype=dtUnknow) then - begin - RegPrepType(node,rtype); - end; -end; - -function TSprvEmit.MakeRead(pSlot:PsrRegSlot;rtype:TsrDataType):PsrRegNode; -var - node:PsrRegNode; -begin - Result:=nil; - if (pSlot=nil) then Exit; - PrepTypeSlot(pSlot,rtype); - node:=pSlot^.current; - if (rtype<>dtUnknow) and (not CompareType(node^.dtype,rtype)) then - begin - Result:=FBitcast.FetchRead(rtype,node); - end else - begin - Result:=node; - Result^.mark_read; - end; -end; - -procedure TSprvEmit.LoadPrepType(node:PsrRegNode;p:PspirvOp;rtype:TsrDataType); -var - pVar:PsrVariable; - pChain:PsrChain; - ctype:TsrDataType; - pReg:PsrRegNode; -begin - if (p^.pParam.pHead^.pData<>nil) then - Case p^.pParam.pHead^.ntype of - ntVar: - begin - pVar:=p^.pParam.pHead^.AsVar; - if (pVar^.dtype=dtUnknow) then - begin - pVar^.dtype:=rtype; - end; - end; - ntChain: - begin - pChain:=p^.pParam.pHead^.AsChain; - ctype:=pChain^.GetRegType; - if (ctype=dtUnknow) then - begin - pChain^.SetRegType(rtype); - end else - if (ctype<>rtype) then - begin - pChain^.SetRegType(rtype); - pReg:=NewReg(rtype); - pReg^.pLine :=node^.pLine; - pReg^.pWriter:=node^.pWriter; - pReg^.mark_read; - node^.SetReg(pReg); - rtype:=ctype; - end; - end; - else; - end; - if (p^.dst_type=nil) then - begin - p^.dst_type:=FSpirvTypes.Fetch(rtype); - end; -end; - -procedure TSprvEmit.RegPrepType(node:PsrRegNode;rtype:TsrDataType); -var - n:PsrRegNode; - pConst:PsrConst; - pOp:PspirvOp; -begin - if (rtype<>dtUnknow) and (node^.dtype=dtUnknow) then - begin - node^.dtype:=rtype; - //backtrace - While (true) do - begin - Case node^.pWriter.ntype of - ntVolatile:Break; //ignore - ntReg: - begin - n:=node^.pWriter.pData; //next - if (n^.dtype=dtUnknow) then - begin - n^.dtype:=rtype; - end else - begin - Break; - end; - node:=n; - end; - ntConst: - begin - pConst:=node^.pWriter.pData; - pConst^.mark_unread; - pConst:=FConsts.Bitcast(rtype,pConst); - node^.pWriter.pData:=pConst; - Break; - end; - ntOp: - begin - pOp:=node^.AsOp; - if (pOp<>nil) then - Case pOp^.OpId of - Op.OpLoad: - begin - LoadPrepType(node,pOp,rtype); - end; - else; - end; - Break; - end; - else - Assert(false,'RegPrepType'); - end; - end; - end; -end; - -function RegDown(node:PsrRegNode):PsrRegNode; -var - tmp:PsrRegNode; -begin - //backtrace - Result:=node; - While (Result<>nil) do - begin - tmp:=Result^.AsReg; //next - if (tmp=nil) then Break; - Result:=tmp; - end; -end; - -function RegDownSlot(node:PsrRegNode):PsrRegNode; -var - tmp:PsrRegNode; -begin - //backtrace - Result:=node; - While (Result<>nil) do - begin - tmp:=Result^.AsReg; //next - if (tmp=nil) then Break; - if (tmp^.pSlot<>Result^.pSlot) then Break; - Result:=tmp; - end; -end; - -Procedure mark_read(const node:TOpParamSingle); -begin - Case node.ntype of - ntConst:PsrConst (node.pData)^.mark_read; - ntType :PsrType (node.pData)^.mark_read; - ntFunc :PSpirvFunc (node.pData)^.mark_read; - ntVar :PsrVariable(node.pData)^.mark_read; - ntReg :PsrRegNode (node.pData)^.mark_read; - ntChain:PsrChain (node.pData)^.mark_read; - else - Assert(false,'mark_read'); - end; -end; - -Procedure mark_write(const node:TOpParamSingle); -begin - Case node.ntype of - ntConst:PsrConst (node.pData)^.mark_read; - ntType :PsrType (node.pData)^.mark_read; - ntFunc :PSpirvFunc (node.pData)^.mark_read; - ntVar :PsrVariable(node.pData)^.mark_write; - ntReg :PsrRegNode (node.pData)^.mark_read; - ntChain:PsrChain (node.pData)^.mark_write; - else - Assert(false,'mark_write'); - end; -end; - -procedure TSprvEmit._emit_spi; + obj:TObject absolute Self; begin Case FSPI.CMD.EN of - W_SOP1 :TEmit_SOP1(Self)._emit_SOP1; - W_SOPC :TEmit_SOPC(Self)._emit_SOPC; - W_SOPP :TEmit_SOPP(Self)._emit_SOPP; - W_VOP1 :TEmit_VOP1(Self)._emit_VOP1; - W_VOPC :TEmit_VOPC(Self)._emit_VOPC; + W_SOP1 :TEmit_SOP1(obj).emit_SOP1; + W_SOPC :TEmit_SOPC(obj).emit_SOPC; + W_SOPP :TEmit_SOPP(obj).emit_SOPP; + W_VOP1 :TEmit_VOP1(obj).emit_VOP1; + W_VOPC :TEmit_VOPC(obj).emit_VOPC; W_VOP3 :Case FSPI.VOP3a.OP of - 0..255:TEmit_VOP3(Self)._emit_VOP3c; + 0..255:TEmit_VOP3(obj).emit_VOP3c; 293..298, - 365..366:TEmit_VOP3(Self)._emit_VOP3b; + 365..366:TEmit_VOP3(obj).emit_VOP3b; else - TEmit_VOP3(Self)._emit_VOP3a; + TEmit_VOP3(obj).emit_VOP3a; end; - W_DS :TEmit_DS(Self)._emit_DS; - W_MUBUF :TEmit_MUBUF(Self)._emit_MUBUF; - W_MTBUF :TEmit_MTBUF(Self)._emit_MTBUF; - W_EXP :TEmit_EXP(Self)._emit_EXP; - W_VINTRP:TEmit_VINTRP(Self)._emit_VINTRP; - W_MIMG :TEmit_MIMG(Self)._emit_MIMG; - W_SMRD :TEmit_SMRD(Self)._emit_SMRD; - W_SOPK :TEmit_SOPK(Self)._emit_SOPK; - W_SOP2 :TEmit_SOP2(Self)._emit_SOP2; - W_VOP2 :TEmit_VOP2(Self)._emit_VOP2; + //W_DS :TEmit_DS (obj).emit_DS; + W_MUBUF :TEmit_MUBUF (obj).emit_MUBUF; + W_MTBUF :TEmit_MTBUF (obj).emit_MTBUF; + W_EXP :TEmit_EXP (obj).emit_EXP; + W_VINTRP:TEmit_VINTRP(obj).emit_VINTRP; + W_MIMG :TEmit_MIMG (obj).emit_MIMG; + W_SMRD :TEmit_SMRD (obj).emit_SMRD; + W_SOPK :TEmit_SOPK (obj).emit_SOPK; + W_SOP2 :TEmit_SOP2 (obj).emit_SOP2; + W_VOP2 :TEmit_VOP2 (obj).emit_VOP2; else - Assert(false); + Assert(false,'Unknow encode:0x'+HexStr(FSPI.CMD.EN,4)); end; end; +Procedure TSprvEmit.PostStage; +begin + TSprvEmit_post(TObject(Self)).PostStage; +end; + +Procedure TSprvEmit.AllocStage; +begin + TSprvEmit_alloc(TObject(Self)).AllocStage; +end; + +Procedure TSprvEmit.Print; +begin + TSprvEmit_print(TObject(Self)).Print; +end; + +Procedure TSprvEmit.SaveToStream(Stream:TStream); +begin + TSprvEmit_bin(TObject(Self)).SaveToStream(Stream); +end; + end. diff --git a/spirv/emit_alloc.pas b/spirv/emit_alloc.pas index 6c2fbff7..a22232dd 100644 --- a/spirv/emit_alloc.pas +++ b/spirv/emit_alloc.pas @@ -7,36 +7,35 @@ interface uses sysutils, spirv, - srNodes, + srNode, + srType, srTypes, srConst, srRefId, srReg, srLayout, - srBuffer, srVariable, + srInput, + srOutput, + srVertLayout, + srFragLayout, + srUniform, + srBuffer, + srDecorate, srOp, srOpUtils, - SprvEmit; + emit_fetch; type - TSprvEmit_alloc=object(TSprvEmit) - procedure Alloc; + TSprvEmit_alloc=class(TEmitFetch) + procedure AllocStage; procedure AllocSpirvID(P:PsrRefId); procedure AllocBinding; procedure AllocTypeBinding; - procedure AllocSourceExtension; - procedure AllocTypeName; - Procedure AllocVarName; procedure AllocEntryPoint; procedure AllocHeader; procedure AllocOpListId(node:PspirvOp); - procedure AllocHeaderId; - procedure AllocTypesId; - procedure AllocConstId; - procedure AllocVariableId; - procedure AllocOpSingle(const Param:TOpParamSingle); - procedure AllocOpParamNode(node:POpParamNode); + procedure AllocListId(node:PsrNode); procedure AllocFuncId; procedure AllocOpId(node:PSpirvOp); procedure AllocOpBlock(pBlock:PsrOpBlock); @@ -44,134 +43,99 @@ type implementation -procedure TSprvEmit_alloc.Alloc; +procedure TSprvEmit_alloc.AllocStage; begin AllocBinding; + + BufferList.AllocTypeBinding; AllocTypeBinding; AllocHeader; - AllocSourceExtension; - AllocTypeName; - AllocVarName; + //Source Extension + DataLayoutList.AllocSourceExtension; + DataLayoutList.AllocFuncExt; + VertLayoutList.AllocSourceExtension; + UniformList .AllocSourceExtension; + BufferList .AllocSourceExtension; - AllocHeaderId; + //Decorate Name + BufferList .AllocName; + VariableList.AllocName; + + //header id + AllocOpListId(HeaderList.First); + AllocOpListId(DebugInfoList.First); + AllocOpListId(DecorateList.First); + + //element id + AllocListId(TypeList.First); + AllocListId(ConstList.First); + AllocListId(VariableList.First); - AllocTypesId; - AllocConstId; - AllocVariableId; AllocFuncId; end; procedure TSprvEmit_alloc.AllocSpirvID(P:PsrRefId); begin - FSpirvIdAlloc.FetchSpirvID(P); + RefIdAlloc.FetchSpirvID(P); end; procedure TSprvEmit_alloc.AllocBinding; var FBinding:Integer; begin - FInputs .AllocBinding(@FDecorates); - FOutputs .AllocBinding(@FDecorates); - FVertLayouts.AllocBinding(@FDecorates); - FFragLayouts.AllocBinding(@FDecorates,@FSpirvCaps); + InputList .AllocBinding; + OutputList.AllocBinding; + + VertLayoutList.AllocBinding; + FragLayoutList.AllocBinding; FBinding:=0; - FUniforms.AllocBinding(FBinding,@FDecorates); - FBuffers .AllocBinding(FBinding,@FDecorates); + + UniformList.AllocBinding(FBinding); + BufferList .AllocBinding(FBinding); end; procedure TSprvEmit_alloc.AllocTypeBinding; var node:PsrType; - pField:PsrField; begin - node:=FSpirvTypes.FList.pHead; + node:=TypeList.First; While (node<>nil) do begin - case node^.dtype of - dtTypeStruct: + case node^.OpId of + + Op.OpTypeArray, + Op.OpTypeRuntimeArray: begin - pField:=node^.key.ext.pField; - if (pField<>nil) then + DecorateList.OpDecorate(node,Decoration.ArrayStride,node^.array_stride); + end; + + Op.OpTypeFloat: begin - if (pField^.GetStructDecorate<>DWORD(-1)) then - begin - FDecorates.emit_decorate(ntType,node,pField^.GetStructDecorate,0); + case node^.dtype.BitSize of + 16:AddCapability(Capability.Float16); + 64:AddCapability(Capability.Float64); + else; end; - pField^.AllocBinding(node,@FDecorates); end; - end; - dtTypeArray, - dtTypeRuntimeArray: - begin - FDecorates.emit_decorate(ntType,node,Decoration.ArrayStride,node^.key.ext.array_stride); - end; - - else; - end; - - node:=node^.pNext; - end; -end; - -procedure TSprvEmit_alloc.AllocSourceExtension; -begin - FDataLayouts.AllocSourceExtension(@FDebugInfo); - FDataLayouts.AllocFuncExt(@FDebugInfo,FCodeHeap); - FVertLayouts.AllocSourceExtension(@FDebugInfo); - FUniforms .AllocSourceExtension(@FDebugInfo); - FBuffers .AllocSourceExtension(@FDebugInfo); -end; - -procedure TSprvEmit_alloc.AllocTypeName; -var - node:PsrType; - pField:PsrField; -begin - node:=FSpirvTypes.FList.pHead; - While (node<>nil) do - begin - - case node^.dtype of - dtTypeStruct: - begin - pField:=node^.key.ext.pField; - if (pField<>nil) and - (pField^.parent=nil) and - (pField^.pBuffer<>nil) then + Op.OpTypeInt: begin - FDebugInfo.emit_name(ntType,node,pField^.pBuffer^.GetStructName); + case node^.dtype.BitSize of + 8:AddCapability(Capability.Int8); + 16:AddCapability(Capability.Int16); + 64:AddCapability(Capability.Int64); + else; + end; end; - end; else; end; - node:=node^.pNext; - end; -end; - -Procedure TSprvEmit_alloc.AllocVarName; -var - node:PsrVariable; - n:RawByteString; -begin - node:=FVariables.pHead; - While (node<>nil) do - begin - if (node^.pType<>nil) then - begin - n:=node^.GetName; - if (n<>'') then - begin - FDebugInfo.emit_name(ntVar,node,n); - end; - end; - node:=node^.pNext; + node:=node^.Next; end; end; @@ -180,7 +144,7 @@ begin While (node<>nil) do begin AllocOpId(node); - node:=node^.pNext; + node:=node^.Next; end; end; @@ -188,24 +152,24 @@ procedure TSprvEmit_alloc.AllocEntryPoint; var node:PSpirvOp; begin - node:=FHeader.AddSpirvOp(Op.OpEntryPoint); + node:=HeaderList.AddSpirvOp(Op.OpEntryPoint); node^.AddLiteral(FExecutionModel,ExecutionModel.GetStr(FExecutionModel)); - node^.AddParam(ntFunc,FMain); - node^.AddString(FMain^.name); + node^.AddParam(Main); + node^.AddString(Main^.name); - FInputs .AllocEntryPoint(node); - FVertLayouts.AllocEntryPoint(node); - FFragLayouts.AllocEntryPoint(node); - FOutputs .AllocEntryPoint(node); + InputList .AllocEntryPoint(node); + VertLayoutList.AllocEntryPoint(node); + FragLayoutList.AllocEntryPoint(node); + OutputList .AllocEntryPoint(node); end; procedure TSprvEmit_alloc.AllocHeader; var node:PSpirvOp; begin - node:=FHeader.AddSpirvOp(Op.OpMemoryModel); + node:=HeaderList.AddSpirvOp(Op.OpMemoryModel); node^.AddLiteral(AddressingModel.Logical,AddressingModel.GetStr(AddressingModel.Logical)); node^.AddLiteral(MemoryModel.GLSL450,MemoryModel.GetStr(MemoryModel.GLSL450)); @@ -214,14 +178,14 @@ begin Case FExecutionModel of ExecutionModel.Fragment: begin - node:=FHeader.AddSpirvOp(Op.OpExecutionMode); - node^.AddParam(ntFunc,FMain); + node:=HeaderList.AddSpirvOp(Op.OpExecutionMode); + node^.AddParam(Main); node^.AddLiteral(ExecutionMode.OriginUpperLeft,ExecutionMode.GetStr(ExecutionMode.OriginUpperLeft)); end; ExecutionModel.GLCompute: begin - node:=FHeader.AddSpirvOp(Op.OpExecutionMode); - node^.AddParam(ntFunc,FMain); + node:=HeaderList.AddSpirvOp(Op.OpExecutionMode); + node^.AddParam(Main); node^.AddLiteral(ExecutionMode.LocalSize,ExecutionMode.GetStr(ExecutionMode.LocalSize)); node^.AddLiteral(FLocalSize.x); node^.AddLiteral(FLocalSize.y); @@ -231,135 +195,12 @@ begin end; -procedure TSprvEmit_alloc.AllocHeaderId; +procedure TSprvEmit_alloc.AllocListId(node:PsrNode); begin - AllocOpListId(FHeader.pHead); - AllocOpListId(FDebugInfo.pHead); - AllocOpListId(FDecorates.pHead); -end; - -procedure TSprvEmit_alloc.AllocTypesId; -var - node:PsrType; - pConst:PsrConst; -begin - node:=FSpirvTypes.FList.pHead; While (node<>nil) do begin - case node^.dtype of - dtTypeArray: - begin - //find a const - pConst:=FConsts.Fetchi(dtUInt32,node^.key.ext.array_count); - if (pConst^.pType=nil) then - begin - pConst^.pType:=FSpirvTypes.Fetch(pConst^.key.dtype); - AllocSpirvID(@pConst^.pType^.ID); - end; - FConsts.FList.Remove(pConst); - AllocSpirvID(@pConst^.ID); - end; - else; - end; - AllocSpirvID(@node^.ID); - node:=node^.pNext; - end; -end; - -procedure TSprvEmit_alloc.AllocConstId; -var - node:PsrConst; -begin - node:=FConsts.FList.pHead; - While (node<>nil) do - begin - if (node^.key.dtype<>dtUnknow) then - begin - AllocSpirvID(@node^.ID) - end; - node:=node^.pNext; - end; -end; - -procedure TSprvEmit_alloc.AllocVariableId; -var - node:PsrVariable; -begin - node:=FVariables.pHead; - While (node<>nil) do - begin - if (node^.pType<>nil) then - begin - AllocSpirvID(@node^.ID); - AllocSpirvID(@node^.pType^.ID); - end; - node:=node^.pNext; - end; -end; - -procedure TSprvEmit_alloc.AllocOpSingle(const Param:TOpParamSingle); -var - pReg:PsrRegNode; -begin - Assert(Param.pData<>nil,'AllocOpSingle$1'); - Case Param.ntype of - - ntFunc: - begin - AllocSpirvID(@PSpirvFunc(Param.pData)^.ID); - end; - - ntRefId: - begin - AllocSpirvID(Param.pData); - end; - - ntType: - begin - AllocSpirvID(@PsrType(Param.pData)^.ID); - end; - - ntReg: - begin - pReg:=Param.pData; - Case pReg^.pWriter.ntype of - ntConst:; - ntOp:AllocSpirvID(@pReg^.ID); - else - Assert(false,'AllocOpSingle$2'); - end; - end; - - ntVar: - begin - AllocSpirvID(@PsrVariable(Param.pData)^.ID); - end; - - ntChain: - begin - AllocSpirvID(@PsrChain(Param.pData)^.ID); - end; - - ntConst: - begin - AllocSpirvID(@PsrConst(Param.pData)^.ID) - end; - - else - Assert(false,'AllocOpSingle$3'); - end; - -end; - -procedure TSprvEmit_alloc.AllocOpParamNode(node:POpParamNode); -begin - Case node^.ntype of - ntLiteral:; - ntString :; - else - begin - AllocOpSingle(node^.AsParam); - end; + AllocSpirvID(node^.GetRef); + node:=node^.Next; end; end; @@ -367,11 +208,11 @@ procedure TSprvEmit_alloc.AllocFuncId; var pFunc:PSpirvFunc; begin - pFunc:=FSpirvFuncs.FList.pHead; + pFunc:=FuncList.First; While (pFunc<>nil) do begin - AllocOpBlock(@pFunc^.FTop); - pFunc:=pFunc^.pNext; + AllocOpBlock(pFunc^.pTop); + pFunc:=pFunc^.Next; end; end; @@ -387,34 +228,38 @@ begin if Info.result then //dst begin - Assert(node^.dst.ntype<>ntUnknow,'AllocOp$1'); - Assert(node^.dst.pData<>nil ,'AllocOp$2'); - AllocOpSingle(node^.dst); + Assert(node^.pDst<>nil,'AllocOp$1'); + if (node^.pDst<>nil) then + begin + AllocSpirvID(node^.pDst^.GetRef); + end; end else begin //no dst - if (node^.dst.ntype<>ntUnknow) then + if (node^.pDst<>nil) then begin - Assert(node^.dst.pData<>nil,'AllocOp$3'); - AllocOpSingle(node^.dst); + AllocSpirvID(node^.pDst^.GetRef); end; end; if Info.rstype then //dst type begin - if (node^.dst_type=nil) then + if (node^.pType=nil) then begin - pReg:=node^.dst.AsReg; - if (pReg^.dtype=dtUnknow) then pReg^.dtype:=dtFloat32; - node^.dst_type:=FSpirvTypes.Fetch(pReg^.dtype); - //Assert(false,'AllocOp$4'); + pReg:=node^.pDst^.AsType(ntReg); + Assert(pReg<>nil,'AllocOp$2'); + Assert(pReg^.dtype<>dtUnknow,'AllocOp$3'); + if (pReg<>nil) then + begin + node^.pType:=TypeList.Fetch(pReg^.dtype); + end; end; end; - Param:=node^.pParam.pHead; + Param:=node^.ParamFirst; While (Param<>nil) do begin - AllocOpParamNode(Param); - Param:=Param^.pNext; + AllocSpirvID(Param^.Value^.GetRef); + Param:=Param^.Next; end; end; @@ -424,22 +269,14 @@ var node:PSpirvOp; begin if (pBlock=nil) then Exit; - node:=pBlock^.pHead; + node:=pBlock^.First; While (node<>nil) do begin - - if (node^.OpId=OpBlock) then - begin - if (node^.dst.ntype=ntBlock) then - begin - AllocOpBlock(node^.dst.pData); - end; - end else + if node^.IsType(ntOp) then begin AllocOpId(node); end; - - node:=node^.pNext; + node:=flow_down_next_up(node); end; end; diff --git a/spirv/emit_bin.pas b/spirv/emit_bin.pas index 0b7a1981..3cd7d29d 100644 --- a/spirv/emit_bin.pas +++ b/spirv/emit_bin.pas @@ -8,17 +8,16 @@ uses SySutils, Classes, spirv, - srNodes, + srNode, + srType, srTypes, srConst, - srReg, - srLayout, srVariable, srOp, srOpUtils, - srCap, + srCapability, srRefId, - SprvEmit; + emit_fetch; type TSPIRVHeader=packed record @@ -30,7 +29,7 @@ type TOOL_VERSION:WORD; TOOL_ID:WORD; BOUND:DWORD; - RESERVED:DWORD; + SCHEMA:DWORD; end; PSPIRVInstruction=^TSPIRVInstruction; @@ -45,31 +44,23 @@ type COUNT:DWORD; Procedure AllocData; Procedure NewOp(OpId:WORD); + Procedure Reset; Procedure Flush(Stream:TStream); - procedure AddParamId(P:DWORD); - procedure AddString(const name:PChar); - procedure AddRefId(P:PsrRefId); - procedure AddConstId(P:PsrConst); - procedure AddVarId(P:PsrVariable); - procedure AddTypeId(P:PsrType); - procedure AddFuncId(P:PSpirvFunc); - procedure AddChainId(P:PsrChain); - procedure AddRegId(P:PsrRegNode); + procedure AddParam(P:DWORD); + procedure AddNode(node:PsrNode); end; - TSprvEmit_bin=object(TSprvEmit) + TSprvEmit_bin=class(TEmitFetch) procedure SaveToStream(Stream:TStream); procedure SaveHeader(Stream:TStream;var Header:TSPIRVHeader); procedure SaveCaps(Stream:TStream); - procedure SaveOpList(Stream:TStream;node:PspirvOp); + procedure SaveOpBlock(Stream:TStream;pBlock:PsrOpBlock); procedure SaveHeaderInfo(Stream:TStream); procedure SaveTypes(Stream:TStream); - procedure SaveConst(var buf:TSVInstrBuffer;node:PsrConst); procedure SaveConst(Stream:TStream); procedure SaveVariable(Stream:TStream); procedure SaveFunc(Stream:TStream); procedure SaveOp(Stream:TStream;node:PSpirvOp); - procedure SaveOpBlock(Stream:TStream;pBlock:PsrOpBlock); end; implementation @@ -97,15 +88,20 @@ begin Data[0]:=DWORD(I); end; +Procedure TSVInstrBuffer.Reset; +begin + COUNT:=0; +end; + Procedure TSVInstrBuffer.Flush(Stream:TStream); begin if (Stream=nil) or (COUNT=0) then Exit; TSPIRVInstruction(Data[0]).COUNT:=COUNT; Stream.Write(Data[0],COUNT*SizeOf(DWORD)); - COUNT:=0; + Reset; end; -procedure TSVInstrBuffer.AddParamId(P:DWORD); +procedure TSVInstrBuffer.AddParam(P:DWORD); var I:DWORD; begin @@ -116,75 +112,33 @@ begin Data[i]:=P; end; -procedure TSVInstrBuffer.AddString(const name:PChar); +procedure TSVInstrBuffer.AddNode(node:PsrNode); var + R:PsrRefId; I,L,D:DWORD; begin - Assert(name<>nil); + Assert(node<>nil); Assert(COUNT<>0,'new op not created'); - L:=StrLen(name); - D:=(L+SizeOf(DWORD)) div SizeOf(DWORD); + R:=node^.GetRef; + if (R<>nil) then + begin + I:=COUNT; + Inc(COUNT); + AllocData; + Data[i]:=R^.ID; + end else + begin + L:=node^.GetData(nil); //get size + D:=(L+(SizeOf(DWORD)-1)) div 4; //align + Assert(D<>0,'AddNode:'+node^.ntype.ClassName); - I:=COUNT; - COUNT:=COUNT+D; - AllocData; + I:=COUNT; + COUNT:=COUNT+D; + AllocData; - FillDWord(Data[i],D,0); - Move(PChar(name)^,Data[i],L); -end; - -procedure TSVInstrBuffer.AddRefId(P:PsrRefId); -begin - Assert(P<>nil ,'AddRefId$1'); - Assert(P^.Alloc,'AddRefId$2'); - AddParamId(P^.ID); -end; - -procedure TSVInstrBuffer.AddConstId(P:PsrConst); -begin - Assert(P<>nil,'AddConstId'); - AddRefId(@P^.ID); -end; - -procedure TSVInstrBuffer.AddVarId(P:PsrVariable); -begin - Assert(P<>nil,'AddVarId'); - AddRefId(@P^.ID); -end; - -procedure TSVInstrBuffer.AddTypeId(P:PsrType); -begin - Assert(P<>nil,'AddTypeId'); - AddRefId(@P^.ID); -end; - -procedure TSVInstrBuffer.AddFuncId(P:PSpirvFunc); -begin - Assert(P<>nil,'AddFuncId'); - AddRefId(@P^.ID); -end; - -procedure TSVInstrBuffer.AddChainId(P:PsrChain); -begin - Assert(P<>nil,'AddChainId'); - AddRefId(@P^.ID); -end; - -procedure TSVInstrBuffer.AddRegId(P:PsrRegNode); -begin - Assert(P<>nil,'AddRegId$1'); - Case P^.pWriter.ntype of - ntConst: - begin - AddConstId(P^.pWriter.pData); - end; - ntOp: - begin - AddRefId(@P^.ID); - end; - else - Assert(false,'AddRegId$2'); + FillDWord(Data[i],D,0); + node^.GetData(@Data[i]); end; end; @@ -196,10 +150,12 @@ begin Header:=Default(TSPIRVHeader); - Header.MAGIC:=spirv.MagicNumber; - DWORD(Header.VERSION):=FBuffers.cfg.SpvVersion; - Header.TOOL_VERSION:=1; - Header.BOUND:=FSpirvIdAlloc.GetSpirvIDBound; + Header.MAGIC :=MagicNumber; + DWORD(Header.VERSION) :=Config.SpvVersion; + Header.TOOL_VERSION:=2; + Header.TOOL_ID :=0; + Header.BOUND :=RefIdAlloc.GetSpirvIDBound; + Header.SCHEMA :=0; SaveHeader(Stream,Header); @@ -219,199 +175,96 @@ end; procedure TSprvEmit_bin.SaveCaps(Stream:TStream); var buf:TSVInstrBuffer; - node:PSpirvCap; + node:PsrCapability; begin buf:=Default(TSVInstrBuffer); - node:=FSpirvCaps.First; + node:=CapabilityList.First; While (node<>nil) do begin buf.NewOp(Op.OpCapability); - buf.AddParamId(node^.ID); + buf.AddParam(node^.ID); buf.Flush(Stream); - node:=FSpirvCaps.Next(node); + node:=CapabilityList.Next(node); end; end; -procedure TSprvEmit_bin.SaveOpList(Stream:TStream;node:PspirvOp); +procedure TSprvEmit_bin.SaveOpBlock(Stream:TStream;pBlock:PsrOpBlock); +var + node:PSpirvOp; begin + if (pBlock=nil) then Exit; + node:=pBlock^.First; + While (node<>nil) do begin - SaveOp(Stream,node); - node:=node^.pNext; + if node^.IsType(ntOp) then + begin + SaveOp(Stream,node); + end; + node:=flow_down_next_up(node); end; end; procedure TSprvEmit_bin.SaveHeaderInfo(Stream:TStream); begin - SaveOpList(Stream,FHeader.pHead); - SaveOpList(Stream,FDebugInfo.pHead); - SaveOpList(Stream,FDecorates.pHead); + SaveOpBlock(Stream,@HeaderList); + SaveOpBlock(Stream,@DebugInfoList); + SaveOpBlock(Stream,@DecorateList); end; procedure TSprvEmit_bin.SaveTypes(Stream:TStream); var buf:TSVInstrBuffer; node:PsrType; - pConst:PsrConst; - i:dword; - ie:Boolean; + i:Word; begin - buf:=Default(TSVInstrBuffer); - node:=FSpirvTypes.FList.pHead; + node:=TypeList.First; While (node<>nil) do begin - ie:=True; + buf.NewOp(node^.OpId); + buf.AddNode(node); - pConst:=nil; - case node^.dtype of - dtTypeArray: - begin - //find a const - pConst:=FConsts.Fetchi(dtUInt32,node^.key.ext.array_count); - SaveConst(buf,pConst); - buf.Flush(Stream); - end; - else; - end; - - buf.NewOp(node^.key.OpId); - buf.AddTypeId(node); - - case node^.key.OpId of - - Op.OpTypeFloat: - begin - buf.AddParamId(node^.key.ext.float_size); - end; - - Op.OpTypeInt: - begin - buf.AddParamId(node^.key.ext.int_size); - buf.AddParamId(node^.key.ext.int_sign); - end; - - Op.OpTypeVector: - begin - ie:=False; - buf.AddTypeId(node^.GetCompItem(0)); - buf.AddParamId(node^.key.ext.array_count); - end; - - Op.OpTypePointer: - begin - buf.AddParamId(node^.key.ext.Storage_Class); - end; - - Op.OpTypeArray: - begin - ie:=False; - buf.AddTypeId(node^.GetCompItem(0)); - buf.AddConstId(pConst); - end; - - Op.OpTypeRuntimeArray: - begin - ie:=False; - buf.AddTypeId(node^.GetCompItem(0)); - end; - - Op.OpTypeImage: - begin - ie:=False; - buf.AddTypeId(node^.GetCompItem(0)); - With node^.key.ext.image do - begin - buf.AddParamId(Dim); - buf.AddParamId(Depth); - buf.AddParamId(Arrayed); - buf.AddParamId(MS); - buf.AddParamId(Sampled); - buf.AddParamId(Format); - end; - end; - - - end; - - if ie then - if (node^.key.count<>0) then + if (node^.ItemCount<>0) then + begin + For i:=0 to node^.ItemCount-1 do begin - For i:=0 to node^.key.count-1 do - begin - buf.AddTypeId(node^.GetCompItem(i)); - end; + buf.AddNode(node^.GetItem(i)); end; + end; buf.Flush(Stream); - node:=node^.pNext; + node:=node^.Next; end; end; -procedure TSprvEmit_bin.SaveConst(var buf:TSVInstrBuffer;node:PsrConst); -var - i:dword; -begin - - if (node^.key.count=0) then - begin - if (node^.key.dtype=dtBool) then - begin - Case node^.AsBool of - True :buf.NewOp(Op.OpConstantTrue); - False:buf.NewOp(Op.OpConstantFalse); - end; - - buf.AddTypeId(node^.pType); - buf.AddConstId(node); - end else - begin - buf.NewOp(Op.OpConstant); - buf.AddTypeId(node^.pType); - buf.AddConstId(node); - - Case BitSizeType(node^.key.dtype) of - 8:buf.AddParamId(node^.AsByte); - 16:buf.AddParamId(node^.AsWord); - 32:buf.AddParamId(node^.AsUint); - 64:begin - buf.AddParamId(Lo(node^.AsUint64)); - buf.AddParamId(Hi(node^.AsUint64)); - end; - else - Assert(false,'SaveConst'); - end; - - end; - end else - begin - buf.NewOp(Op.OpConstantComposite); - buf.AddTypeId(node^.pType); - buf.AddConstId(node); - - For i:=0 to node^.key.count-1 do - begin - buf.AddConstId(node^.GetCompItem(i)); - end; - end; - -end; - procedure TSprvEmit_bin.SaveConst(Stream:TStream); var buf:TSVInstrBuffer; node:PsrConst; + i:Word; begin buf:=Default(TSVInstrBuffer); - node:=FConsts.FList.pHead; + node:=ConstList.FList.pHead; While (node<>nil) do begin - if (node^.key.dtype<>dtUnknow) then + if (node^.dtype<>dtUnknow) then begin - SaveConst(buf,node); + buf.NewOp(node^.OpId); + buf.AddNode(node^.pType); + buf.AddNode(node); + + if (node^.dtype<>dtBool) and (node^.ItemCount<>0) then + begin + For i:=0 to node^.ItemCount-1 do + begin + buf.AddNode(node^.GetItem(i)); + end; + end; + buf.Flush(Stream); end; - node:=node^.pNext; + node:=node^.Next; end; end; @@ -421,52 +274,19 @@ var node:PsrVariable; begin buf:=Default(TSVInstrBuffer); - node:=FVariables.pHead; + node:=VariableList.First; While (node<>nil) do begin if (node^.pType<>nil) then begin buf.NewOp(Op.OpVariable); - buf.AddTypeId(node^.pType); - buf.AddVarId(node); - buf.AddParamId(node^.GetStorageClass); + buf.AddNode(node^.pType); + buf.AddNode(node); + buf.AddParam(node^.GetStorageClass); + buf.Flush(Stream); end; - node:=node^.pNext; - end; -end; - -procedure SaveOpSingle(var buf:TSVInstrBuffer;const Param:TOpParamSingle); -begin - Assert(Param.pData<>nil,'SaveOpSingle$1'); - Case Param.ntype of - ntFunc :buf.AddFuncId(Param.pData); - ntRefId:buf.AddRefId(Param.pData); - ntType :buf.AddTypeId(Param.pData); - ntReg :buf.AddRegId(Param.pData); - ntVar :buf.AddVarId(Param.pData); - ntChain:buf.AddChainId(Param.pData); - ntConst:buf.AddConstId(Param.pData); - else - Assert(false,'PrintOpSingle$3'); - end; -end; - -procedure SaveOpParamNode(var buf:TSVInstrBuffer;node:POpParamNode); -begin - Case node^.ntype of - ntLiteral: - begin - buf.AddParamId(node^.Value); - end; - ntString: - begin - buf.AddString(@node^.name); - end; - else - begin - SaveOpSingle(buf,node^.AsParam); - end; + node:=node^.Next; end; end; @@ -474,11 +294,11 @@ procedure TSprvEmit_bin.SaveFunc(Stream:TStream); var pFunc:PSpirvFunc; begin - pFunc:=FSpirvFuncs.FList.pHead; + pFunc:=FuncList.First; While (pFunc<>nil) do begin - SaveOpBlock(Stream,@pFunc^.FTop); - pFunc:=pFunc^.pNext; + SaveOpBlock(Stream,pFunc^.pTop); + pFunc:=pFunc^.Next; end; end; @@ -497,58 +317,46 @@ begin if Info.rstype then //dst type begin - Assert(node^.dst_type<>nil,'SaveOp$4'); - buf.AddTypeId(node^.dst_type); + Assert(node^.pType<>nil,'SaveOp$1'); + if (node^.pType<>nil) then + begin + buf.AddNode(node^.pType); + end else + begin + buf.Reset; + Exit; + end; end; if Info.result then //dst begin - Assert(node^.dst.ntype<>ntUnknow,'SaveOp$1'); - Assert(node^.dst.pData<>nil,'SaveOp$2'); - SaveOpSingle(buf,node^.dst); + Assert(node^.pDst<>nil,'SaveOp$2'); + if (node^.pDst<>nil) then + begin + buf.AddNode(node^.pDst); + end else + begin + buf.Reset; + Exit; + end; end else begin //no dst - if (node^.dst.ntype<>ntUnknow) then + if (node^.pDst<>nil) then begin - Assert(node^.dst.pData<>nil,'SaveOp$3'); - SaveOpSingle(buf,node^.dst); + buf.AddNode(node^.pDst); end; end; - Param:=node^.pParam.pHead; + Param:=node^.ParamFirst; While (Param<>nil) do begin - SaveOpParamNode(buf,Param); - Param:=Param^.pNext; + buf.AddNode(Param^.Value); + Param:=Param^.Next; end; buf.Flush(Stream); end; -procedure TSprvEmit_bin.SaveOpBlock(Stream:TStream;pBlock:PsrOpBlock); -var - node:PSpirvOp; -begin - if (pBlock=nil) then Exit; - node:=pBlock^.pHead; - While (node<>nil) do - begin - - if (node^.OpId=OpBlock) then - begin - if (node^.dst.ntype=ntBlock) then - begin - SaveOpBlock(Stream,node^.dst.pData); - end; - end else - begin - SaveOp(Stream,node); - end; - - node:=node^.pNext; - end; -end; - end. diff --git a/spirv/emit_ds.pas b/spirv/emit_ds.pas deleted file mode 100644 index 3acaf227..00000000 --- a/spirv/emit_ds.pas +++ /dev/null @@ -1,64 +0,0 @@ -unit emit_DS; - -{$mode objfpc}{$H+} - -interface - -uses - sysutils, - ps4_pssl, - srTypes, - srReg, - spirv, - SprvEmit, - emit_op; - -type - TEmit_DS=object(TEmitOp) - procedure _emit_DS; - procedure _emit_DS_SWIZZLE_B32; - end; - -implementation - -procedure TEmit_DS._emit_DS_SWIZZLE_B32; //TODO -Var - dst:PsrRegSlot; -begin - dst:=FRegsStory.get_vdst8(FSPI.DS.VDST); - SetConst(dst,dtFloat32,0); -end; - -procedure TEmit_DS._emit_DS; -begin - - Case FSPI.DS.OP of - - DS_NOP:; - - //DS_SWIZZLE_B32 v4 v3 v0 v0 OFFSET:0x80AA GDS:0 - - DS_SWIZZLE_B32: //TODO - begin; - _emit_DS_SWIZZLE_B32; - end; - - else - Assert(false,'DS?'); - end; - -end; - -{ -OFFSET0:Byte; -OFFSET1:Byte; -GDS:bit1; -ADDR:Byte; (vbindex) -DATA0:Byte; (vsrc0) -DATA1:Byte; (vsrc1) -VDST:Byte; -} - -end. - - diff --git a/spirv/emit_exp.pas b/spirv/emit_exp.pas index 34fef3cd..c8c43254 100644 --- a/spirv/emit_exp.pas +++ b/spirv/emit_exp.pas @@ -6,27 +6,26 @@ interface uses sysutils, - spirv, ps4_pssl, - srNodes, - srLabel, - srTypes, + srCFGLabel, + srConfig, + srFlow, + srType, srReg, srVariable, srOutput, srOp, srOpUtils, - SprvEmit, - emit_op; + emit_fetch; type - TEmit_EXP=object(TEmitOp) - procedure _emit_EXP; + TEmit_EXP=class(TEmitFetch) + procedure emit_EXP; end; implementation -procedure TEmit_EXP._emit_EXP; +procedure TEmit_EXP.emit_EXP; Var exc:PsrRegNode; node:PSpirvOp; @@ -35,7 +34,7 @@ Var dout:PsrVariable; dst:PsrRegNode; src:array[0..3] of PsrRegNode; - rsl:array[0..3] of PsrRegNode; + //rsl:array[0..3] of PsrRegNode; rtype:TsrDataType; f,i,p:Byte; @@ -46,12 +45,12 @@ begin if (FSPI.EXP.VM<>0) and (FSPI.EXP.DONE<>0) then begin pOpBlock:=AllocBlockOp; - pOpBlock^.SetInfo(btOther,FCursor.Adr,FCursor.Adr); + pOpBlock^.SetInfo(btOther,Cursor.Adr,Cursor.Adr); PushBlockOp(line,pOpBlock,nil); - exc:=MakeRead(@FRegsStory.EXEC[0],dtBool); + exc:=MakeRead(get_exec0,dtBool); node:=AddSpirvOp(OpMakeExp); - node^.AddParam(ntReg,exc); //<-fetch read + node^.AddParam(exc); //<-fetch read end; //before @@ -60,13 +59,13 @@ begin begin if (pOpBlock<>nil) then //is pushed begin - FMain^.PopBlock; + Main^.PopBlock; end; Exit; end; pOpBlock:=AllocBlockOp; //down - pOpBlock^.SetInfo(btOther,FCursor.Adr,FCursor.Adr); + pOpBlock^.SetInfo(btOther,Cursor.Adr,Cursor.Adr); PushBlockOp(line,pOpBlock,nil); //output @@ -94,7 +93,7 @@ begin Assert(false); end; dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),dtFloat32); //output in FSPI.EXP.TGT - emit_OpStore(line,dout,src[0]); + OpStore(line,dout,src[0]); end else begin @@ -128,11 +127,10 @@ begin Inc(i); end; - dst:=emit_OpMakeVec(line,rtype,p,@src); - dst^.mark_read; + dst:=OpMakeVec(line,rtype,@src); dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),rtype); //output in FSPI.EXP.TGT - emit_OpStore(line,dout,dst); + OpStore(line,dout,dst); end; end else @@ -153,43 +151,31 @@ begin Assert(false); end; - if FUseOutput16 then + if Config.UseOutput16 then begin - dst:=emit_OpMakeVec(line,dtVec4h,4,@src); - dst^.mark_read; + dst:=OpMakeVec(line,dtVec4h,@src); 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; + 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:=OpMakeVec(line,rtype,@src); + dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),rtype); //output in FSPI.EXP.TGT - emit_OpStore(line,dout,dst); + OpStore(line,dout,dst); end; if (pOpBlock<>nil) then //is pushed begin - FMain^.PopBlock; - FMain^.PopBlock; + Main^.PopBlock; + Main^.PopBlock; end; end; diff --git a/spirv/emit_fetch.pas b/spirv/emit_fetch.pas new file mode 100644 index 00000000..1bd6d36b --- /dev/null +++ b/spirv/emit_fetch.pas @@ -0,0 +1,613 @@ +unit emit_fetch; + +{$mode objfpc}{$H+} + +interface + +uses + ps4_pssl, + srNode, + srBitcast, + srType, + srTypes, + srConst, + srReg, + srOp, + srOpUtils, + srLayout, + srVertLayout, + srFragLayout, + srVariable, + srInput, + srOutput, + srUniform, + srFlow; + +type + TEmitFetch=class(TEmitFlow) + // + function GroupingSharp(src:PPsrRegSlot;rtype:TsrResourceType):PsrDataLayout; + // + procedure PrepTypeSlot(pSlot:PsrRegSlot;rtype:TsrDataType); + function MakeRead(pSlot:PsrRegSlot;rtype:TsrDataType):PsrRegNode; + // + function PrepTypeNode(var node:PsrRegNode;rtype:TsrDataType;relax:Boolean=true):Integer; + function PrepTypeDst(var node:PsrRegNode;rtype:TsrDataType;relax:Boolean=true):Integer; + function PrepTypeParam(node:POpParamNode;rtype:TsrDataType;relax:Boolean=true):Integer; + // + function get_vcc0:PsrRegSlot; + function get_vcc1:PsrRegSlot; + function get_m0:PsrRegSlot; + function get_exec0:PsrRegSlot; + function get_exec1:PsrRegSlot; + function get_scc:PsrRegSlot; + // + function get_sdst7(SDST:Byte):PsrRegSlot; + function get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean; + 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):PsrRegNode; + function fetch_ssrc9(SSRC:Word;rtype:TsrDataType):PsrRegNode; + function fetch_ssrc9_pair(SSRC:Word;src:PPsrRegNode;rtype:TsrDataType):Boolean; + function fetch_vsrc8(VSRC:Word;rtype:TsrDataType):PsrRegNode; + function fetch_vdst8(VDST:Word;rtype:TsrDataType):PsrRegNode; + procedure fetch_vsrc8_vec2h(VSRC:Word;var dst0,dst1:PsrRegNode); + // + procedure OpCmpV(OpId:DWORD;dst:PsrRegSlot;src0,src1:PsrRegNode); + procedure OpCmpS(OpId:DWORD;dst:PsrRegSlot;src0,src1:PsrRegNode); + procedure OpConvFloatToHalf2(dst:PsrRegSlot;src0,src1:PsrRegNode); + // + function AddInput(dst:PsrRegSlot;rtype:TsrDataType;itype:TpsslInputType;id:Byte=0):PsrRegNode; + function AddAncillary(dst:PsrRegSlot):PsrRegNode; + function AddVertLayout(pLayout:PsrDataLayout;rtype:TsrDataType):PsrRegNode; + function AddFragLayout(itype:TpsslInputType;rtype:TsrDataType;location:DWORD):PsrRegNode; + function FetchLoad(pChain:PsrChain;rtype:TsrDataType):PsrRegNode; + Procedure FetchStore(pChain:PsrChain;src:PsrRegNode); + procedure AddUserdata(dst:PsrRegSlot;offset_dw:Byte); + function FetchChain(grp:PsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrRegNode; + function MakeChain(pSlot:PsrRegSlot;grp:PsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrRegNode; + Procedure AddVecInput(dst:PsrRegSlot;vtype,rtype:TsrDataType;itype:TpsslInputType;id:Byte); + function FetchUniform(src:PsrDataLayout;pType:PsrType):PsrNode; + function FetchImage(src:PsrDataLayout;dtype:TsrDataType;info:TsrTypeImageInfo):PsrNode; + function FetchSampler(src:PsrDataLayout):PsrNode; + function FetchOutput(etype:TpsslExportType;rtype:TsrDataType):PsrVariable; + end; + +function GetInputRegNode(node:PsrRegNode):PsrInput; + +implementation + +function GetInputRegNode(node:PsrRegNode):PsrInput; +var + pSource:PsrNode; +begin + pSource:=GetSourceRegNode(node); + Result:=pSource^.AsType(ntInput); +end; + +// + +function TEmitFetch.GroupingSharp(src:PPsrRegSlot;rtype:TsrResourceType):PsrDataLayout; +var + chain:TsrChains; + i,n:Byte; +begin + Result:=nil; + chain:=Default(TsrChains); + n:=GetResourceSizeDw(rtype); + + For i:=0 to n-1 do + begin + chain[i]:=GetChainRegNode(src[i]^.current); + end; + + Result:=DataLayoutList.Grouping(chain,rtype); +end; + +// + +procedure TEmitFetch.PrepTypeSlot(pSlot:PsrRegSlot;rtype:TsrDataType); +begin + if (pSlot=nil) then Exit; + if (pSlot^.current=nil) then + begin + pSlot^.New(line,rtype); //Unresolve + Exit; + end; + + pSlot^.current^.PrepType(ord(rtype)); +end; + +function TEmitFetch.MakeRead(pSlot:PsrRegSlot;rtype:TsrDataType):PsrRegNode; +var + node:PsrRegNode; +begin + Result:=nil; + if (pSlot=nil) then Exit; + PrepTypeSlot(pSlot,rtype); + node:=pSlot^.current; + if (rtype<>dtUnknow) and (not CompareType(node^.dtype,rtype)) then + begin + Result:=BitcastList.FetchRead(rtype,node); + end else + begin + Result:=node; + end; + if (rtype<>dtUnknow) then + begin + Result^.Weak:=False; + end; +end; + +// + +function TEmitFetch.PrepTypeNode(var node:PsrRegNode;rtype:TsrDataType;relax:Boolean=true):Integer; +begin + Result:=0; + if (node=nil) then Exit; + if (rtype=dtUnknow) then Exit; + + if is_unprep_type(node^.dtype,rtype,node^.Weak) then + begin + node^.PrepType(ord(rtype)); + Inc(Result); + end else + begin + Case relax of + True :relax:=CompareType(node^.dtype,rtype); + False:relax:=(node^.dtype=rtype); + end; + if not relax then + begin + node:=BitcastList.FetchRead(rtype,node); + Inc(Result); + end; + end; +end; + +function TEmitFetch.PrepTypeDst(var node:PsrRegNode;rtype:TsrDataType;relax:Boolean=true):Integer; +begin + Result:=0; + if (node=nil) then Exit; + if (rtype=dtUnknow) then Exit; + + if is_unprep_type(node^.dtype,rtype,node^.Weak) then + begin + node^.PrepType(ord(rtype)); + Inc(Result); + end else + begin + Case relax of + True :relax:=CompareType(node^.dtype,rtype); + False:relax:=(node^.dtype=rtype); + end; + if not relax then + begin + node:=BitcastList.FetchDstr(rtype,node); + Inc(Result); + end; + end; +end; + +function TEmitFetch.PrepTypeParam(node:POpParamNode;rtype:TsrDataType;relax:Boolean=true):Integer; +var + pReg:PsrRegNode; +begin + Result:=0; + if (node=nil) then Exit; + if (rtype=dtUnknow) then Exit; + if node^.Value^.IsType(ntReg) then + begin + pReg:=node^.AsReg; + Result:=PrepTypeNode(pReg,rtype,relax); + node^.Value:=pReg; + end else + begin + node^.Value^.PrepType(ord(rtype)); + end; +end; + +// + +function TEmitFetch.get_vcc0:PsrRegSlot; +begin + Result:=@RegsStory.VCC[0]; +end; + +function TEmitFetch.get_vcc1:PsrRegSlot; +begin + Result:=@RegsStory.VCC[1]; +end; + +function TEmitFetch.get_m0:PsrRegSlot; +begin + Result:=@RegsStory.M0; +end; + +function TEmitFetch.get_exec0:PsrRegSlot; +begin + Result:=@RegsStory.EXEC[0]; +end; + +function TEmitFetch.get_exec1:PsrRegSlot; +begin + Result:=@RegsStory.EXEC[1]; +end; + +function TEmitFetch.get_scc:PsrRegSlot; +begin + Result:=@RegsStory.SCC; +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_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):PsrRegNode; +Var + src:PsrRegSlot; + pConst:PsrConst; +begin + if is_const_ssrc8(SOFFSET) then + begin + pConst:=ConstList.Fetch_ssrc8_const(SOFFSET,0,rtype); + Result:=NewReg(pConst); + end else + begin + src:=RegsStory.get_ssrc8(SOFFSET); + Result:=MakeRead(src,rtype); + end; +end; + +function TEmitFetch.fetch_ssrc9(SSRC:Word;rtype:TsrDataType):PsrRegNode; +Var + src:PsrRegSlot; + pConst:PsrConst; +begin + if is_const_ssrc9(SSRC) then + begin + pConst:=ConstList.Fetch_ssrc9_const(SSRC,FSPI.INLINE32,rtype); + Result:=NewReg(pConst); + end else + begin + src:=RegsStory.get_ssrc9(SSRC); + Result:=MakeRead(src,rtype); + end; +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]:=NewReg(ConstList.Fetch_ssrc9_const(SSRC,FSPI.INLINE32,rtype)); + src[1]:=NewReg(ConstList.Fetch(dtUnknow,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_vsrc8(VSRC:Word;rtype:TsrDataType):PsrRegNode; +var + src:PsrRegSlot; +begin + src:=RegsStory.get_vsrc8(VSRC); + Result:=MakeRead(src,rtype); +end; + +function TEmitFetch.fetch_vdst8(VDST:Word;rtype:TsrDataType):PsrRegNode; +var + src:PsrRegSlot; +begin + src:=RegsStory.get_vdst8(VDST); + Result:=MakeRead(src,rtype); +end; + +procedure TEmitFetch.fetch_vsrc8_vec2h(VSRC:Word;var dst0,dst1:PsrRegNode); +var + pSlot:PsrRegSlot; + dst:PsrRegNode; +begin + pSlot:=RegsStory.get_vsrc8(VSRC); + + dst:=MakeRead(pSlot,dtVec2h); + + dst0:=NewReg(dtHalf16); + dst1:=NewReg(dtHalf16);; + + OpExtract(line,dst0,dst,0); + OpExtract(line,dst1,dst,1); +end; + +// + +procedure TEmitFetch.OpCmpV(OpId:DWORD;dst:PsrRegSlot;src0,src1:PsrRegNode); +Var + tmp:PsrRegNode; + exc:PsrRegNode; +begin + tmp:=NewReg(dtBool); + + _Op2(line,OpId,tmp,src0,src1); + + exc:=MakeRead(get_exec0,dtBool); + OpLogicalAnd(dst,tmp,exc); +end; + +procedure TEmitFetch.OpCmpS(OpId:DWORD;dst:PsrRegSlot;src0,src1:PsrRegNode); +begin + Op2(OpId,dtBool,dst,src0,src1); +end; + +procedure TEmitFetch.OpConvFloatToHalf2(dst:PsrRegSlot;src0,src1:PsrRegNode); +var + rsl:array[0..1] of PsrRegNode; +begin + rsl[0]:=OpFToF(src0,dtHalf16); + rsl[1]:=OpFToF(src1,dtHalf16); + + dst^.New(line,dtVec2h); + + OpMakeCon(line,dst^.current,@rsl); +end; + +// + +function TEmitFetch.AddInput(dst:PsrRegSlot;rtype:TsrDataType;itype:TpsslInputType;id:Byte=0):PsrRegNode; +var + i:PsrInput; + v:PsrVariable; + r:PsrRegNode; +begin + i:=InputList.Fetch(rtype,itype,id); + + v:=i^.pVar; + r:=i^.pReg; + + if (r=nil) then + begin + r:=dst^.New(line,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.AddAncillary(dst:PsrRegSlot):PsrRegNode; +var + src:array[0..2] of PsrRegNode; +begin + src[0]:=NewReg_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:PsrDataLayout;rtype:TsrDataType):PsrRegNode; +var + i:PsrVertLayout; + v:PsrVariable; + dst:PsrRegNode; +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):PsrRegNode; +var + i:PsrFragLayout; + v:PsrVariable; + dst:PsrRegNode; +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:PsrChain;rtype:TsrDataType):PsrRegNode; +begin + Result:=nil; + if (pChain=nil) then Exit; + + Result:=NewReg(rtype); + + pChain^.FetchLoad(line,Result); +end; + +Procedure TEmitFetch.FetchStore(pChain:PsrChain;src:PsrRegNode); +begin + if (pChain=nil) or (src=nil) then Exit; + + pChain^.FetchStore(line,src); +end; + +procedure TEmitFetch.AddUserdata(dst:PsrRegSlot;offset_dw:Byte); +var + lvl_0:TsrChainLvl_0; + pLayout:PsrDataLayout; + pChain:PsrChain; + pReg:PsrRegNode; +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:PsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrRegNode; +var + pChain:PsrChain; +begin + pChain:=grp^.Fetch(lvl_0,lvl_1); + Result:=FetchLoad(pChain,dtUnknow); +end; + +function TEmitFetch.MakeChain(pSlot:PsrRegSlot;grp:PsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrRegNode; +var + pChain:PsrChain; + pReg:PsrRegNode; +begin + pChain:=grp^.Fetch(lvl_0,lvl_1); + 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:PsrRegNode; +begin + rsl:=AddInput(@RegsStory.FUnattach,vtype,itype,0); + OpExtract(init_line,dst^.New(line,rtype),rsl,id); +end; + +//// + +function TEmitFetch.FetchUniform(src:PsrDataLayout;pType:PsrType):PsrNode; +var + u:PsrUniform; + v:PsrVariable; + r:PsrRegUniform; +begin + u:=UniformList.Fetch(src,pType); + 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:PsrDataLayout;dtype:TsrDataType;info:TsrTypeImageInfo):PsrNode; +var + pType:PsrType; +begin + pType:=TypeList.Fetch(dtype); + pType:=TypeList.FetchImage(pType,info); + Result:=FetchUniform(src,pType); +end; + +function TEmitFetch.FetchSampler(src:PsrDataLayout):PsrNode; +var + pType:PsrType; +begin + pType:=TypeList.Fetch(dtTypeSampler); + Result:=FetchUniform(src,pType); +end; + +function TEmitFetch.FetchOutput(etype:TpsslExportType;rtype:TsrDataType):PsrVariable; +var + o:PsrOutput; +begin + o:=OutputList.Fetch(etype,rtype); + Result:=o^.pVar; +end; + +end. + diff --git a/spirv/emit_mimg.pas b/spirv/emit_mimg.pas index b80a6a2c..d067af2c 100644 --- a/spirv/emit_mimg.pas +++ b/spirv/emit_mimg.pas @@ -10,24 +10,24 @@ uses si_ci_vi_merged_enum, ps4_shader, ps4_pssl, - srNodes, - srTypes, - srConst, + srNode, + srType, srReg, srLayout, srOp, - SprvEmit, - emit_op; + emit_fetch; type - TEmit_MIMG=object(TEmitOp) - procedure _emit_MIMG; - procedure _DistribDmask(dst:PsrRegNode;telem:TsrDataType); - Function _GatherCoord_f(var offset:DWORD;dim_id:Byte):PsrRegNode; - Function _GatherCoord_u(var offset:DWORD;dim_id:Byte):PsrRegNode; - Function _Gather_packed_offset(var offset:DWORD;dim:Byte):PsrRegNode; - procedure _emit_image_sample(Tgrp:PsrRegNode;info:PsrImageInfo); - procedure _emit_image_load(Tgrp:PsrRegNode;info:PsrImageInfo); + TEmit_MIMG=class(TEmitFetch) + procedure emit_MIMG; + procedure DistribDmask(dst:PsrRegNode;telem:TsrDataType); + function GatherDmask(telem:TsrDataType):PsrRegNode; + Function GatherCoord_f(var offset:DWORD;dim_id:Byte):PsrRegNode; + Function GatherCoord_u(var offset:DWORD;dim_id:Byte):PsrRegNode; + Function Gather_packed_offset(var offset:DWORD;dim:Byte):PsrRegNode; + procedure emit_image_sample(Tgrp:PsrNode;info:PsrImageInfo); + procedure emit_image_load(Tgrp:PsrNode;info:PsrImageInfo); + procedure emit_image_store(Tgrp:PsrNode;info:PsrImageInfo); end; implementation @@ -373,7 +373,7 @@ begin Result.tinfo.Format :=GetImageFormat(PT); end; -procedure TEmit_MIMG._DistribDmask(dst:PsrRegNode;telem:TsrDataType); //result +procedure TEmit_MIMG.DistribDmask(dst:PsrRegNode;telem:TsrDataType); //result var pSlot:PsrRegSlot; i,d:Byte; @@ -382,14 +382,40 @@ begin For i:=0 to 3 do if Byte(FSPI.MIMG.DMASK).TestBit(i) then begin - pSlot:=FRegsStory.get_vdst8(FSPI.MIMG.VDATA+d); Inc(d); + pSlot:=get_vdst8(FSPI.MIMG.VDATA+d); + Inc(d); Assert(pSlot<>nil); - dst^.mark_read; - emit_OpCompExtract(line,pSlot^.New(line,telem),dst,i); + OpExtract(line,pSlot^.New(line,telem),dst,i); end; end; -Function TEmit_MIMG._GatherCoord_f(var offset:DWORD;dim_id:Byte):PsrRegNode; //src +function TEmit_MIMG.GatherDmask(telem:TsrDataType):PsrRegNode; +var + src:array[0..3] of PsrRegNode; + i,d,m:Byte; +begin + d:=0; + For i:=0 to 3 do + if Byte(FSPI.MIMG.DMASK).TestBit(i) then + begin + src[i]:=fetch_vsrc8(FSPI.MIMG.VDATA+d,telem); + Inc(d); + m:=i; + end else + begin + src[i]:=nil; + end; + + //Result:=telem.AsVector(4); + For i:=0 to m do + begin + Assert(src[i]<>nil,'TODO: zero or prev value?'); + end; + + Result:=OpMakeVec(line,telem.AsVector(m+1),@src); +end; + +Function TEmit_MIMG.GatherCoord_f(var offset:DWORD;dim_id:Byte):PsrRegNode; //src var src:array[0..3] of PsrRegNode; i,count:Byte; @@ -416,8 +442,7 @@ begin src[2]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+2,dtFloat32); //face end; - Result:=emit_OpMakeCube(line,GetVecType(dtFloat32,count),count,@src); - Result^.mark_read; + Result:=OpMakeCub(line,TsrDataType(dtFloat32).AsVector(count),@src); end else begin @@ -432,8 +457,7 @@ begin Result:=src[0]; end else begin - Result:=emit_OpMakeVec(line,GetVecType(dtFloat32,count),count,@src); - Result^.mark_read; + Result:=OpMakeVec(line,TsrDataType(dtFloat32).AsVector(count),@src); end; end; @@ -441,7 +465,7 @@ begin offset:=offset+count; end; -Function TEmit_MIMG._GatherCoord_u(var offset:DWORD;dim_id:Byte):PsrRegNode; //src +Function TEmit_MIMG.GatherCoord_u(var offset:DWORD;dim_id:Byte):PsrRegNode; //src var src:array[0..3] of PsrRegNode; i,count:Byte; @@ -468,8 +492,7 @@ begin src[2]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+2,dtInt32); //face end; - Result:=emit_OpMakeCube(line,GetVecType(dtInt32,count),count,@src); - Result^.mark_read; + Result:=OpMakeCub(line,TsrDataType(dtInt32).AsVector(count),@src); end else begin @@ -484,8 +507,7 @@ begin Result:=src[0]; end else begin - Result:=emit_OpMakeVec(line,GetVecType(dtInt32,count),count,@src); - Result^.mark_read; + Result:=OpMakeVec(line,TsrDataType(dtInt32).AsVector(count),@src); end; end; @@ -493,7 +515,7 @@ begin offset:=offset+count; end; -Function TEmit_MIMG._Gather_packed_offset(var offset:DWORD;dim:Byte):PsrRegNode; +Function TEmit_MIMG.Gather_packed_offset(var offset:DWORD;dim:Byte):PsrRegNode; var src:PsrRegNode; begin @@ -503,22 +525,21 @@ begin Inc(offset); Case dim of - 1:Result:=emit_OpPackOfs(line,dtInt32,dim,src); - 2:Result:=emit_OpPackOfs(line,dtVec2i,dim,src); - 3:Result:=emit_OpPackOfs(line,dtVec3i,dim,src); + 1:Result:=OpPackOfs(line,dtInt32,dim,src); + 2:Result:=OpPackOfs(line,dtVec2i,dim,src); + 3:Result:=OpPackOfs(line,dtVec3i,dim,src); else Assert(False); end; - Result^.mark_read; end; -procedure TEmit_MIMG._emit_image_sample(Tgrp:PsrRegNode;info:PsrImageInfo); +procedure TEmit_MIMG.emit_image_sample(Tgrp:PsrNode;info:PsrImageInfo); var src:array[0..3] of PsrRegSlot; pLayout:PsrDataLayout; - Sgrp:PsrRegNode; + Sgrp:PsrNode; dst,cmb,coord,lod,offset:PsrRegNode; @@ -527,72 +548,71 @@ var node:PSpirvOp; begin - if not FRegsStory.get_srsrc(FSPI.MIMG.SSAMP,4,@src) then Assert(false); + if not get_srsrc(FSPI.MIMG.SSAMP,4,@src) then Assert(false); pLayout:=GroupingSharp(src,rtSSharp4); Sgrp:=FetchSampler(pLayout); - cmb:=emit_OpSampledImage(line,Tgrp,Sgrp,info^.dtype,info^.tinfo); - cmb^.mark_read; + cmb:=OpSampledImage(line,Tgrp,Sgrp,info^.dtype,info^.tinfo); - dst:=NewReg(GetVecType(info^.dtype,4)); + dst:=NewReg(info^.dtype.AsVector(4)); roffset:=0; Case FSPI.MIMG.OP of IMAGE_SAMPLE: begin - coord:=_GatherCoord_f(roffset,info^.tinfo.Dim); + coord:=GatherCoord_f(roffset,info^.tinfo.Dim); if (FExecutionModel=ExecutionModel.Fragment) then begin - node:=emit_OpImageSampleImplicitLod(line,dst,cmb,coord); + node:=OpImageSampleImplicitLod(line,cmb,dst,coord); end else begin - node:=emit_OpImageSampleExplicitLod(line,dst,cmb,coord); + node:=OpImageSampleExplicitLod(line,cmb,dst,coord); end; end; IMAGE_SAMPLE_LZ: begin - coord:=_GatherCoord_f(roffset,info^.tinfo.Dim); + coord:=GatherCoord_f(roffset,info^.tinfo.Dim); - node:=emit_OpImageSampleExplicitLod(line,dst,cmb,coord); + node:=OpImageSampleExplicitLod(line,cmb,dst,coord); node^.AddLiteral(ImageOperands.Lod,'Lod'); //0 - lod:=FetchReg(FConsts.Fetchf(dtFloat32,0)); - node^.AddParam(ntReg,lod); + lod:=NewReg_s(dtFloat32,0); + node^.AddParam(lod); end; IMAGE_SAMPLE_LZ_O: begin - offset:=_Gather_packed_offset(roffset,GetDimCount(info^.tinfo.Dim)); + offset:=Gather_packed_offset(roffset,GetDimCount(info^.tinfo.Dim)); - coord:=_GatherCoord_f(roffset,info^.tinfo.Dim); + coord:=GatherCoord_f(roffset,info^.tinfo.Dim); - node:=emit_OpImageSampleExplicitLod(line,dst,cmb,coord); + node:=OpImageSampleExplicitLod(line,cmb,dst,coord); node^.AddLiteral(ImageOperands.Lod or ImageOperands.ConstOffset,'Lod|ConstOffset'); //0 - lod:=FetchReg(FConsts.Fetchf(dtFloat32,0)); - node^.AddParam(ntReg,lod); + lod:=NewReg_s(dtFloat32,0); + node^.AddParam(lod); //1 - node^.AddParam(ntReg,offset); + node^.AddParam(offset); end; else Assert(false); end; - _DistribDmask(dst,info^.dtype); + DistribDmask(dst,info^.dtype); end; -procedure TEmit_MIMG._emit_image_load(Tgrp:PsrRegNode;info:PsrImageInfo); +procedure TEmit_MIMG.emit_image_load(Tgrp:PsrNode;info:PsrImageInfo); var dst,coord,lod,smp:PsrRegNode; @@ -601,15 +621,15 @@ var node:PSpirvOp; begin - dst:=NewReg(GetVecType(info^.dtype,4)); + dst:=NewReg(info^.dtype.AsVector(4)); roffset:=0; Case FSPI.MIMG.OP of IMAGE_LOAD: begin - coord:=_GatherCoord_u(roffset,info^.tinfo.Dim); - node:=emit_OpImageFetch(line,Tgrp,dst,coord); + coord:=GatherCoord_u(roffset,info^.tinfo.Dim); + node:=OpImageFetch(line,Tgrp,dst,coord); if (info^.tinfo.MS<>0) then //fragid T# 2D MSAA begin @@ -617,35 +637,79 @@ begin Inc(roffset); node^.AddLiteral(ImageOperands.Sample,'Sample'); - node^.AddParam(ntReg,smp); + node^.AddParam(smp); end; end; IMAGE_LOAD_MIP: //All except MSAA begin - coord:=_GatherCoord_u(roffset,info^.tinfo.Dim); - node:=emit_OpImageFetch(line,Tgrp,dst,coord); + coord:=GatherCoord_u(roffset,info^.tinfo.Dim); + node:=OpImageFetch(line,Tgrp,dst,coord); lod:=fetch_vsrc8(FSPI.MIMG.VADDR+roffset,dtUint32); Inc(roffset); node^.AddLiteral(ImageOperands.Lod,'Lod'); - node^.AddParam(ntReg,lod); + node^.AddParam(lod); end; else Assert(false); end; - _DistribDmask(dst,info^.dtype); + DistribDmask(dst,info^.dtype); end; -procedure TEmit_MIMG._emit_MIMG; +procedure TEmit_MIMG.emit_image_store(Tgrp:PsrNode;info:PsrImageInfo); +var + dst,coord,lod,smp:PsrRegNode; + + roffset:DWORD; + + node:PSpirvOp; +begin + dst:=GatherDmask(info^.dtype); + + roffset:=0; + + Case FSPI.MIMG.OP of + IMAGE_STORE: + begin + coord:=GatherCoord_u(roffset,info^.tinfo.Dim); + node:=OpImageWrite(line,Tgrp,coord,dst); + + if (info^.tinfo.MS<>0) then //fragid T# 2D MSAA + begin + smp:=fetch_vsrc8(FSPI.MIMG.VADDR+roffset,dtUint32); + Inc(roffset); + + node^.AddLiteral(ImageOperands.Sample,'Sample'); + node^.AddParam(smp); + end; + end; + IMAGE_STORE_MIP: //All except MSAA + begin + coord:=GatherCoord_u(roffset,info^.tinfo.Dim); + node:=OpImageWrite(line,Tgrp,coord,dst); + + lod:=fetch_vsrc8(FSPI.MIMG.VADDR+roffset,dtUint32); + Inc(roffset); + + node^.AddLiteral(ImageOperands.Lod,'Lod'); + node^.AddParam(lod); + end; + else + Assert(false); + end; + +end; + +procedure TEmit_MIMG.emit_MIMG; var src:array[0..7] of PsrRegSlot; pLayout:PsrDataLayout; info:TsrImageInfo; - Tgrp:PsrRegNode; + Tgrp:PsrNode; begin @@ -656,17 +720,13 @@ begin Case FSPI.MIMG.R128 of 0: begin - if not FRegsStory.get_srsrc(FSPI.MIMG.SRSRC,8,@src) then Assert(false); + if not get_srsrc(FSPI.MIMG.SRSRC,8,@src) then Assert(false); pLayout:=GroupingSharp(src,rtTSharp4); - //print_tsharp4(pLayout^.pData); - //Tgrp:=GroupingSharp(@src,rtTSharp8); end; 1: begin - if not FRegsStory.get_srsrc(FSPI.MIMG.SRSRC,4,@src) then Assert(false); + if not get_srsrc(FSPI.MIMG.SRSRC,4,@src) then Assert(false); pLayout:=GroupingSharp(src,rtTSharp8); - //print_tsharp8(pLayout^.pData); - //Tgrp:=GroupingSharp(@src,rtTSharp4); end; end; @@ -678,7 +738,7 @@ begin info.tinfo.Sampled:=1; Tgrp:=FetchImage(pLayout,info.dtype,info.tinfo); - _emit_image_sample(Tgrp,@info); + emit_image_sample(Tgrp,@info); end; IMAGE_LOAD..IMAGE_LOAD_MIP_PCK_SGN: //loaded @@ -686,10 +746,16 @@ begin info.tinfo.Sampled:=1; Tgrp:=FetchImage(pLayout,info.dtype,info.tinfo); - _emit_image_load(Tgrp,@info); + emit_image_load(Tgrp,@info); end; - IMAGE_STORE:; //TODO + IMAGE_STORE..IMAGE_STORE_MIP_PCK: //stored + begin + info.tinfo.Sampled:=2; + Tgrp:=FetchImage(pLayout,info.dtype,info.tinfo); + + emit_image_store(Tgrp,@info); + end; else Assert(false,'MIMG?'+IntToStr(FSPI.MIMG.OP)); diff --git a/spirv/emit_mtbuf.pas b/spirv/emit_mtbuf.pas index 6137130b..45ac842e 100644 --- a/spirv/emit_mtbuf.pas +++ b/spirv/emit_mtbuf.pas @@ -9,33 +9,32 @@ uses ps4_pssl, srReg, srLayout, - SprvEmit, + emit_fetch, srVBufInfo, emit_vbuf_load, - emit_vbuf_store, - emit_op; + emit_vbuf_store; type - TEmit_MTBUF=object(TEmitOp) - procedure _emit_MTBUF; - procedure _emit_TBUFFER_LOAD_FORMAT(count:Byte); - procedure _emit_TBUFFER_STORE_FORMAT(count:Byte); + TEmit_MTBUF=class(TEmitFetch) + procedure emit_MTBUF; + procedure emit_TBUFFER_LOAD_FORMAT(count:Byte); + procedure emit_TBUFFER_STORE_FORMAT(count:Byte); end; implementation -procedure TEmit_MTBUF._emit_TBUFFER_LOAD_FORMAT(count:Byte); +procedure TEmit_MTBUF.emit_TBUFFER_LOAD_FORMAT(count:Byte); var src:array[0..3] of PsrRegSlot; grp:PsrDataLayout; begin - if not FRegsStory.get_srsrc(FSPI.MTBUF.SRSRC,4,@src) then Assert(false); + if not get_srsrc(FSPI.MTBUF.SRSRC,4,@src) then Assert(false); grp:=GroupingSharp(@src,rtVSharp4); - TEmit_vbuf_load(Self).buf_load( + TEmit_vbuf_load(TObject(Self)).buf_load( Buf_info(grp, dst_sel_identity, FSPI.MTBUF.DFMT, @@ -45,18 +44,18 @@ begin end; -procedure TEmit_MTBUF._emit_TBUFFER_STORE_FORMAT(count:Byte); +procedure TEmit_MTBUF.emit_TBUFFER_STORE_FORMAT(count:Byte); var src:array[0..3] of PsrRegSlot; grp:PsrDataLayout; begin - if not FRegsStory.get_srsrc(FSPI.MTBUF.SRSRC,4,@src) then Assert(false); + if not get_srsrc(FSPI.MTBUF.SRSRC,4,@src) then Assert(false); grp:=GroupingSharp(@src,rtVSharp4); - TEmit_vbuf_store(Self).buf_store( + TEmit_vbuf_store(TObject(Self)).buf_store( Buf_info(grp, dst_sel_identity, FSPI.MTBUF.DFMT, @@ -66,19 +65,19 @@ begin end; -procedure TEmit_MTBUF._emit_MTBUF; +procedure TEmit_MTBUF.emit_MTBUF; begin case FSPI.MTBUF.OP of - TBUFFER_LOAD_FORMAT_X :_emit_TBUFFER_LOAD_FORMAT(1); - TBUFFER_LOAD_FORMAT_XY :_emit_TBUFFER_LOAD_FORMAT(2); - TBUFFER_LOAD_FORMAT_XYZ :_emit_TBUFFER_LOAD_FORMAT(3); - TBUFFER_LOAD_FORMAT_XYZW :_emit_TBUFFER_LOAD_FORMAT(4); + TBUFFER_LOAD_FORMAT_X :emit_TBUFFER_LOAD_FORMAT(1); + TBUFFER_LOAD_FORMAT_XY :emit_TBUFFER_LOAD_FORMAT(2); + TBUFFER_LOAD_FORMAT_XYZ :emit_TBUFFER_LOAD_FORMAT(3); + TBUFFER_LOAD_FORMAT_XYZW :emit_TBUFFER_LOAD_FORMAT(4); - TBUFFER_STORE_FORMAT_X :_emit_TBUFFER_STORE_FORMAT(1); - TBUFFER_STORE_FORMAT_XY :_emit_TBUFFER_STORE_FORMAT(2); - TBUFFER_STORE_FORMAT_XYZ :_emit_TBUFFER_STORE_FORMAT(3); - TBUFFER_STORE_FORMAT_XYZW:_emit_TBUFFER_STORE_FORMAT(4); + TBUFFER_STORE_FORMAT_X :emit_TBUFFER_STORE_FORMAT(1); + TBUFFER_STORE_FORMAT_XY :emit_TBUFFER_STORE_FORMAT(2); + TBUFFER_STORE_FORMAT_XYZ :emit_TBUFFER_STORE_FORMAT(3); + TBUFFER_STORE_FORMAT_XYZW:emit_TBUFFER_STORE_FORMAT(4); end; //OFFSET:bit12; //Unsigned byte offset. diff --git a/spirv/emit_mubuf.pas b/spirv/emit_mubuf.pas index edc4cbcc..ab90488b 100644 --- a/spirv/emit_mubuf.pas +++ b/spirv/emit_mubuf.pas @@ -8,48 +8,53 @@ uses sysutils, ps4_shader, ps4_pssl, - srTypes, + srConfig, + srType, srReg, srLayout, srInput, spirv, - SprvEmit, + emit_fetch, srVBufInfo, emit_vbuf_load, - emit_vbuf_store, - emit_op; + emit_vbuf_store; type - TEmit_MUBUF=object(TEmitOp) - procedure _emit_MUBUF; - procedure _make_load_zero(dst:PsrRegSlot); - procedure _make_load_one(dst:PsrRegSlot); - procedure _make_load_comp(dst:PsrRegSlot;rsl:PsrRegNode;i:Byte); - function _emit_BUFFER_LOAD_VA(src:PPsrRegSlot;count:Byte):Boolean; - procedure _emit_BUFFER_LOAD_FORMAT(count:Byte); - procedure _emit_BUFFER_STORE_FORMAT(count:Byte); + TEmit_MUBUF=class(TEmitFetch) + procedure emit_MUBUF; + procedure make_load_zero(dst:PsrRegSlot;dtype:TsrDataType); + procedure make_load_one(dst:PsrRegSlot;dtype:TsrDataType); + procedure make_load_comp(dst:PsrRegSlot;dtype:TsrDataType;rsl:PsrRegNode;i:Byte); + function emit_BUFFER_LOAD_VA(src:PPsrRegSlot;count:Byte):Boolean; + procedure emit_BUFFER_LOAD_FORMAT(count:Byte); + procedure emit_BUFFER_STORE_FORMAT(count:Byte); end; implementation -procedure TEmit_MUBUF._make_load_zero(dst:PsrRegSlot); +procedure TEmit_MUBUF.make_load_zero(dst:PsrRegSlot;dtype:TsrDataType); begin - SetConst(dst,FConsts.Fetchi(dtFloat32,0)); + SetConst_q(dst,dtype,0); end; -procedure TEmit_MUBUF._make_load_one(dst:PsrRegSlot); +procedure TEmit_MUBUF.make_load_one(dst:PsrRegSlot;dtype:TsrDataType); begin - SetConst(dst,FConsts.Fetchf(dtFloat32,1)); + if (dtype=dtFloat32) then + begin + SetConst_s(dst,dtype,1); + end else + begin + SetConst_i(dst,dtype,1); + end; end; -procedure TEmit_MUBUF._make_load_comp(dst:PsrRegSlot;rsl:PsrRegNode;i:Byte); +procedure TEmit_MUBUF.make_load_comp(dst:PsrRegSlot;dtype:TsrDataType;rsl:PsrRegNode;i:Byte); begin - dst^.New(line,dtFloat32); - rsl^.mark_read; - emit_OpCompExtract(line,dst^.current,rsl,i); + dst^.New(line,dtype); + OpExtract(line,dst^.current,rsl,i); end; -function TEmit_MUBUF._emit_BUFFER_LOAD_VA(src:PPsrRegSlot;count:Byte):Boolean; +function TEmit_MUBUF.emit_BUFFER_LOAD_VA(src:PPsrRegSlot;count:Byte):Boolean; var dst:PsrRegSlot; @@ -61,59 +66,69 @@ var inp_idx:PsrInput; - dsel:Tdst_sel; + info:TBuf_info; + elem_res:TsrDataType; + elem_vec:TsrDataType; i,d,elem_count:Byte; begin Result:=False; - idx:=FRegsStory.get_vsrc8(FSPI.MUBUF.VADDR+0)^.current; + idx:=get_vsrc8(FSPI.MUBUF.VADDR+0)^.current; inp_idx:=GetInputRegNode(idx); if (inp_idx<>nil) then - if (inp_idx^.key.itype=itVIndex) then //is input attach + if (inp_idx^.itype=itVIndex) then //is input attach begin grp:=GroupingSharp(src,rtVSharp4); PV:=grp^.pData; - rsl:=AddVertLayout(grp,dtVec4f); - dsel:=dst_sel(PV^.dst_sel_x, - PV^.dst_sel_y, - PV^.dst_sel_z, - PV^.dst_sel_w); + info:=Buf_info(grp, + dst_sel(PV^.dst_sel_x, + PV^.dst_sel_y, + PV^.dst_sel_z, + PV^.dst_sel_w), + PV^.dfmt, + PV^.nfmt, + count); + + elem_res:=info.GetResultType; + elem_vec:=elem_res.AsVector(info.GetElemCount); + + rsl:=AddVertLayout(grp,elem_vec); elem_count:=GetElemCount(PV^.dfmt); For i:=0 to count-1 do begin - dst:=FRegsStory.get_vdst8(FSPI.MUBUF.VDATA+i); + dst:=get_vdst8(FSPI.MUBUF.VDATA+i); if (dst=nil) then Assert(false); //0=0, 1=1, 4=R, 5=G, 6=B, 7=A - Case dsel[i] of + Case info.dsel[i] of 0:begin //0 - _make_load_zero(dst); + make_load_zero(dst,elem_res); end; 1:begin //1 - _make_load_one(dst); + make_load_one(dst,elem_res); end; 4..7: begin //RGBA - d:=dsel[i]-4; + d:=info.dsel[i]-4; if (dnil); - node^.dst_type:=dtype; - node^.SetDstReg(dst); + node:=AddSpirvOp(pLine,OpId); //need first + node^.pType:=TypeList.Fetch(dst^.dtype); + node^.pDst:=dst; node^.AddParam(src); Result:=node; end; -procedure TEmitOp.emit_OpLoad(pLine:PspirvOp;dst:PsrRegNode;src:PsrVariable); -Var - p:TOpParamSingle; - dtype:PsrType; -begin - p.SetParam(ntVar,src); - dtype:=FSpirvTypes.Fetch(dst^.dtype); - //Assert(dtype<>nil); - emit_OpLoad(pLine,dtype,dst,p); -end; - -procedure TEmitOp.emit_OpStore(pLine:PspirvOp;dst:TOpParamSingle;src:PsrRegNode); +function TEmitOp._Op2(pLine:PspirvOp;OpId:DWORD;dst,src0,src1:PsrRegNode):PSpirvOp; Var node:PSpirvOp; begin - node:=AddSpirvOp(pLine,Op.OpStore); - node^.dst:=dst; - node^.AddParam(ntReg,src); + node:=AddSpirvOp(pLine,OpId); //need first + node^.pType:=TypeList.Fetch(dst^.dtype); + node^.pDst:=dst; + node^.AddParam(src0); + node^.AddParam(src1); + Result:=node; end; -procedure TEmitOp.emit_OpStore(pLine:PspirvOp;dst:PsrVariable;src:PsrRegNode); +function TEmitOp._Op3(pLine:PspirvOp;OpId:DWORD;dst,src0,src1,src2:PsrRegNode):PSpirvOp; Var - p:TOpParamSingle; + node:PSpirvOp; begin - if (dst^.dtype<>src^.dtype) then Assert(false); - - dst^.mark_write; - p.SetParam(ntVar,dst); - emit_OpStore(pLine,p,src); + node:=AddSpirvOp(pLine,OpId); //need first + node^.pType:=TypeList.Fetch(dst^.dtype); + node^.pDst:=dst; + node^.AddParam(src0); + node^.AddParam(src1); + node^.AddParam(src2); + Result:=node; end; -function TEmitOp.emit_OpCompExtract(pLine:PspirvOp;dst,src:PsrRegNode;id:DWORD):PSpirvOp; +function TEmitOp._Op4(pLine:PspirvOp;OpId:DWORD;dst,src0,src1,src2,src3:PsrRegNode):PSpirvOp; +Var + node:PSpirvOp; +begin + node:=AddSpirvOp(pLine,OpId); //need first + node^.pType:=TypeList.Fetch(dst^.dtype); + node^.pDst:=dst; + node^.AddParam(src0); + node^.AddParam(src1); + node^.AddParam(src2); + node^.AddParam(src3); + Result:=node; +end; + +// + +function TEmitOp._OpGlsl1(pLine:PspirvOp;OpId:DWORD;dst,src:PsrRegNode):PSpirvOp; +Var + node:PSpirvOp; +begin + node:=AddSGlslOp(pLine,OpId); //need first + node^.pType:=TypeList.Fetch(dst^.dtype); + node^.pDst:=dst; + node^.AddParam(src); + Result:=node; +end; + +function TEmitOp._OpGlsl2(pLine:PspirvOp;OpId:DWORD;dst,src0,src1:PsrRegNode):PSpirvOp; +Var + node:PSpirvOp; +begin + node:=AddSGlslOp(pLine,OpId); //need first + node^.pType:=TypeList.Fetch(dst^.dtype); + node^.pDst:=dst; + node^.AddParam(src0); + node^.AddParam(src1); + Result:=node; +end; + +function TEmitOp._OpGlsl3(pLine:PspirvOp;OpId:DWORD;dst,src0,src1,src2:PsrRegNode):PSpirvOp; +Var + node:PSpirvOp; +begin + node:=AddSGlslOp(pLine,OpId); //need first + node^.pType:=TypeList.Fetch(dst^.dtype); + node^.pDst:=dst; + node^.AddParam(src0); + node^.AddParam(src1); + node^.AddParam(src2); + Result:=node; +end; + +// + +function TEmitOp.Op1(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src:PsrRegNode):PSpirvOp; +begin + Result:=_Op1(line,OpId,dst^.New(line,rtype),src); +end; + +function TEmitOp.Op2(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1:PsrRegNode):PSpirvOp; +begin + Result:=_Op2(line,OpId,dst^.New(line,rtype),src0,src1); +end; + +function TEmitOp.Op3(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2:PsrRegNode):PSpirvOp; +begin + Result:=_Op3(line,OpId,dst^.New(line,rtype),src0,src1,src2); +end; + +function TEmitOp.Op4(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2,src3:PsrRegNode):PSpirvOp; +begin + Result:=_Op4(line,OpId,dst^.New(line,rtype),src0,src1,src2,src3); +end; + +function TEmitOp.OpGlsl1(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src:PsrRegNode):PSpirvOp; +begin + Result:=_OpGlsl1(line,OpId,dst^.New(line,rtype),src); +end; + +function TEmitOp.OpGlsl2(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1:PsrRegNode):PSpirvOp; +begin + Result:=_OpGlsl2(line,OpId,dst^.New(line,rtype),src0,src1) +end; + +function TEmitOp.OpGlsl3(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2:PsrRegNode):PSpirvOp; +begin + Result:=_OpGlsl3(line,OpId,dst^.New(line,rtype),src0,src1,src2); +end; + +function TEmitOp.OpBitcast(pLine:PspirvOp;dst,src:PsrRegNode):PSpirvOp; +begin + Result:=_Op1(pLine,Op.OpBitcast,dst,src); +end; + +function TEmitOp.OpBoolToInt(pLine:PspirvOp;dst,src:PsrRegNode):PSpirvOp; +Var + src0,src1:PsrRegNode; +begin + src0:=NewReg_q(dst^.dtype,0,@pLine); + src1:=NewReg_q(dst^.dtype,1,@pLine); + + Result:=_Op3(pLine,Op.OpSelect,dst,src,src1,src0); +end; + +function TEmitOp.OpIntToBool(pLine:PspirvOp;dst,src:PsrRegNode):PSpirvOp; +Var + src0:PsrRegNode; +begin + src0:=NewReg_q(src^.dtype,0,@pLine); + + Result:=_Op2(pLine,Op.OpINotEqual,dst,src,src0); +end; + +function TEmitOp.OpCast(nLine,dst,src:PsrNode):PsrNode; +var + rdst,rsrc,rtmp:PsrRegNode; + pLine:PspirvOp; +begin + pLine:=nLine^.AsType(ntOpCustom); + rdst := dst^.AsType(ntReg); + rsrc := src^.AsType(ntReg); + + Assert(pLine<>nil); + Assert(dst<>nil); + Assert(src<>nil); + + if (rsrc^.dtype=dtBool) then + begin + Case rdst^.dtype of + dtInt32, + dtUint32:Result:=OpBoolToInt(pLine,rdst,rsrc); + else + begin + rtmp:=NewReg(dtUint32); + OpBoolToInt(pLine,rtmp,rsrc); + Result:=OpBitcast(pLine,rdst,rtmp); + end; + end; + end else + if (rdst^.dtype=dtBool) then + begin + Case rsrc^.dtype of + dtInt32, + dtUint32:Result:=OpIntToBool(pLine,rdst,rsrc); + else + begin + rtmp:=NewReg(dtUint32); + OpBitcast(pLine,rtmp,rsrc); + Result:=OpIntToBool(pLine,rdst,rtmp); + end; + end; + end else + begin + Result:=OpBitcast(pLine,rdst,rsrc); + end; +end; + +function TEmitOp.OpLoad(nLine,dtype,dst,src:PsrNode):PsrNode; +var + pLine:PspirvOp; + pType:PsrType; + node:PSpirvOp; +begin + pLine:=nLine^.AsType(ntOpCustom); + pType:=dtype^.AsType(ntType); + Assert(dst<>nil); + Assert(src<>nil); + Assert(pLine<>nil); + //Assert(pType<>nil); + node:=AddSpirvOp(pLine,Op.OpLoad); + node^.pType:=pType; + node^.pDst :=dst; + node^.AddParam(src); + Result:=node; +end; + +function TEmitOp.OpStore(nLine,dst,src:PsrNode):PsrNode; +Var + pLine:PspirvOp; + node:PSpirvOp; +begin + pLine:=nLine^.AsType(ntOpCustom); + Assert(dst<>nil); + Assert(src<>nil); + Assert(pLine<>nil); + node:=AddSpirvOp(pLine,Op.OpStore); + node^.pDst:=dst; //write + node^.AddParam(src); + Result:=node; +end; + +function TEmitOp.OpLoad(pLine:PspirvOp;dst:PsrRegNode;src:PsrNode):PSpirvOp; +Var + dtype:PsrType; +begin + dtype:=TypeList.Fetch(dst^.dtype); + Result:=PSpirvOp(OpLoad(pLine,dtype,dst,src)); +end; + +function TEmitOp.OpExtract(pLine:PspirvOp;dst,src:PsrRegNode;id:DWORD):PSpirvOp; Var node:PSpirvOp; begin node:=AddSpirvOp(pLine,Op.OpCompositeExtract); - node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); - node^.SetDstReg(dst); - node^.AddParam(ntReg,src); + node^.pType:=TypeList.Fetch(dst^.dtype); + node^.pDst:=dst; + node^.AddParam(src); node^.AddLiteral(id); Result:=node; end; -function TEmitOp.emit_OpCompConstruct(pLine:PspirvOp;dst:PsrRegNode):PSpirvOp; +function TEmitOp.OpConstruct(pLine:PspirvOp;dst:PsrRegNode):PSpirvOp; var node:PSpirvOp; begin node:=AddSpirvOp(pLine,Op.OpCompositeConstruct); - node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); - Assert(node^.dst_type<>nil); - node^.SetDstReg(dst); + node^.pType:=TypeList.Fetch(dst^.dtype); + Assert(node^.pType<>nil); + node^.pDst:=dst; Result:=node; + //child add later end; -function TEmitOp.emit_OpAccessChain(pLine:PspirvOp;vType:PsrType;dst:PsrChain;src:PsrVariable):PSpirvOp; +function TEmitOp.OpAccessChain(pLine:PspirvOp;vType:PsrType;dst:PsrChain;src:PsrVariable):PSpirvOp; Var node:PSpirvOp; begin node:=AddSpirvOp(pLine,Op.OpAccessChain); - Assert(vType<>nil); - - node^.dst_type:=FSpirvTypes.FetchPointer(vType,src^.GetStorageClass); - node^.dst.SetParam(ntChain,dst); - - node^.AddParam(ntVar,src); //base - //index sets later - - dst^.pLine:=node; - + node^.pType:=TypeList.FetchPointer(vType,src^.GetStorageClass); + node^.pDst:=dst; + node^.AddParam(src); //base + //dst^.pLine:=node; Result:=node; + //index add later end; -function TEmitOp.emit_OpExtInst(pLine:PspirvOp;OpId:DWORD):PSpirvOp; -var - node:PSpirvOp; -begin - if (FGLSL_std_450=nil) then - begin - FGLSL_std_450:=FHeader.AddSpirvOp(Op.OpExtInstImport); - FGLSL_std_450^.dst.SetParam(ntRefId,NewRefId); - FGLSL_std_450^.AddString('GLSL.std.450'); - end; - - node:=AddSpirvOp(pLine,Op.OpExtInst); - node^.AddParam(ntRefId,FGLSL_std_450^.dst.AsRefId); - node^.AddLiteral(OpId,GlslOp.GetStr(OpId)); - Result:=node; -end; - -function TEmitOp.emit_OpCondMerge(pLine,pLabel:PspirvOp):PSpirvOp; +function TEmitOp.OpCondMerge(pLine,pLabel:PspirvOp):PSpirvOp; Var node:PSpirvOp; begin node:=AddSpirvOp(pLine,Op.OpSelectionMerge); - node^.AddParam(ntRefId,pLabel^.dst.AsRefId); + node^.AddParam(pLabel^.pDst); node^.AddLiteral(SelectionControl.None,'None'); Result:=node; end; -function TEmitOp.emit_OpLoopMerge(pLine,pLabel0,pLabel1:PspirvOp):PSpirvOp; +function TEmitOp.OpLoopMerge(pLine,pLabel0,pLabel1:PspirvOp):PSpirvOp; Var node:PSpirvOp; begin node:=AddSpirvOp(pLine,Op.OpLoopMerge); - node^.AddParam(ntRefId,pLabel0^.dst.AsRefId); - node^.AddParam(ntRefId,pLabel1^.dst.AsRefId); + node^.AddParam(pLabel0^.pDst); + node^.AddParam(pLabel1^.pDst); node^.AddLiteral(LoopControl.None,'None'); Result:=node; end; -function TEmitOp.emit_OpBranch(pLine,pLabel:PspirvOp):PSpirvOp; +function TEmitOp.OpBranch(pLine,pLabel:PspirvOp):PSpirvOp; Var node:PSpirvOp; begin node:=AddSpirvOp(pLine,Op.OpBranch); - node^.AddParam(ntRefId,pLabel^.dst.AsRefId); + node^.AddParam(pLabel^.pDst); Result:=node; end; -function TEmitOp.emit_OpBranchCond(pLine,pLabel0,pLabel1:PspirvOp;src:PsrRegNode):PSpirvOp; +function TEmitOp.OpBranchCond(pLine,pLabel0,pLabel1:PspirvOp;src:PsrRegNode):PSpirvOp; Var node:PSpirvOp; begin node:=AddSpirvOp(pLine,Op.OpBranchConditional); - node^.AddParam(ntReg,src); - node^.AddParam(ntRefId,pLabel0^.dst.AsRefId); - node^.AddParam(ntRefId,pLabel1^.dst.AsRefId); + node^.AddParam(src); + node^.AddParam(pLabel0^.pDst); + node^.AddParam(pLabel1^.pDst); Result:=node; end; -function TEmitOp.emit_OpReturnValue(pLine:PspirvOp;src:PsrRegNode):PSpirvOp; +function TEmitOp.OpReturnValue(pLine:PspirvOp;src:PsrRegNode):PSpirvOp; Var node:PSpirvOp; begin node:=AddSpirvOp(pLine,Op.OpReturnValue); - node^.AddParam(ntReg,src); - Result:=node; -end; - -function TEmitOp.emit_Op1(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src:PsrRegNode):PSpirvOp; -Var - node:PSpirvOp; -begin - node:=AddSpirvOp(OpId); //need first - - dst^.New(line,rtype); - - node^.dst_type:=FSpirvTypes.Fetch(rtype); - node^.SetDstReg(dst^.current); - - node^.AddParam(ntReg,src); - Result:=node; -end; - -function TEmitOp.emit_Op2(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1:PsrRegNode):PSpirvOp; -Var - node:PSpirvOp; -begin - node:=AddSpirvOp(OpId); //need first - - dst^.New(line,rtype); - - node^.dst_type:=FSpirvTypes.Fetch(rtype); - node^.SetDstReg(dst^.current); - - node^.AddParam(ntReg,src0); - node^.AddParam(ntReg,src1); - Result:=node; -end; - -function TEmitOp.emit_Op3(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2:PsrRegNode):PSpirvOp; -Var - node:PSpirvOp; -begin - node:=AddSpirvOp(OpId); //need first - - dst^.New(line,rtype); - - node^.dst_type:=FSpirvTypes.Fetch(rtype); - node^.SetDstReg(dst^.current); - - node^.AddParam(ntReg,src0); - node^.AddParam(ntReg,src1); - node^.AddParam(ntReg,src2); - Result:=node; -end; - -function TEmitOp.emit_OpExt1(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src:PsrRegNode):PSpirvOp; -Var - node:PSpirvOp; -begin - node:=emit_OpExtInst(line,OpId); //need first - - dst^.New(line,rtype); - - node^.dst_type:=FSpirvTypes.Fetch(rtype); - node^.SetDstReg(dst^.current); - - node^.AddParam(ntReg,src); - Result:=node; -end; - -function TEmitOp.emit_OpExt2(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1:PsrRegNode):PSpirvOp; -Var - node:PSpirvOp; -begin - node:=emit_OpExtInst(line,OpId); //need first - - dst^.New(line,rtype); - - node^.dst_type:=FSpirvTypes.Fetch(rtype); - node^.SetDstReg(dst^.current); - - node^.AddParam(ntReg,src0); - node^.AddParam(ntReg,src1); - Result:=node; -end; - -function TEmitOp.emit_OpExt3(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2:PsrRegNode):PSpirvOp; -Var - node:PSpirvOp; -begin - node:=emit_OpExtInst(line,OpId); //need first - - dst^.New(line,rtype); - - node^.dst_type:=FSpirvTypes.Fetch(rtype); - node^.SetDstReg(dst^.current); - - node^.AddParam(ntReg,src0); - node^.AddParam(ntReg,src1); - node^.AddParam(ntReg,src2); - Result:=node; -end; - -procedure TEmitOp._emit_ConvFloatToHalf(dst:PsrRegSlot;src0,src1:PsrRegNode); -var - rsl:array[0..1] of PsrRegNode; -begin - //vdst[15:00].hf = ConvertFloatToHalfFloat(vsrc0.f); - //vdst[31:16].hf = ConvertFloatToHalfFloat(vsrc1.f); - - rsl[0]:=NewReg(dtHalf16); - rsl[1]:=NewReg(dtHalf16); - - _emit_Op1(line,Op.OpFConvert,rsl[0],src0); - _emit_Op1(line,Op.OpFConvert,rsl[1],src1); - - rsl[0]^.mark_read; - rsl[1]^.mark_read; - - dst^.New(line,dtVec2h); - - emit_OpMakeConstruct(line,dst^.current,2,@rsl); -end; - -function TEmitOp._emit_Op1(pLine:PspirvOp;OpId:DWORD;dst,src:PsrRegNode):PSpirvOp; -Var - node:PSpirvOp; -begin - node:=AddSpirvOp(pLine,OpId); //need first - node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); - node^.SetDstReg(dst); - node^.AddParam(ntReg,src); - Result:=node; -end; - -function TEmitOp._emit_Op2(pLine:PspirvOp;OpId:DWORD;dst,src0,src1:PsrRegNode):PSpirvOp; -Var - node:PSpirvOp; -begin - node:=AddSpirvOp(pLine,OpId); //need first - node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); - node^.SetDstReg(dst); - node^.AddParam(ntReg,src0); - node^.AddParam(ntReg,src1); + node^.AddParam(src); Result:=node; end; // -function TEmitOp._emit_OpExt1(pLine:PspirvOp;OpId:DWORD;dst,src:PsrRegNode):PSpirvOp; -Var - node:PSpirvOp; -begin - node:=emit_OpExtInst(pLine,OpId); //need first - node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); - node^.SetDstReg(dst); - node^.AddParam(ntReg,src); - Result:=node; -end; - -function TEmitOp._emit_OpExt2(pLine:PspirvOp;OpId:DWORD;dst,src0,src1:PsrRegNode):PSpirvOp; -Var - node:PSpirvOp; -begin - node:=emit_OpExtInst(pLine,OpId); //need first - node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); - node^.SetDstReg(dst); - node^.AddParam(ntReg,src0); - node^.AddParam(ntReg,src1); - Result:=node; -end; - -// - -function TEmitOp._emit_OpIsNan(pLine:PspirvOp;dst,src:PsrRegNode):PSpirvOp; -begin - Result:=_emit_Op1(pLine,Op.OpIsNan,dst,src); -end; - -function TEmitOp._emit_OpFAbs(pLine:PspirvOp;dst,src:PsrRegNode):PSpirvOp; -begin - Result:=_emit_OpExt1(pLine,GlslOp.FAbs,dst,src); -end; - -function TEmitOp._emit_OpSAbs(pLine:PspirvOp;dst,src:PsrRegNode):PSpirvOp; -begin - Result:=_emit_OpExt1(pLine,GlslOp.SAbs,dst,src); -end; - -function TEmitOp._emit_OpUMin(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; -begin - Result:=_emit_OpExt2(pLine,GlslOp.UMin,dst,src0,src1); -end; - -function TEmitOp._emit_OpUMax(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; -begin - Result:=_emit_OpExt2(pLine,GlslOp.UMax,dst,src0,src1); -end; - -function TEmitOp._emit_OpFMin(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; -begin - Result:=_emit_OpExt2(pLine,GlslOp.FMin,dst,src0,src1); -end; - -function TEmitOp._emit_OpFMax(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; -begin - Result:=_emit_OpExt2(pLine,GlslOp.FMax,dst,src0,src1); -end; - -function TEmitOp._emit_OpNMin(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; -begin - Result:=_emit_OpExt2(pLine,GlslOp.NMin,dst,src0,src1); -end; - -function TEmitOp._emit_OpNMax(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; -begin - Result:=_emit_OpExt2(pLine,GlslOp.NMax,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpFloor(dst:PsrRegSlot;src:PsrRegNode); -begin - emit_OpExt1(GlslOp.Floor,dtFloat32,dst,src); -end; - -procedure TEmitOp.emit_OpFract(dst:PsrRegSlot;src:PsrRegNode); -begin - emit_OpExt1(GlslOp.Fract,dtFloat32,dst,src); -end; - -procedure TEmitOp.emit_OpSqrt(dst:PsrRegSlot;src:PsrRegNode); -begin - emit_OpExt1(GlslOp.Sqrt,dtFloat32,dst,src); -end; - -procedure TEmitOp.emit_OpInverseSqrt(dst:PsrRegSlot;src:PsrRegNode); -begin - emit_OpExt1(GlslOp.InverseSqrt,dtFloat32,dst,src); -end; - -procedure TEmitOp.emit_OpLog2(dst:PsrRegSlot;src:PsrRegNode); -begin - emit_OpExt1(GlslOp.Log2,dtFloat32,dst,src); -end; - -procedure TEmitOp.emit_OpExp2(dst:PsrRegSlot;src:PsrRegNode); -begin - emit_OpExt1(GlslOp.Exp2,dtFloat32,dst,src); -end; - -procedure TEmitOp.emit_OpSin(dst:PsrRegSlot;src:PsrRegNode); -begin - emit_OpExt1(GlslOp.Sin,dtFloat32,dst,src); -end; - -procedure TEmitOp.emit_OpFMin(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_OpExt2(GlslOp.FMin,dtFloat32,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpFMax(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_OpExt2(GlslOp.FMax,dtFloat32,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpFClamp(dst:PsrRegSlot;src,min,max:PsrRegNode); -begin - emit_OpExt3(GlslOp.FClamp,dtFloat32,dst,src,min,max); -end; - -procedure TEmitOp.emit_OpFmaF32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode); +procedure TEmitOp.OpFmaF32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode); begin //vdst = vsrc0.f * vsrc1.f + vdst.f -> fma //NoContraction decoration - emit_OpExt3(GlslOp.Fma,dtFloat32,dst,src0,src1,src2); + OpGlsl3(GlslOp.Fma,dtFloat32,dst,src0,src1,src2); end; -procedure TEmitOp.emit_OpFmaI32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode); +procedure TEmitOp.OpFmaI32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode); var mul,sum:PsrRegNode; begin @@ -634,13 +510,11 @@ begin mul:=NewReg(dtInt32); sum:=dst^.New(line,dtInt32); - _emit_OpIMul(line,mul,src0,src1); - - mul^.mark_read; - _emit_OpIAdd(line,sum,mul,src2); + _Op2(line,Op.OpIMul,mul,src0,src1); + _Op2(line,Op.OpIAdd,sum,mul,src2); end; -procedure TEmitOp.emit_OpFmaU32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode); +procedure TEmitOp.OpFmaU32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode); var mul,sum:PsrRegNode; begin @@ -648,604 +522,765 @@ begin mul:=NewReg(dtUInt32); sum:=dst^.New(line,dtUInt32); - _emit_OpIMul(line,mul,src0,src1); - - mul^.mark_read; - _emit_OpIAdd(line,sum,mul,src2); + _Op2(line,Op.OpIMul,mul,src0,src1); + _Op2(line,Op.OpIAdd,sum,mul,src2); end; // -procedure TEmitOp.emit_OpCmpV(OpId:DWORD;dst:PsrRegSlot;src0,src1:PsrRegNode); //sdst[thread_id:] = (vsrc1.u vsrc2.u) & EXEC -Var - tmp:PsrRegNode; - exc:PsrRegNode; +procedure TEmitOp.OpSelect(dst:PsrRegSlot;src0,src1,cond:PsrRegNode); begin - emit_Op2(OpId,dtBool,@FRegsStory.FUnattach,src0,src1); - - tmp:=FRegsStory.FUnattach.current; - tmp^.mark_read; - - exc:=MakeRead(@FRegsStory.EXEC[0],dtBool); - emit_OpLogicalAnd(dst,tmp,exc); + Op3(Op.OpSelect,LazyType2(src0^.dtype,src1^.dtype),dst,cond,src1,src0); end; -procedure TEmitOp.emit_OpCmpS(OpId:DWORD;dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(OpId,dtBool,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpSelect(dst:PsrRegSlot;src0,src1,cond:PsrRegNode); -begin - emit_Op3(Op.OpSelect,LazyType2(src0^.dtype,src1^.dtype),dst,cond,src1,src0); -end; - -function TEmitOp._emit_OpFNegate(pLine:PspirvOp;dst,src:PsrRegNode):PSpirvOp; -begin - Result:=_emit_Op1(pLine,Op.OpFNegate,dst,src); -end; - -procedure TEmitOp._emit_OpIAddC(pLine:PspirvOp;dst,car,src0,src1:PsrRegNode); +procedure TEmitOp.OpIAddCar(pLine:PspirvOp;dst,car,src0,src1:PsrRegNode); Var node:PSpirvOp; rsl:PsrRegNode; begin node:=AddSpirvOp(pLine,Op.OpIAddCarry); //need first + node^.AddParam(src0); + node^.AddParam(src1); rsl:=NewReg(dtStruct2u); - node^.dst_type:=FSpirvTypes.Fetch(dtStruct2u); - node^.SetDstReg(rsl); + node^.pType:=TypeList.Fetch(dtStruct2u); + node^.pDst:=rsl; - node^.AddParam(ntReg,src0); - node^.AddParam(ntReg,src1); - - rsl^.mark_read; - rsl^.mark_read; + dst:=BitcastList.FetchDstr(TsrDataType(dtStruct2u).Child,dst); + car:=BitcastList.FetchDstr(TsrDataType(dtStruct2u).Child,car); pLine:=node; - pLine:=emit_OpCompExtract(pLine,dst,rsl,0); - pLine:=emit_OpCompExtract(pLine,car,rsl,1); + pLine:=OpExtract(pLine,dst,rsl,0); + pLine:=OpExtract(pLine,car,rsl,1); end; -function TEmitOp._emit_OpIAdd(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; -begin - {if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then - begin - dst^.dtype:=dtInt32; - end else - begin - dst^.dtype:=dtUInt32; - end;} - Result:=_emit_Op2(pLine,Op.OpIAdd,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpIAddExt(dst,car:PsrRegSlot;src0,src1:PsrRegNode); +procedure TEmitOp.OpIAddExt(dst,car:PsrRegSlot;src0,src1:PsrRegNode); Var node:PSpirvOp; + rsl:PsrRegPair; begin - node:=AddSpirvOp(OpIAddExt); //need first + node:=AddSpirvOp(srOpUtils.OpIAddExt); //need first + node^.AddParam(src0); + node^.AddParam(src1); - dst^.New(line,dtUint32); //alloc - car^.New(line,dtUint32); //alloc + rsl:=NewRegPair; + rsl^.pWriter:=node; + node^.pDst:=rsl; - car^.current^.mark_read; //mark dep - node^.SetDstReg(car^.current); //set with dep - node^.SetDstReg(dst^.current); //set dst - - node^.AddParam(ntReg,car^.current); - node^.AddParam(ntReg,src0); - node^.AddParam(ntReg,src1); + rsl^.pDst0:=dst^.New(line,dtUint32); + rsl^.pDst1:=car^.New(line,dtUint32); end; -procedure TEmitOp.emit_OpISubExt(dst,bor:PsrRegSlot;src0,src1:PsrRegNode); -Var - node:PSpirvOp; -begin - node:=AddSpirvOp(OpISubExt); //need first - - dst^.New(line,dtUint32); //alloc - bor^.New(line,dtUint32); //alloc - - bor^.current^.mark_read; //mark dep - node^.SetDstReg(bor^.current); //set with dep - node^.SetDstReg(dst^.current); //set dst - - node^.AddParam(ntReg,bor^.current); - node^.AddParam(ntReg,src0); - node^.AddParam(ntReg,src1); -end; - -procedure TEmitOp._emit_OpISubB(pLine:PspirvOp;dst,bor,src0,src1:PsrRegNode); +procedure TEmitOp.OpISubBor(pLine:PspirvOp;dst,bor,src0,src1:PsrRegNode); Var node:PSpirvOp; rsl:PsrRegNode; begin node:=AddSpirvOp(pLine,Op.OpISubBorrow); //need first + node^.AddParam(src0); + node^.AddParam(src1); rsl:=NewReg(dtStruct2u); - node^.dst_type:=FSpirvTypes.Fetch(dtStruct2u); - node^.SetDstReg(rsl); + node^.pType:=TypeList.Fetch(dtStruct2u); + node^.pDst:=rsl; - node^.AddParam(ntReg,src0); - node^.AddParam(ntReg,src1); - - rsl^.mark_read; - rsl^.mark_read; + dst:=BitcastList.FetchDstr(TsrDataType(dtStruct2u).Child,dst); + bor:=BitcastList.FetchDstr(TsrDataType(dtStruct2u).Child,bor); pLine:=node; - pLine:=emit_OpCompExtract(pLine,dst,rsl,0); - pLine:=emit_OpCompExtract(pLine,bor,rsl,1); + pLine:=OpExtract(pLine,dst,rsl,0); + pLine:=OpExtract(pLine,bor,rsl,1); end; -function TEmitOp._emit_OpISub(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +procedure TEmitOp.OpISubExt(dst,bor:PsrRegSlot;src0,src1:PsrRegNode); +Var + node:PSpirvOp; + rsl:PsrRegPair; begin - {if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then - begin - dst^.dtype:=dtInt32; - end else - begin - dst^.dtype:=dtUInt32; - end;} - Result:=_emit_Op2(pLine,Op.OpISub,dst,src0,src1); + node:=AddSpirvOp(srOpUtils.OpISubExt); //need first + node^.AddParam(src0); + node^.AddParam(src1); + + rsl:=NewRegPair; + rsl^.pWriter:=node; + node^.pDst:=rsl; + + rsl^.pDst0:=dst^.New(line,dtUint32); + rsl^.pDst1:=bor^.New(line,dtUint32); end; -function TEmitOp._emit_OpAbsDiff(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +// + +function TEmitOp.OpAbsDiff(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; begin - Result:=_emit_Op2(pLine,OpAbsDiff,dst,src0,src1); + Result:=_Op2(pLine,srOpUtils.OpAbsDiff,dst,src0,src1); end; -function TEmitOp._emit_OpIMul(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +procedure TEmitOp.OpWQM32(dst:PsrRegSlot;src:PsrRegNode); begin - {if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then - begin - dst^.dtype:=dtInt32; - end else - begin - dst^.dtype:=dtUInt32; - end;} - Result:=_emit_Op2(pLine,Op.OpIMul,dst,src0,src1); + Op1(srOpUtils.OpWQM32,dtUnknow,dst,src); end; -function TEmitOp._emit_OpUDiv(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +procedure TEmitOp.OpBFEU32(dst:PsrRegSlot;base,src0,src1:PsrRegNode); begin - Result:=_emit_Op2(pLine,Op.OpUDiv,dst,src0,src1); + Op3(srOpUtils.OpBFEU32,dtUint32,dst,base,src0,src1); end; -function TEmitOp._emit_OpSDiv(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +procedure TEmitOp.OpBFIB32(dst:PsrRegSlot;bitmsk,src0,src1:PsrRegNode); begin - Result:=_emit_Op2(pLine,Op.OpSDiv,dst,src0,src1); + Op3(srOpUtils.OpBFIB32,dtUint32,dst,bitmsk,src0,src1); end; -function TEmitOp._emit_OpShr(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +function TEmitOp.OpBFITo(src0,src1,src2,src3:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; begin - Result:=_emit_Op2(pLine,Op.OpShiftRightLogical,dst,src0,src1); + Result:=NewReg(src0^.dtype); + _set_line(ppLine,_Op4(_get_line(ppLine),Op.OpBitFieldInsert,Result,src0,src1,src2,src3)); end; -function TEmitOp._emit_OpShrA(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +// + +procedure TEmitOp.OpPackAnc(dst:PsrRegSlot;prim,smid,rtid:PsrRegNode); begin - Result:=_emit_Op2(pLine,Op.OpShiftRightArithmetic,dst,src0,src1); + Op3(srOpUtils.OpPackAnc,dtUint32,dst,prim,smid,rtid); end; -function TEmitOp._emit_OpShl(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +// + +function TEmitOp.OpUMinTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; begin - Result:=_emit_Op2(pLine,Op.OpShiftLeftLogical,dst,src0,src1); + Result:=NewReg(src0^.dtype); + _set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.UMin,Result,src0,src1)); end; -procedure TEmitOp.emit_WQM_32(dst:PsrRegSlot;src:PsrRegNode); +function TEmitOp.OpUMaxTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; begin - emit_Op1(OpWQM32,dtUnknow,dst,src); + Result:=NewReg(src0^.dtype); + _set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.UMax,Result,src0,src1)); end; -procedure TEmitOp.emit_MED3F(dst:PsrRegSlot;src0,src1,src2:PsrRegNode); +function TEmitOp.OpFMinTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + Result:=NewReg(src0^.dtype); + _set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.FMin,Result,src0,src1)); +end; + +function TEmitOp.OpFMaxTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + Result:=NewReg(src0^.dtype); + _set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.FMax,Result,src0,src1)); +end; + +function TEmitOp.OpNMinTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + Result:=NewReg(src0^.dtype); + _set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.NMin,Result,src0,src1)); +end; + +function TEmitOp.OpNMaxTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + Result:=NewReg(src0^.dtype); + _set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.NMax,Result,src0,src1)); +end; + +procedure TEmitOp.OpMED3F(dst:PsrRegSlot;src0,src1,src2:PsrRegNode); var min:PsrRegNode; max:PsrRegNode; - tmp:PsrRegNode; - ret:PsrRegNode; + mmx:PsrRegNode; begin - //emit_Op3(OpMED3F,dtFloat32,dst,src0,src1,src2); + min:=OpFMinTo(src0,src1); //min(s0,s1) + max:=OpNMaxTo(src0,src1); //max(s0,s1) + mmx:=OpFMinTo(max ,src2); //min(max(s0,s1),s2) - min:=NewReg(dtFloat32); - src0^.mark_read; - src1^.mark_read; - _emit_OpFMin(line,min,src0,src1); //min(s0,s1) - - max:=NewReg(dtFloat32); - src0^.mark_read; - src1^.mark_read; - _emit_OpNMax(line,max,src0,src1); //max(s0,s1) - - tmp:=NewReg(dtFloat32); - max^.mark_read; - src2^.mark_read; - _emit_OpFMin(line,tmp,max,src2); //min(max(s0,s1),s2) - - ret:=dst^.New(line,dtFloat32); - min^.mark_read; - tmp^.mark_read; - _emit_OpNMax(line,ret,min,tmp); //max(min(s0,s1),min(max(s0,s1),s2)) + OpGlsl2(GlslOp.NMax,src0^.dtype,dst,min,mmx); //max(min(s0,s1),min(max(s0,s1),s2)) end; -function TEmitOp.emit_OpMakeConstruct(pLine:PspirvOp;dst:PsrRegNode;count:Byte;src:PPsrRegNode):PSpirvOp; -Var - p:PsrCacheOp; - node:PSpirvOp; - i:Byte; -begin - Result:=pLine; - Assert((count>0) and (count<=4)); - - pLine:=GetMaxPlace(pLine,count,src); - - p:=FCacheOps.Fetch(pLine^.pParent,Op.OpCompositeConstruct,dst^.dtype,count,src); - if (p^.pReg=nil) then - begin - node:=emit_OpCompConstruct(pLine,dst); - For i:=0 to count-1 do - begin - node^.AddParam(ntReg,src[i]); - end; - p^.pReg:=dst; //save - Result:=node; - end else - begin - p^.pReg^.mark_read; - dst^.SetReg(p^.pReg); - //deref - For i:=0 to count-1 do - begin - src[i]^.mark_unread; - end; - end; -end; - -function TEmitOp.emit_OpMakeVec(pLine:PspirvOp;rtype:TsrDataType;count:Byte;src:PPsrRegNode):PsrRegNode; -Var - p:PsrCacheOp; - node:PSpirvOp; - i:Byte; -begin - Assert((count>0) and (count<=4)); - - pLine:=GetMaxPlace(pLine,count,src); - - p:=FCacheOps.Fetch(pLine^.pParent,OpMakeVec,rtype,count,src); - Result:=p^.pReg; - if (Result=nil) then - begin - node:=AddSpirvOp(pLine,OpMakeVec); //need first - - Result:=NewReg(rtype); - - node^.SetDstReg(Result); - node^.AddLiteral(ord(rtype)); - node^.AddLiteral(count); - - For i:=0 to count-1 do - begin - node^.AddParam(ntReg,src[i]); - end; - - p^.pReg:=Result; //save - end else - begin - //deref - For i:=0 to count-1 do - begin - src[i]^.mark_unread; - end; - end; -end; - - -//x,y,face,slice -function TEmitOp.emit_OpMakeCube(pLine:PspirvOp;rtype:TsrDataType;count:Byte;src:PPsrRegNode):PsrRegNode; -Var - p:PsrCacheOp; - node:PSpirvOp; - i:Byte; -begin - - Assert((count=3) or (count=4)); - - pLine:=GetMaxPlace(pLine,count,src); - - p:=FCacheOps.Fetch(pLine^.pParent,OpMakeCM,rtype,count,src); - Result:=p^.pReg; - if (Result=nil) then - begin - node:=AddSpirvOp(pLine,OpMakeCM); //need first - - Result:=NewReg(rtype); - - node^.SetDstReg(Result); - node^.AddLiteral(ord(rtype)); - node^.AddLiteral(count); - - For i:=0 to count-1 do - begin - node^.AddParam(ntReg,src[i]); - end; - - p^.pReg:=Result; //save - end else - begin - //deref - For i:=0 to count-1 do - begin - src[i]^.mark_unread; - end; - end; -end; - -function TEmitOp.emit_OpPackOfs(pLine:PspirvOp;rtype:TsrDataType;count:Byte;src:PsrRegNode):PsrRegNode; +function TEmitOp.OpPackOfs(pLine:PspirvOp;rtype:TsrDataType;count:Byte;src:PsrRegNode):PsrRegNode; Var p:PsrCacheOp; + dst:PsrRegNode; node:PSpirvOp; begin - Assert((count>0) and (count<=3)); + Assert(count<>0); + Assert(src<>nil); pLine:=GetMaxPlace(pLine,1,@src); - p:=FCacheOps.Fetch(pLine^.pParent,OpPackOfs,rtype,1,@src); - Result:=p^.pReg; - if (Result=nil) then + p:=CacheOpList.Fetch(pLine^.Parent,srOpUtils.OpPackOfs,rtype,1,@src); + + if (p^.pDst=nil) then begin - node:=AddSpirvOp(pLine,OpPackOfs); //need first + node:=AddSpirvOp(pLine,srOpUtils.OpPackOfs); //need first - Result:=NewReg(rtype); + dst:=NewReg(rtype); - node^.SetDstReg(Result); - node^.AddLiteral(ord(rtype)); + node^.pDst:=dst; node^.AddLiteral(count); - node^.AddParam(ntReg,src); + node^.AddParam(src); - p^.pReg:=Result; //save + p^.pDst:=dst; //save + Result:=dst; end else begin - //deref - src^.mark_unread; + Result:=PsrRegNode(p^.pDst); end; end; -function TEmitOp.emit_OpSampledImage(pLine:PspirvOp;Tgrp,Sgrp:PsrRegNode;dtype:TsrDataType;info:TsrTypeImageInfo):PsrRegNode; +function TEmitOp.OpMakeCon(pLine:PspirvOp;dst:PsrRegNode;src:PPsrRegNode):PSpirvOp; Var - src:array[0..1] of PsrRegNode; + p:PsrCacheOp; + node:PSpirvOp; + rtype:TsrDataType; + i:Byte; +begin + Result:=pLine; + Assert(src<>nil); + + rtype:=dst^.dtype; + + pLine:=GetMaxPlace(pLine,rtype.Count,src); + + p:=CacheOpList.Fetch(pLine^.Parent,Op.OpCompositeConstruct,rtype,rtype.Count,src); + + if (p^.pDst=nil) then + begin + node:=OpConstruct(pLine,dst); + For i:=0 to rtype.Count-1 do + begin + node^.AddParam(src[i]); + end; + p^.pDst:=dst; //save + Result:=node; + end else + begin + dst^.pWriter:=p^.pDst; + end; +end; + +function TEmitOp.OpMakeVec(pLine:PspirvOp;rtype:TsrDataType;src:PPsrRegNode):PsrRegNode; +Var + p:PsrCacheOp; + dst:PsrRegNode; + node:PSpirvOp; + i:Byte; +begin + Assert(src<>nil); + + pLine:=GetMaxPlace(pLine,rtype.Count,src); + + p:=CacheOpList.Fetch(pLine^.Parent,srOpUtils.OpMakeVec,rtype,rtype.Count,src); + + if (p^.pDst=nil) then + begin + node:=AddSpirvOp(pLine,srOpUtils.OpMakeVec); //need first + + dst:=NewReg(rtype); + + node^.pDst:=dst; + + For i:=0 to rtype.Count-1 do + begin + node^.AddParam(src[i]); + end; + + p^.pDst:=dst; //save + Result:=dst; + end else + begin + Result:=PsrRegNode(p^.pDst); + end; +end; + +//x,y,face,slice +function TEmitOp.OpMakeCub(pLine:PspirvOp;rtype:TsrDataType;src:PPsrRegNode):PsrRegNode; +Var + p:PsrCacheOp; + dst:PsrRegNode; + node:PSpirvOp; + i:Byte; +begin + Assert(src<>nil); + + pLine:=GetMaxPlace(pLine,rtype.Count,src); + + p:=CacheOpList.Fetch(pLine^.Parent,srOpUtils.OpMakeCub,rtype,rtype.Count,src); + + if (p^.pDst=nil) then + begin + node:=AddSpirvOp(pLine,srOpUtils.OpMakeCub); //need first + + dst:=NewReg(rtype); + + node^.pDst:=dst; + + For i:=0 to rtype.Count-1 do + begin + node^.AddParam(src[i]); + end; + + p^.pDst:=dst; //save + Result:=dst; + end else + begin + Result:=PsrRegNode(p^.pDst); + end; +end; + +function TEmitOp.OpSampledImage(pLine:PspirvOp;Tgrp,Sgrp:PsrNode;dtype:TsrDataType;info:TsrTypeImageInfo):PsrRegNode; +Var + src:array[0..1] of PsrNode; pType:PsrType; p:PsrCacheOp; + dst:PsrRegNode; node:PSpirvOp; begin src[0]:=Tgrp; src[1]:=Sgrp; - p:=FCacheOps.Fetch(pLine^.pParent,Op.OpSampledImage,dtTypeSampledImage,2,@src); - Result:=p^.pReg; - if (Result=nil) then + p:=CacheOpList.Fetch(pLine^.Parent,Op.OpSampledImage,dtTypeSampledImage,2,@src); + + if (p^.pDst=nil) then begin - Tgrp^.mark_read; - Sgrp^.mark_read; + node:=AddSpirvOp(pLine,Op.OpSampledImage); //need first - Result:=NewReg(dtTypeSampledImage); + dst:=NewReg(dtTypeSampledImage); - node:=AddSpirvOp(pLine,Op.OpSampledImage); + pType:=TypeList.Fetch(dtype); + pType:=TypeList.FetchImage(pType,info); + pType:=TypeList.FetchSampledImage(pType); - pType:=FSpirvTypes.FetchImage(FSpirvTypes.Fetch(dtype),info); - node^.dst_type:=FSpirvTypes.FetchSampledImage(pType); - node^.SetDstReg(Result); + node^.pType:=pType; + node^.pDst:=dst; - node^.AddParam(ntReg,Tgrp); - node^.AddParam(ntReg,Sgrp); + node^.AddParam(Tgrp); + node^.AddParam(Sgrp); - p^.pReg:=Result; //save + p^.pDst:=dst; //save + Result:=dst; + end else + begin + Result:=PsrRegNode(p^.pDst); end; end; // -procedure TEmitOp.emit_OpFAdd(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(Op.OpFAdd,dtFloat32,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpFSub(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(Op.OpFSub,dtFloat32,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpIAdd(dst:PsrRegSlot;src0,src1:PsrRegNode); +procedure TEmitOp.OpIAdd(dst:PsrRegSlot;src0,src1:PsrRegNode); begin if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then begin - emit_Op2(Op.OpIAdd,dtInt32,dst,src0,src1); + Op2(Op.OpIAdd,dtInt32,dst,src0,src1); end else begin - emit_Op2(Op.OpIAdd,dtUInt32,dst,src0,src1); + Op2(Op.OpIAdd,dtUInt32,dst,src0,src1); end; end; -procedure TEmitOp.emit_OpISub(dst:PsrRegSlot;src0,src1:PsrRegNode); +procedure TEmitOp.OpISub(dst:PsrRegSlot;src0,src1:PsrRegNode); begin if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then begin - emit_Op2(Op.OpISub,dtInt32,dst,src0,src1); + Op2(Op.OpISub,dtInt32,dst,src0,src1); end else begin - emit_Op2(Op.OpISub,dtUInt32,dst,src0,src1); + Op2(Op.OpISub,dtUInt32,dst,src0,src1); end; end; -procedure TEmitOp.emit_OpIMul(dst:PsrRegSlot;src0,src1:PsrRegNode); +procedure TEmitOp.OpIMul(dst:PsrRegSlot;src0,src1:PsrRegNode); begin if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then begin - emit_Op2(Op.OpIMul,dtInt32,dst,src0,src1); + Op2(Op.OpIMul,dtInt32,dst,src0,src1); end else begin - emit_Op2(Op.OpIMul,dtUInt32,dst,src0,src1); + Op2(Op.OpIMul,dtUInt32,dst,src0,src1); end; end; -procedure TEmitOp.emit_OpFMul(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(Op.OpFMul,dtFloat32,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpUDiv(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(Op.OpUDiv,dtUint32,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpFDiv(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(Op.OpFDiv,dtFloat32,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpBfeU(dst:PsrRegSlot;base,offset,count:PsrRegNode); -begin - emit_Op3(Op.OpBitFieldUExtract,dtUInt32,dst,base,offset,count); -end; - -procedure TEmitOp.emit_OpShl(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(Op.OpShiftLeftLogical,dtUint32,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpShr(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(Op.OpShiftRightLogical,dtUint32,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpShrA(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(Op.OpShiftRightArithmetic,dtInt32,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpNot(dst:PsrRegSlot;src:PsrRegNode); -begin - emit_Op1(Op.OpNot,dtUnknow{dtUint32},dst,src); -end; - -procedure TEmitOp.emit_OpLogicalNot(dst:PsrRegSlot;src:PsrRegNode); -begin - emit_Op1(Op.OpLogicalNot,dtBool,dst,src); -end; - -procedure TEmitOp.emit_OpBitwiseOr(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(Op.OpBitwiseOr,dtUnknow{dtUint32},dst,src0,src1); -end; - -procedure TEmitOp.emit_OpBitwiseXor(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(Op.OpBitwiseXor,{dtUnknow}dtUint32,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpLogicalOr(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(Op.OpLogicalOr,dtBool,dst,src0,src1); -end; - -procedure TEmitOp.emit_OpBitwiseAnd(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(Op.OpBitwiseAnd,dtUnknow{dtUint32},dst,src0,src1); -end; - -procedure TEmitOp.emit_OpLogicalAnd(dst:PsrRegSlot;src0,src1:PsrRegNode); -begin - emit_Op2(Op.OpLogicalAnd,dtBool,dst,src0,src1); -end; - // -function TEmitOp.emit_OpImageSampleImplicitLod(pLine:PspirvOp;dst,cmb,coord:PsrRegNode):PSpirvOp; +function TEmitOp.OpShlTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src1=nil) then Exit(src0); + + Result:=NewReg(src0^.dtype); + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpShiftLeftLogical,Result,src0,src1)); +end; + +function TEmitOp.OpShlTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) or (src1=0) then Exit(src0); + Result:=OpShlTo(src0,NewReg_q(src0^.dtype,src1,ppLine),ppLine); +end; + +function TEmitOp.OpShrTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src1=nil) then Exit(src0); + + Result:=NewReg(src0^.dtype); + if (src0^.dtype.Sign<>0) then + begin + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpShiftRightArithmetic,Result,src0,src1)); + end else + begin + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpShiftRightLogical ,Result,src0,src1)); + end; +end; + +function TEmitOp.OpShrTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) or (src1=0) then Exit(src0); + Result:=OpShrTo(src0,NewReg_q(src0^.dtype,src1,ppLine),ppLine); +end; + +// + +function TEmitOp.OpIAddTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) then Exit(src1); + if (src1=nil) then Exit(src0); + + if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then + begin + Result:=NewReg(dtInt32); + end else + begin + Result:=NewReg(dtUInt32); + end; + + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpIAdd,Result,src0,src1)); +end; + +function TEmitOp.OpIAddTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) or (src1=0) then Exit(src0); + Result:=OpIAddTo(src0,NewReg_q(src0^.dtype,src1,ppLine),ppLine); +end; + +function TEmitOp.OpISubTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) then Exit(src1); + if (src1=nil) then Exit(src0); + + if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then + begin + Result:=NewReg(dtInt32); + end else + begin + Result:=NewReg(dtUInt32); + end; + + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpISub,Result,src0,src1)); +end; + +function TEmitOp.OpISubTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) or (src1=0) then Exit(src0); + Result:=OpISubTo(src0,NewReg_q(src0^.dtype,src1,ppLine),ppLine); +end; + +function TEmitOp.OpIMulTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) then Exit(src1); + if (src1=nil) then Exit(src0); + + if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then + begin + Result:=NewReg(dtInt32); + end else + begin + Result:=NewReg(dtUInt32); + end; + + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpIMul,Result,src0,src1)); +end; + +function TEmitOp.OpIMulTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) or (src1<=1) then Exit(src0); + + if isPowerOfTwo(src1) then + begin + src1:=fastIntLog2(src1); + Result:=OpShlTo (src0,src1,ppLine); + end else + begin + Result:=OpIMulTo(src0,src1,ppLine); + end; +end; + +function TEmitOp.OpIDivTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src1=nil) then Exit(src0); + + Result:=NewReg(src0^.dtype); + if (src0^.dtype.Sign<>0) then + begin + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpSDiv,Result,src0,src1)); + end else + begin + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpUDiv,Result,src0,src1)); + end; +end; + +function TEmitOp.OpIDivTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) or (src1<=1) then Exit(src0); + + if isPowerOfTwo(src1) then + begin + src1:=fastIntLog2(src1); + Result:=OpShrTo (src0,src1,ppLine); + end else + begin + Result:=OpIDivTo(src0,src1,ppLine); + end; +end; + +// + +function TEmitOp.OpFAddTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) then Exit(src1); + if (src1=nil) then Exit(src0); + + Result:=NewReg(src0^.dtype); + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpFAdd,Result,src0,src1)); +end; + +function TEmitOp.OpFSubTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) then Exit(src1); + if (src1=nil) then Exit(src0); + + Result:=NewReg(src0^.dtype); + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpFSub,Result,src0,src1)); +end; + +function TEmitOp.OpFMulTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) then Exit(src1); + if (src1=nil) then Exit(src0); + + Result:=NewReg(src0^.dtype); + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpFMul,Result,src0,src1)); +end; + +function TEmitOp.OpFDivTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src1=nil) then Exit(src0); + + Result:=NewReg(src0^.dtype); + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpFDiv,Result,src0,src1)); +end; + +// + +function TEmitOp.OpFAddToS(src0:PsrRegNode;src1:Single;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) or (src1=0) then Exit(src0); + Result:=OpFAddTo(src0,NewReg_s(src0^.dtype,src1,ppLine),ppLine); +end; + +function TEmitOp.OpFMulToS(src0:PsrRegNode;src1:Single;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) or (src1=0) or (src1=1) then Exit(src0); + Result:=OpFMulTo(src0,NewReg_s(src0^.dtype,src1,ppLine),ppLine); +end; + +// + +function TEmitOp.OpUToF(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src=nil) then Exit(src); + + Result:=NewReg(rtype); + _Op1(_get_line(ppLine),Op.OpConvertUToF,Result,src); +end; + +function TEmitOp.OpSToF(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src=nil) then Exit(src); + + Result:=NewReg(rtype); + _Op1(_get_line(ppLine),Op.OpConvertSToF,Result,src); +end; + +function TEmitOp.OpUToU(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src=nil) then Exit(src); + + Result:=NewReg(rtype); + _Op1(_get_line(ppLine),Op.OpUConvert,Result,src); +end; + +function TEmitOp.OpSToS(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src=nil) then Exit(src); + + Result:=NewReg(rtype); + _Op1(_get_line(ppLine),Op.OpSConvert,Result,src); +end; + +function TEmitOp.OpFToF(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src=nil) then Exit(src); + + Result:=NewReg(rtype); + _Op1(_get_line(ppLine),Op.OpFConvert,Result,src); +end; + +// + +procedure TEmitOp.OpNot(dst:PsrRegSlot;src:PsrRegNode); +begin + Op1(Op.OpNot,dtUnknow,dst,src); //post type +end; + +procedure TEmitOp.OpLogicalNot(dst:PsrRegSlot;src:PsrRegNode); +begin + Op1(Op.OpLogicalNot,dtBool,dst,src); +end; + +procedure TEmitOp.OpBitwiseOr(dst:PsrRegSlot;src0,src1:PsrRegNode); +begin + Op2(Op.OpBitwiseOr,dtUnknow,dst,src0,src1); //post type +end; + +procedure TEmitOp.OpBitwiseXor(dst:PsrRegSlot;src0,src1:PsrRegNode); +begin + Op2(Op.OpBitwiseXor,dtUint32,dst,src0,src1); //post need? +end; + +procedure TEmitOp.OpLogicalOr(dst:PsrRegSlot;src0,src1:PsrRegNode); +begin + Op2(Op.OpLogicalOr,dtBool,dst,src0,src1); +end; + +procedure TEmitOp.OpBitwiseAnd(dst:PsrRegSlot;src0,src1:PsrRegNode); +begin + Op2(Op.OpBitwiseAnd,dtUnknow,dst,src0,src1); //post type +end; + +procedure TEmitOp.OpLogicalAnd(dst:PsrRegSlot;src0,src1:PsrRegNode); +begin + Op2(Op.OpLogicalAnd,dtBool,dst,src0,src1); +end; + +// + +function TEmitOp.OpNotTo(src:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + Result:=NewReg(dtUnknow); + _set_line(ppLine,_Op1(_get_line(ppLine),Op.OpNot,Result,src)); //post type +end; + +function TEmitOp.OpBitwiseOrTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + Result:=NewReg(dtUnknow); + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpBitwiseOr,Result,src0,src1)); //post type +end; + +function TEmitOp.OpBitwiseAndTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; +begin + Result:=NewReg(dtUnknow); + _set_line(ppLine,_Op2(_get_line(ppLine),Op.OpBitwiseAnd,Result,src0,src1)); //post type +end; + +function TEmitOp.OpBitwiseAndTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (src0=nil) then Exit(src0); + Result:=OpBitwiseAndTo(src0,NewReg_q(src0^.dtype,src1,ppLine),ppLine); +end; + +// + +function TEmitOp.OpImageSampleImplicitLod(pLine:PspirvOp;img:PsrNode;dst,coord:PsrRegNode):PSpirvOp; Var node:PSpirvOp; begin - node:=AddSpirvOp(pLine,Op.OpImageSampleImplicitLod); - node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); - node^.SetDstReg(dst); + node:=AddSpirvOp(pLine,Op.OpImageSampleImplicitLod); //need first - node^.AddParam(ntReg,cmb); - node^.AddParam(ntReg,coord); + node^.pType:=TypeList.Fetch(dst^.dtype); + node^.pDst:=dst; + + node^.AddParam(img); + node^.AddParam(coord); Result:=node; end; -function TEmitOp.emit_OpImageSampleExplicitLod(pLine:PspirvOp;dst,cmb,coord:PsrRegNode):PSpirvOp; +function TEmitOp.OpImageSampleExplicitLod(pLine:PspirvOp;img:PsrNode;dst,coord:PsrRegNode):PSpirvOp; Var node:PSpirvOp; begin - node:=AddSpirvOp(pLine,Op.OpImageSampleExplicitLod); - node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); - node^.SetDstReg(dst); + node:=AddSpirvOp(pLine,Op.OpImageSampleExplicitLod); //need first - node^.AddParam(ntReg,cmb); - node^.AddParam(ntReg,coord); + node^.pType:=TypeList.Fetch(dst^.dtype); + node^.pDst:=dst; + + node^.AddParam(img); + node^.AddParam(coord); Result:=node; end; -function TEmitOp.emit_OpImageFetch(pLine:PspirvOp;Tgrp,dst,coord:PsrRegNode):PSpirvOp; +function TEmitOp.OpImageFetch(pLine:PspirvOp;Tgrp:PsrNode;dst,coord:PsrRegNode):PSpirvOp; Var node:PSpirvOp; begin - Tgrp^.mark_read; + node:=AddSpirvOp(pLine,Op.OpImageFetch); //need first - node:=AddSpirvOp(pLine,Op.OpImageFetch); - node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); - node^.SetDstReg(dst); + node^.pType:=TypeList.Fetch(dst^.dtype); + node^.pDst:=dst; - node^.AddParam(ntReg,Tgrp); - node^.AddParam(ntReg,coord); + node^.AddParam(Tgrp); + node^.AddParam(coord); Result:=node; end; -function TEmitOp.emit_OpImageRead(pLine:PspirvOp;Tgrp,dst,idx:PsrRegNode):PspirvOp; +function TEmitOp.OpImageRead(pLine:PspirvOp;Tgrp:PsrNode;dst,idx:PsrRegNode):PspirvOp; Var node:PSpirvOp; begin - Tgrp^.mark_read; + node:=AddSpirvOp(pLine,Op.OpImageRead); //need first - node:=AddSpirvOp(pLine,Op.OpImageRead); - node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); - node^.SetDstReg(dst); + node^.pType:=TypeList.Fetch(dst^.dtype); + node^.pDst:=dst; - node^.AddParam(ntReg,Tgrp); + node^.AddParam(Tgrp); if (idx<>nil) then begin - node^.AddParam(ntReg,idx); + node^.AddParam(idx); end else begin - node^.AddParam(ntConst,FConsts.Fetchi(dtUint32,0)); + node^.AddParam(ConstList.Fetch_i(dtUint32,0)); end; Result:=node; end; -function TEmitOp.emit_OpImageWrite(pLine:PspirvOp;Tgrp,idx,src:PsrRegNode):PspirvOp; +function TEmitOp.OpImageWrite(pLine:PspirvOp;Tgrp:PsrNode;idx,src:PsrRegNode):PspirvOp; Var node:PSpirvOp; begin - Tgrp^.mark_read; //mark write - - node:=AddSpirvOp(pLine,Op.OpImageWrite); - node^.dst.SetParam(ntReg,Tgrp); - - node^.AddParam(ntReg,Tgrp); + node:=AddSpirvOp(pLine,Op.OpImageWrite); //need first + node^.pDst:=Tgrp; //write if (idx<>nil) then begin - node^.AddParam(ntReg,idx); + node^.AddParam(idx); end else begin - node^.AddParam(ntConst,FConsts.Fetchi(dtUint32,0)); + node^.AddParam(ConstList.Fetch_i(dtUint32,0)); end; - node^.AddParam(ntReg,src); + node^.AddParam(src); Result:=node; end; diff --git a/spirv/emit_post.pas b/spirv/emit_post.pas index 78265a91..ab6a0089 100644 --- a/spirv/emit_post.pas +++ b/spirv/emit_post.pas @@ -7,38 +7,36 @@ interface uses sysutils, spirv, - srNodes, + srNode, + srType, srTypes, srConst, srReg, srVariable, - srVolatile, srLayout, srBuffer, + srBitcast, + srPrivate, srOp, srOpUtils, - SprvEmit, - emit_op; + emit_fetch; type TPostCb=function(node:PSpirvOp):Integer of object; TRegsCb=function(pLine:PspirvOp;var node:PsrRegNode):Integer of object; - TChainCb=function(node:PsrChain):Integer of object; - TSprvEmit_post=object(TEmitOp) - function Post:Integer; - - function PrepTypeNode(var node:PsrRegNode;rtype:TsrDataType;relax:Boolean=true):Integer; - function PrepTypeDst(var node:PsrRegNode;rtype:TsrDataType;relax:Boolean=true):Integer; - function PrepTypeParam(node:POpParamNode;rtype:TsrDataType;relax:Boolean=true):Integer; + TSprvEmit_post=class(TEmitFetch) + function PostStage:Integer; function RegFindCond(pLine:PspirvOp;var node:PsrRegNode):Integer; - function RegCollapse({%H-}pLine:PspirvOp;var node:PsrRegNode):Integer; + function RegCollapse(pLine:PspirvOp;var node:PsrRegNode):Integer; + function RegVResolve(pLine:PspirvOp;var node:PsrRegNode):Integer; + function RegWResolve(pLine:PspirvOp;var node:PsrRegNode):Integer; function RegTypecast(pLine:PspirvOp;var node:PsrRegNode):Integer; function RegSTStrict(pLine:PspirvOp;var node:PsrRegNode):Integer; function RegVTStrict(pLine:PspirvOp;var node:PsrRegNode):Integer; - function NodeOpSameOp(node:PSpirvOp):Integer; + //function NodeOpSameOp(node:PSpirvOp):Integer; function NodeOpStrict(node:PSpirvOp):Integer; function OnOpStep1(node:PSpirvOp):Integer; //backward @@ -46,240 +44,95 @@ type function OnOpStep3(node:PSpirvOp):Integer; //forward function OnOpStep4(node:PSpirvOp):Integer; //forward function OnOpStep5(node:PSpirvOp):Integer; //backward + function OnOpStep6(node:PSpirvOp):Integer; //backward + function OnOpStep7(node:PSpirvOp):Integer; //backward function PostFuncAnalize:Integer; - function EnumChain(p:PsrDataLayout;cb:TChainCb):Integer; - function EnumChain(cb:TChainCb):Integer; + function OnChainUpdate(node:PsrChain):Integer; function PostDataLayoutAnalize:Integer; function FetchField(var pChain:PsrChain;dtype:TsrDataType):PsrField; - Procedure SetLoadType(pChain:PsrChain;rtype:TsrDataType); function OnChainField(node:PsrChain):Integer; function OnChainAlloc(node:PsrChain):Integer; procedure OnFieldType(node:PsrField); - procedure AllocBufferVar(node:PsrBuffer); function PostConstAnalize:Integer; function PostVariableAnalize:Integer; - function PostTypeAnalize(first:Boolean):Integer; + function PostTypeAnalize:Integer; end; -function DstIsClear(const node:TOpParamSingle):Boolean; function EnumLineRegs(cb:TRegsCb;pLine:PSpirvOp):Integer; function EnumBlockOpForward(cb:TPostCb;pBlock:PsrOpBlock):Integer; function EnumBlockOpBackward(cb:TPostCb;pBlock:PsrOpBlock):Integer; -procedure RegUnmark(node:PsrRegNode); -Procedure NodeParamClear(node:POpParamNode); -function NodeOpClear(p:PSpirvOp):Integer; implementation uses emit_post_op; -function TSprvEmit_post.Post:Integer; +function TSprvEmit_post.PostStage:Integer; begin Result:=0; Result:=Result+PostFuncAnalize; - Result:=Result+PostConstAnalize; - Result:=Result+PostTypeAnalize(True); //1 Result:=Result+PostVariableAnalize; - Result:=Result+PostTypeAnalize(False); //2 - -end; - -function TSprvEmit_post.PrepTypeNode(var node:PsrRegNode;rtype:TsrDataType;relax:Boolean=true):Integer; -var - old:PsrRegNode; -begin - Result:=0; - if (node=nil) then Exit; - if (rtype=dtUnknow) then Exit; - - if (node^.dtype=dtUnknow) then - begin - RegPrepType(node,rtype); - Inc(Result); - end else - begin - Case relax of - True :relax:=CompareType(node^.dtype,rtype); - False:relax:=(node^.dtype=rtype); - end; - if not relax then - begin - old:=node; - node:=FBitcast.FetchRead(rtype,old); - RegUnmark(old); - Inc(Result); - end; - end; -end; - -function TSprvEmit_post.PrepTypeDst(var node:PsrRegNode;rtype:TsrDataType;relax:Boolean=true):Integer; -var - old:PsrRegNode; -begin - Result:=0; - if (node=nil) then Exit; - if (rtype=dtUnknow) then Exit; - - if (node^.dtype=dtUnknow) then - begin - RegPrepType(node,rtype); - Inc(Result); - end else - begin - Case relax of - True :relax:=CompareType(node^.dtype,rtype); - False:relax:=(node^.dtype=rtype); - end; - if not relax then - begin - old:=node; - node:=FBitcast.FetchDst(rtype,old); - Inc(Result); - end; - end; - -end; - -function TSprvEmit_post.PrepTypeParam(node:POpParamNode;rtype:TsrDataType;relax:Boolean=true):Integer; -begin - Result:=0; - if (node=nil) then Exit; - if (rtype=dtUnknow) then Exit; - if (node^.ntype<>ntReg) then Exit; - Result:=PrepTypeNode(node^.pData,rtype,relax); -end; - -function DstIsClear(const node:TOpParamSingle):Boolean; -var - pVar:PsrVariable; - pReg:PsrRegNode; - pFunc:PSpirvFunc; - pChain:PsrChain; -begin - Result:=False; - Case node.ntype of - ntUnknow:;//dst not used - ntBlock:; - ntRefId:; - ntVar: - begin - pVar:=node.pData; - Result:=(pVar^.read_count=0) and (pVar^.write_count=0); - end; - ntReg: - begin - pReg:=node.pData; - Result:=(pReg^.read_count=0); - end; - ntFunc: - begin - pFunc:=node.pData; - Result:=(pFunc^.read_count=0); - end; - ntChain: - begin - pChain:=node.pData; - Result:=(pChain^.read_count=0) and (pChain^.write_count=0); - end; - else - Assert(false,'DstIsClear'); - end; + Result:=Result+PostConstAnalize; + Result:=Result+PostTypeAnalize; end; function EnumLineRegs(cb:TRegsCb;pLine:PSpirvOp):Integer; var node:POpParamNode; + pReg:PsrRegNode; begin Result:=0; if (cb=nil) or (pLine=nil) then Exit; - node:=pLine^.pParam.pHead; + node:=pLine^.ParamFirst; While (node<>nil) do begin - Case node^.ntype of - ntReg: - begin - Result:=Result+cb(pLine,node^.pData); - end - else; + if node^.Value^.IsType(ntReg) then + begin + pReg:=node^.AsReg; + Result:=Result+cb(pLine,pReg); + node^.Value:=pReg; end; - node:=node^.pNext; + node:=node^.Next; end; end; function EnumBlockOpForward(cb:TPostCb;pBlock:PsrOpBlock):Integer; var - node:PSpirvOp; + node,prev:PSpirvOp; begin Result:=0; if (pBlock=nil) or (cb=nil) then Exit; - node:=pBlock^.pHead; - repeat - While (node<>nil) do + node:=pBlock^.First; + While (node<>nil) do + begin + prev:=node; + node:=flow_down_next_up(node); + if prev^.IsType(ntOp) then begin - Case node^.OpId of - OpBlock: - begin - pBlock:=node^.dst.AsBlock; //down - if (pBlock<>nil) then - begin - pBlock^.pUpLine:=node; - node:=pBlock^.pHead; - Continue; - end; - end; - else - begin - Result:=Result+cb(node); - end; - end; - node:=node^.pNext; + Result:=Result+cb(prev); end; - node:=pBlock^.pUpLine; //prev - if (node=nil) then Break; - pBlock:=node^.pParent; //up - if (pBlock=nil) then Break; - node:=node^.pNext; - until false; + end; end; function EnumBlockOpBackward(cb:TPostCb;pBlock:PsrOpBlock):Integer; var - node:PSpirvOp; + node,prev:PSpirvOp; begin Result:=0; if (pBlock=nil) or (cb=nil) then Exit; - node:=pBlock^.pTail; - repeat - While (node<>nil) do + node:=pBlock^.Last; + While (node<>nil) do + begin + prev:=node; + node:=flow_down_prev_up(node); + if prev^.IsType(ntOp) then begin - Case node^.OpId of - OpBlock: - begin - pBlock:=node^.dst.AsBlock; //down - if (pBlock<>nil) then - begin - pBlock^.pUpLine:=node; - node:=pBlock^.pTail; - Continue; - end; - end; - else - begin - Result:=Result+cb(node); - end; - end; - node:=node^.pPrev; + Result:=Result+cb(prev); end; - node:=pBlock^.pUpLine; //prev - if (node=nil) then Break; - pBlock:=node^.pParent; //up - if (pBlock=nil) then Break; - node:=node^.pPrev; - until false; + end; end; function TSprvEmit_post.RegFindCond(pLine:PspirvOp;var node:PsrRegNode):Integer; @@ -293,7 +146,7 @@ begin Result:=0; if (node=nil) then Exit; - pBlock:=pLine^.pParent; + pBlock:=pLine^.Parent; src:=RegDown(node); n:=false; @@ -304,12 +157,12 @@ begin if (tmp<>nil) then begin if (tmp=pBlock) and (pLine^.OpId=Op.OpBranchConditional) then Exit; - RegUnmark(node); - node:=FetchReg(FConsts.Fetchb(n xor tmp^.Cond.FVal)); + + node:=NewReg_b(n xor tmp^.Cond.FVal,@pLine); Exit(1); end; - p:=src^.AsOp; + p:=src^.pWriter^.AsType(ntOp); if (p=nil) then Exit; Case p^.OpId of @@ -319,7 +172,7 @@ begin Exit; end; - src:=p^.ParamNode(0)^.AsReg; + src:=p^.ParamFirst^.AsReg; if (src=nil) then Exit; src:=RegDown(src); n:=not n; @@ -329,85 +182,174 @@ end; function TSprvEmit_post.RegCollapse(pLine:PspirvOp;var node:PsrRegNode):Integer; var - new,old:PsrRegNode; + old:PsrRegNode; begin Result:=0; if (node=nil) then Exit; - //backtrace + if (node^.dtype=dtUnknow) then Exit; + old:=node; - While (true) do - begin - Case old^.pWriter.ntype of - ntReg: - begin - new:=old^.pWriter.pData; //next - old^.mark_unread; - if (old^.read_count<>0) then - begin - new^.mark_read; - end; - old:=new; - end; - else - Break; - end; - end; + node:=RegDown(old); if (old<>node) then //is change? begin if (node^.dtype=dtUnknow) or CompareType(node^.dtype,old^.dtype) then begin - node:=old; //set new Inc(Result); end else begin //save to another step - node^.mark_read; - node^.SetReg(old); + old^.pWriter:=node; + node:=old; end; end; end; -function TSprvEmit_post.RegTypecast(pLine:PspirvOp;var node:PsrRegNode):Integer; +function TSprvEmit_post.RegVResolve(pLine:PspirvOp;var node:PsrRegNode):Integer; var - new,old:PsrRegNode; + old:PsrRegNode; begin Result:=0; if (node=nil) then Exit; - //backtrace + old:=node; - While (true) do - begin - Case old^.pWriter.ntype of - ntReg: - begin - new:=old^.pWriter.pData; //next - old^.mark_unread; - if (old^.read_count<>0) then - begin - new^.mark_read; - end; - old:=new; - end; - ntVolatile: - begin //create load/store - TEmitVolatile(Self).PrepVolatile(pLine,old); - Inc(Result); - end - else - Break; + + repeat + node:=RegDown(old); + if node^.pWriter^.IsType(ntVolatile) then + begin + //create load/store + //use forward only + PrivateList.PrepVolatile(pLine,node); + Inc(Result); + end else + begin + Break; end; - end; + until false; + + if (old<>node) then //is change? + begin + if (node^.dtype=dtUnknow) or (node^.dtype=old^.dtype) then + begin + Inc(Result); + end else + begin //save to another step + old^.pWriter:=node; + node:=old; + end; + end; +end; + +function GetDepType(src:PsrRegNode):TsrDataType; +var + node:PRegDNode; + pReg:PsrRegNode; + pLine:PspirvOp; + + Function CmpType(var ret:TsrDataType;dtype:TsrDataType):Boolean; + begin + Result:=False; + if (dtype=dtUnknow) then Exit; + if (ret=dtUnknow) then + begin + ret:=dtype; + end else + begin + if (ret<>dtype) then + begin + ret:=dtUnknow; + Result:=True; //Exit + end; + end; + end; + +begin + Result:=dtUnknow; + node:=src^.FirstDep; + While (node<>nil) do + begin + if node^.pNode^.IsType(ntReg) then + begin + pReg:=node^.pNode^.AsType(ntReg); + if (pReg<>nil) then + begin + if CmpType(Result,pReg^.dtype) then Exit; + end; + end else + if node^.pNode^.IsType(ntOp) then + begin + pLine:=node^.pNode^.AsType(ntOp); + Case pLine^.OpId of + + Op.OpStore: + begin + //ignore? + end; + + else + begin + if CmpType(Result,src^.dtype) then Exit; + end; + end; + end; + node:=node^.pNext; + end; +end; + +function ResolveWeak(new:PsrRegNode):Integer; +var + dtype:TsrDataType; +begin + Result:=0; + While (new<>nil) do + begin + + if new^.Weak then + begin + dtype:=GetDepType(new); + if (dtype<>dtUnknow) then + begin + if (new^.dtype<>dtype) then + begin + new^.dtype:=dtype; + new^.Weak :=False; + Inc(Result); + end else + begin + new^.Weak :=False; + end; + end; + end; + + new:=new^.AsReg; //next + end; +end; + +function TSprvEmit_post.RegWResolve(pLine:PspirvOp;var node:PsrRegNode):Integer; +begin + Result:=0; + if (node=nil) then Exit; + Result:=Result+ResolveWeak(node); +end; + +function TSprvEmit_post.RegTypecast(pLine:PspirvOp;var node:PsrRegNode):Integer; +var + old:PsrRegNode; +begin + Result:=0; + if (node=nil) then Exit; + + old:=node; + node:=RegDown(old); if (old<>node) then //is change? begin if (node^.dtype=dtUnknow) or (node^.dtype=old^.dtype) then begin - node:=old; //set new Inc(Result); end else begin //bitcast - old^.mark_unread; - node:=FBitcast.FetchCast(node^.dtype,old); + node:=BitcastList.FetchCast(old^.dtype,node); Inc(Result); end; end; @@ -416,26 +358,17 @@ end; function TSprvEmit_post.RegSTStrict(pLine:PspirvOp;var node:PsrRegNode):Integer; var dtype:TsrDataType; - dst,old:PsrRegNode; + dst:PsrRegNode; begin Result:=0; if (node^.dtype=dtBool) then Exit; - dst:=pLine^.dst.AsReg; + dst:=pLine^.pDst^.AsType(ntReg); if (dst=nil) then Exit; - {pLine:=node^.pLine; - if (pLine^.dst_type^.key.dtype<>node^.dtype) then - begin - Writeln(Op.GetStr(pLine^.OpId),' ',pLine^.dst_type^.key.dtype,'<>',node^.dtype); - Assert(false); - end;} - dtype:=dst^.dtype; if (dtype<>node^.dtype) then begin - old:=node; - node:=FBitcast.FetchCast(dtype,old); //strict type - RegUnmark(old); + node:=BitcastList.FetchCast(dtype,node); //strict type Inc(Result); end; end; @@ -443,109 +376,21 @@ end; function TSprvEmit_post.RegVTStrict(pLine:PspirvOp;var node:PsrRegNode):Integer; var dtype:TsrDataType; - dst,old:PsrRegNode; + dst:PsrRegNode; begin Result:=0; - dst:=pLine^.dst.AsReg; + dst:=pLine^.pDst^.AsType(ntReg); if (dst=nil) then Exit; - dtype:=GetVecChild(dst^.dtype); + + dtype:=dst^.dtype.Child; if (dtype<>node^.dtype) then begin - old:=node; - node:=FBitcast.FetchCast(dtype,old); //strict type - RegUnmark(old); - Inc(Result); - end; -end; - -procedure _RegUnmark(var st_lt:TsrVolatiles;node:PsrRegNode); -var - n:PsrRegNode; - pConst:PsrConst; -begin - node^.mark_unread; - //backtrace - While (node^.read_count=0) do - begin - Case node^.pWriter.ntype of - ntReg: - begin - n:=node^.pWriter.pData; //next - n^.mark_unread; - node:=n; - end; - ntVolatile: - begin - st_lt.Move_from(TsrVolatiles(node^.pWriter.pData)); - n:=st_lt.pop_reg; - if (n=nil) then Break; - n^.mark_unread; - node:=n; - end; - ntConst: - begin - pConst:=node^.pWriter.pData; - pConst^.mark_unread; - Break; - end; - ntOp:Break; - ntUnknow:Break; //nop - else - Assert(false,'_RegUnmark'); - end; - end; -end; - -procedure RegUnmark(node:PsrRegNode); -var - st_lt:TsrVolatiles; -begin - st_lt:=Default(TsrVolatiles); - While (node<>nil) do - begin - _RegUnmark(st_lt,node); - node:=st_lt.pop_reg; - end; -end; - -Procedure NodeParamClear(node:POpParamNode); -begin - if (node=nil) then Exit; - Case node^.ntype of - ntLiteral:; - ntConst:PsrConst (node^.pData)^.mark_unread; - ntType :PsrType (node^.pData)^.mark_unread; - ntFunc :PSpirvFunc (node^.pData)^.mark_unread; - ntVar :PsrVariable(node^.pData)^.mark_unread; - ntRefId:; - ntReg :RegUnmark (node^.pData); - ntChain:PsrChain (node^.pData)^.mark_unread; - else - Assert(false,'NodeParamClear'); - end; -end; - -function NodeOpClear(p:PSpirvOp):Integer; -var - node:POpParamNode; -begin - Result:=0; - if (p=nil) then Exit; - if (p^.dst_type<>nil) then - begin - p^.dst_type^.mark_unread; - p^.dst_type:=nil; - Inc(Result); - end; - node:=p^.pParam.Pop_head; - While (node<>nil) do - begin - NodeParamClear(node); - node:=p^.pParam.Pop_head; + node:=BitcastList.FetchCast(dtype,node); //strict type Inc(Result); end; end; +{ function TSprvEmit_post.NodeOpSameOp(node:PSpirvOp):Integer; var tmp:PspirvOp; @@ -572,7 +417,6 @@ begin if (src=nil) or (dst=nil) then Exit; - src^.mark_read; dst^.SetReg(src); node^.OpId:=OpLinks; //mark remove @@ -580,20 +424,19 @@ begin Result:=1; end; +} function TSprvEmit_post.NodeOpStrict(node:PSpirvOp):Integer; begin Result:=0; - if (node^.dst.ntype<>ntReg) then Exit; //is reg + if not node^.pDst^.IsType(ntReg) then Exit; //is reg Case node^.OpId of - Op.OpBitFieldUExtract, - Op.OpSelect: - Result:=EnumLineRegs(@RegSTStrict,node); - Op.OpIAddCarry, - Op.OpISubBorrow, - Op.OpCompositeConstruct: - Result:=EnumLineRegs(@RegVTStrict,node); + Op.OpBitFieldUExtract , + Op.OpSelect :Result:=EnumLineRegs(@RegSTStrict,node); + Op.OpIAddCarry , + Op.OpISubBorrow , + Op.OpCompositeConstruct:Result:=EnumLineRegs(@RegVTStrict,node); else; end; @@ -602,125 +445,112 @@ end; function TSprvEmit_post.OnOpStep1(node:PSpirvOp):Integer; //backward begin Result:=0; - Case node^.OpId of - Op.OpNop:; //ignore - OpLinks: - begin - Result:=Result+NodeOpClear(node); //delete links - node^.OpId:=Op.OpNop; //mark remove - Inc(Result); - end; - else - begin - if DstIsClear(node^.dst) then - begin - Result:=Result+NodeOpClear(node); //delete links - node^.OpId:=Op.OpNop; //mark remove - Inc(Result); - end else - begin - Result:=Result+NodeOpSameOp(node); - Result:=Result+EnumLineRegs(@RegCollapse,node); - Result:=Result+EnumLineRegs(@RegFindCond,node); - end; - end; + + if node^.is_cleared then Exit; + + if node^.can_clear then + begin + if node^.Clear then Inc(Result); + end else + begin + //Result:=Result+NodeOpSameOp(node); + Result:=Result+EnumLineRegs(@RegCollapse,node); + Result:=Result+EnumLineRegs(@RegFindCond,node); end; end; function TSprvEmit_post.OnOpStep2(node:PSpirvOp):Integer; //forward begin Result:=0; - Case node^.OpId of - Op.OpNop:; //ignore - OpLinks: - begin - Result:=Result+NodeOpClear(node); //delete links - node^.OpId:=Op.OpNop; //mark remove - Inc(Result); - end; - else - begin - if DstIsClear(node^.dst) then - begin - Result:=Result+NodeOpClear(node); //delete links - node^.OpId:=Op.OpNop; //mark remove - Inc(Result); - end else - begin - //Result:=Result+EnumLineRegs(@RegCond,node); - //Result:=Result+EnumLineRegs(@RegCuts,node); - Result:=Result+TEmitPostOp(Self).PostForward1(node); - end; - end; + + if node^.is_cleared then Exit; + + if node^.can_clear then + begin + if node^.Clear then Inc(Result); + end else + begin + Result:=Result+TEmitPostOp(TObject(Self)).PostForward1(node); end; end; function TSprvEmit_post.OnOpStep3(node:PSpirvOp):Integer; //forward begin Result:=0; - Case node^.OpId of - Op.OpNop:; //ignore - OpLinks: - begin - Result:=Result+NodeOpClear(node); //delete links - node^.OpId:=Op.OpNop; //mark remove - Inc(Result); - end; - else - begin - if DstIsClear(node^.dst) then - begin - Result:=Result+NodeOpClear(node); //delete links - node^.OpId:=Op.OpNop; //mark remove - Inc(Result); - end else - begin - //Result:=Result+EnumLineRegs(@RegCond,node); - //Result:=Result+EnumLineRegs(@RegCuts,node); - Result:=Result+TEmitPostOp(Self).PostForward2(node); - end; - end; + + if node^.is_cleared then Exit; + + if node^.can_clear then + begin + if node^.Clear then Inc(Result); + end else + begin + Result:=Result+TEmitPostOp(TObject(Self)).PostForward2(node); end; end; function TSprvEmit_post.OnOpStep4(node:PSpirvOp):Integer; //forward begin Result:=0; - Case node^.OpId of - Op.OpNop:; //ignore - OpLinks:; //ignore - else - begin - if not DstIsClear(node^.dst) then - begin - Result:=Result+EnumLineRegs(@RegTypecast,node); - Result:=Result+NodeOpStrict(node); - Result:=Result+EnumLineRegs(@RegFindCond,node); - end; - end; + + if node^.is_cleared then Exit; + + if node^.can_clear then + begin + if node^.Clear then Inc(Result); + end else + begin + Result:=Result+EnumLineRegs(@RegVResolve,node); end; end; function TSprvEmit_post.OnOpStep5(node:PSpirvOp):Integer; //backward begin Result:=0; - Case node^.OpId of - Op.OpNop, - OpLinks: - begin - Result:=Result+NodeOpClear(node); //delete links - node^.Remove; //remove - Inc(Result); - end; - else - begin - if DstIsClear(node^.dst) then - begin - Result:=Result+NodeOpClear(node); //delete links - node^.Remove; //remove - Inc(Result); - end; - end; + + if node^.is_cleared then Exit; + + if node^.can_clear then + begin + if node^.Clear then Inc(Result); + end else + begin + Result:=Result+EnumLineRegs(@RegWResolve,node); + end; +end; + +function TSprvEmit_post.OnOpStep6(node:PSpirvOp):Integer; //backward +begin + Result:=0; + + if node^.is_cleared then Exit; + + if node^.can_clear then + begin + if node^.Clear then Inc(Result); + end else + begin + Result:=Result+EnumLineRegs(@RegTypecast,node); + Result:=Result+NodeOpStrict(node); + Result:=Result+EnumLineRegs(@RegFindCond,node); + end; +end; + +function TSprvEmit_post.OnOpStep7(node:PSpirvOp):Integer; //backward +begin + Result:=0; + + if node^.is_cleared then + begin + Assert(node^.read_count=0); + node^.Remove; + Inc(Result); + end else + if node^.can_clear then + begin + node^.Clear; + node^.Remove; + Inc(Result); end; end; @@ -728,123 +558,123 @@ function TSprvEmit_post.PostFuncAnalize:Integer; var pFunc:PSpirvFunc; data_layout:Boolean; - i:Integer; + i,r4:Integer; begin Result:=0; data_layout:=false; //backward analize - pFunc:=FSpirvFuncs.FList.pTail; + pFunc:=FuncList.FList.pTail; While (pFunc<>nil) do begin - data_layout:=(FMain=pFunc); + data_layout:=(Main=pFunc); - repeat + repeat //OnOpStep5 - repeat + repeat //OnOpStep3 - repeat - i:=EnumBlockOpBackward(@OnOpStep1,@pFunc^.FTop); + repeat //OnOpStep2 + + repeat //OnOpStep1 + i:=EnumBlockOpBackward(@OnOpStep1,pFunc^.pTop); + if (i=0) then Break; + Result:=Result+i; + until false; + + i:=EnumBlockOpForward(@OnOpStep2,pFunc^.pTop); if (i=0) then Break; Result:=Result+i; until false; - i:=EnumBlockOpForward(@OnOpStep2,@pFunc^.FTop); + i:=EnumBlockOpForward(@OnOpStep3,pFunc^.pTop); if (i=0) then Break; Result:=Result+i; until false; - i:=EnumBlockOpForward (@OnOpStep3,@pFunc^.FTop); + if data_layout then + begin + Result:=Result+PostDataLayoutAnalize; + data_layout:=false; + end; + + repeat //OnOpStep4 + i:=EnumBlockOpForward(@OnOpStep4,pFunc^.pTop); + if (i=0) then Break; + Result:=Result+i; + until false; + + r4:=0; + repeat //OnOpStep5 + i:=EnumBlockOpBackward(@OnOpStep5,pFunc^.pTop); + if (i=0) then Break; + r4:=r4+i; + until false; + + if (r4=0) then Break; + Result:=Result+r4; + until false; + + //UpdateRegType OpLoad/OpStore + DataLayoutList.EnumChain(@OnChainUpdate); + PrivateList.Post; + + repeat //OnOpStep6 + i:=EnumBlockOpBackward(@OnOpStep6,pFunc^.pTop); if (i=0) then Break; Result:=Result+i; until false; - if data_layout then - begin - Result:=Result+PostDataLayoutAnalize; - data_layout:=false; - end; + Result:=Result+EnumBlockOpBackward(@OnOpStep7,pFunc^.pTop); - repeat - i:=EnumBlockOpForward (@OnOpStep4,@pFunc^.FTop); - if (i=0) then Break; - Result:=Result+i; - until false; - - Result:=Result+EnumBlockOpBackward(@OnOpStep5,@pFunc^.FTop); - - pFunc:=pFunc^.pPrev; + pFunc:=pFunc^.Prev; end; end; -function TSprvEmit_post.EnumChain(p:PsrDataLayout;cb:TChainCb):Integer; -var - node:PsrChain; +function TSprvEmit_post.OnChainUpdate(node:PsrChain):Integer; begin Result:=0; - node:=p^.First; - While (node<>nil) do - begin - if node^.IsUsed then - begin - Result:=Result+cb(node); - end; - node:=p^.Next(node); - end; -end; - -function TSprvEmit_post.EnumChain(cb:TChainCb):Integer; -var - node:PsrDataLayout; -begin - Result:=0; - if (cb=nil) then Exit; - node:=FDataLayouts.First; - While (node<>nil) do - begin - Result:=Result+EnumChain(node,cb); - node:=FDataLayouts.Next(node); - end; + node^.UpdateRegType; end; function TSprvEmit_post.PostDataLayoutAnalize:Integer; begin Result:=0; - FDataLayouts.AllocID; + DataLayoutList.AllocID; - Result:=Result+EnumChain(@OnChainField); + Result:=Result+DataLayoutList.EnumChain(@OnChainField); - FBuffers.ApplyBufferType; - FBuffers.AlignOffset; - FBuffers.FillSpace; - FBuffers.AllocID; - FBuffers.EnumAllField(@OnFieldType); + BufferList.ApplyBufferType; + BufferList.AlignOffset; + BufferList.FillSpace; + BufferList.AllocID; + BufferList.EnumAllField(@OnFieldType); - Result:=Result+EnumChain(@OnChainAlloc); + Result:=Result+DataLayoutList.EnumChain(@OnChainAlloc); end; function TSprvEmit_post.FetchField(var pChain:PsrChain;dtype:TsrDataType):PsrField; var buf:PsrBuffer; F:TFieldFetchValue; - _offset,_count,_stride:PtrUint; - ext:TsrChainExt; - pNew:PsrChain; + _offset,_stride:PtrUint; + _count:PtrUint; + //ext:TsrChainExt; + //pNew:PsrChain; fset_index:Boolean; begin _count:=0; _stride:=0; - if (pChain^.key.ext.pIndex<>nil) then + if (pChain^.pIndex<>nil) then begin //RuntimeArray - buf:=FBuffers.Fetch(pChain^.parent,0); + buf:=BufferList.Fetch(pChain^.parent,0); repeat - _offset:=pChain^.key.offset; - F:=buf^.FTop.FetchRuntimeArray(_offset,pChain^.key.ext.stride); + _offset:=pChain^.offset; + F:=buf^.FTop.FetchRuntimeArray(_offset,pChain^.stride); repeat Case F.fValue of @@ -854,27 +684,27 @@ begin frValueInVector:_offset:=_offset-F.pField^.offset; frValueInArray :_offset:=_offset-F.pField^.offset; end; - F:=F.pField^.FetchValue(_offset,pChain^.key.size,dtype); + F:=F.pField^.FetchValue(_offset,pChain^.size,dtype); until (F.fValue<>frNotFit); if (F.fValue<>frNotFit) then Break; - buf:=FBuffers.NextCast(buf); + buf:=BufferList.NextAlias(buf); until false; end else begin //Value/Vector - buf:=FBuffers.Fetch(pChain^.parent,0); + buf:=BufferList.Fetch(pChain^.parent,0); fset_index:=False; repeat - _offset:=pChain^.key.offset; + _offset:=pChain^.offset; F.pField:=@buf^.FTop; repeat - F:=F.pField^.FetchValue(_offset,pChain^.key.size,dtype); + F:=F.pField^.FetchValue(_offset,pChain^.size,dtype); Case F.fValue of frNotFit :Break; frIdent, @@ -882,12 +712,14 @@ begin begin if fset_index then begin + Break; + { Assert(pChain^.key.ext.pIndex=nil); ext:=Default(TsrChainExt); - ext.pIndex:=FetchReg(FConsts.Fetchi(dtUint32,_count)); + ext.pIndex:=NewReg_i(dtUint32,_count); ext.stride:=_stride; - pNew:=pChain^.parent^.Fetch(_offset,pChain^.key.size,@ext); + pNew:=pChain^.FParent^.Fetch(_offset,pChain^.key.size,@ext); pNew^.read_count :=pChain^.read_count ; pNew^.write_count:=pChain^.write_count; @@ -898,6 +730,7 @@ begin pChain^.rSlot :=Default(TsrRegSlot); pChain:=pNew; + } end; Exit(F.pField); end; @@ -916,7 +749,7 @@ begin until (F.fValue<>frNotFit); if (F.fValue<>frNotFit) then Break; - buf:=FBuffers.NextCast(buf); + buf:=BufferList.NextAlias(buf); fset_index:=False; until false; @@ -925,55 +758,31 @@ begin Result:=F.pField; end; -Procedure TSprvEmit_post.SetLoadType(pChain:PsrChain;rtype:TsrDataType); -var - node:PsrRegNode; - pLine:PspirvOp; -begin - node:=pChain^.rSlot.pStory.pHead; - While (node<>nil) do - begin - node^.dtype:=rtype; - pLine:=node^.pWriter.AsOp; - if (pLine<>nil) then - if (pLine=node^.pLine) then //is current load - if (pLine^.OpId=Op.OpLoad) then - begin - if (pLine^.dst_type<>nil) then - begin - pLine^.dst_type^.mark_unread; - end; - pLine^.dst_type:=FSpirvTypes.Fetch(rtype); - end; - node:=node^.pNext; - end; -end; - function TSprvEmit_post.OnChainField(node:PsrChain):Integer; var pField:PsrField; dtype:TsrDataType; begin Result:=1; - dtype:=node^.GetRegType; + dtype:=node^.dtype; //Writeln('OnChainsField:',dtype,':',node^.key.offset); pField:=FetchField(node,dtype); + Assert(pField<>nil); node^.pField:=pField; if (pField^.dtype<>dtype) then begin - dtype:=pField^.dtype; - SetLoadType(node,dtype); - - //Writeln(pField^.dtype,'<>',dtype); - //Assert(false,'TODO'); + node^.dtype:=pField^.dtype; end; - FBuffers.UpdateStorage(node,pField^.pBuffer); + pField^.pBuffer^.TakeChain(node); end; procedure TSprvEmit_post.OnFieldType(node:PsrField); var count:PtrUint; + + items:PPsrType; sType,pType:PsrType; + child:PsrField; begin if (node^.pType<>nil) then Exit; @@ -986,36 +795,41 @@ begin Assert(child<>nil); Assert(child^.pType<>nil); sType:=child^.pType; - sType^.mark_read; end else begin count:=node^.FCount; Assert(count<>0); - sType:=FSpirvTypes._New(count); + items:=Alloc(SizeOf(Pointer)*count); count:=0; child:=node^.First; While (child<>nil) do begin Assert(child^.pType<>nil); - child^.pType^.mark_read; - sType^.SetCompItem(count,child^.pType); + items[count]:=child^.pType; Inc(count); child:=node^.Next(child); end; - sType:=FSpirvTypes.FetchStructNode(sType,count,node); + if node^.IsTop then + begin + sType:=TypeList.InsertStruct(count,items,False,node^.GetSize); //unique + end else + begin + sType:=TypeList.FetchStruct (count,items,False,node^.GetSize); + end; + end; Case node^.dtype of dtTypeArray: begin - count:=node^.size div node^.stride; - pType:=FSpirvTypes.FetchArray(sType,count,node^.stride); + count:=node^.GetSize div node^.stride; + pType:=TypeList.FetchArray(sType,count); end; dtTypeRuntimeArray: begin - pType:=FSpirvTypes.FetchRuntimeArray(sType,node^.stride); + pType:=TypeList.FetchRuntimeArray(sType); end; else begin @@ -1025,41 +839,19 @@ begin node^.pType:=pType; - if (node^.parent=nil) then + if node^.IsTop then begin - AllocBufferVar(node^.pBuffer); + //Alloc Type Var + node^.pBuffer^.pType:=pType; end; end else begin - node^.pType:=FSpirvTypes.Fetch(node^.dtype); + node^.pType:=TypeList.Fetch(node^.dtype); end; end; -procedure TSprvEmit_post.AllocBufferVar(node:PsrBuffer); -var - pVar:PsrVariable; - pType:PsrType; -begin - pType:=node^.FTop.pType; - Assert(pType<>nil); - - pVar:=node^.pVar; - if (pVar=nil) then - begin - pType^.mark_read; - pType:=FSpirvTypes.FetchPointer(pType,node^.FStorage); - - pVar:=NewVariable; - pVar^.dtype:=dtTypeStruct; - pVar^.pType:=pType; - pVar^.pSource.SetParam(ntBuffer,node); - - node^.pVar:=pVar; - end; -end; - function TSprvEmit_post.OnChainAlloc(node:PsrChain):Integer; var pLine:PspirvOp; @@ -1073,23 +865,22 @@ var begin Result:=1; - pIndex:=RegDown(node^.key.ext.pIndex); + pIndex:=RegDown(node^.pIndex); if (pIndex=nil) or (pIndex^.is_const) then begin pLine:=init_line; end else begin - pLine:=node^.rSlot.first^.pLine; + pLine:=node^.FirstLine; Assert(pLine<>nil); - pLine:=pLine^.pPrev; + pLine:=pLine^.Prev; Assert(pLine<>nil); end; pField:=node^.pField; Assert(pField<>nil); src:=pField^.pBuffer^.pVar; Assert(src<>nil); - src^.mark_read; - pLine:=TEmitOp(Self).emit_OpAccessChain(pLine,pField^.pType,node,src); + pLine:=OpAccessChain(pLine,pField^.pType,node,src); //dtype:=node^.GetRegType; //if (pField^.dtype<>dtype) then @@ -1098,34 +889,33 @@ begin // Assert(false,'TODO'); //end; - pParam:=pLine^.pParam.pTail; + pParam:=pLine^.ParamLast; repeat - Parent:=pField^.parent; + Parent:=pField^.pParent; if (Parent<>nil) then Case Parent^.dtype of dtTypeStruct: begin - pReg:=FetchReg(FConsts.Fetchi(dtUint32,pField^.FID)); - pLine^.AddParamAfter(pParam,ntReg,pReg); + pReg:=NewReg_i(dtUint32,pField^.FID,@pLine); + pLine^.AddParamAfter(pParam,pReg); end; dtTypeArray, dtTypeRuntimeArray: begin if not Parent^.IsStructNotUsed then begin - pReg:=FetchReg(FConsts.Fetchi(dtUint32,pField^.FID)); - pLine^.AddParamAfter(pParam,ntReg,pReg); + pReg:=NewReg_i(dtUint32,pField^.FID,@pLine); + pLine^.AddParamAfter(pParam,pReg); end; Assert(pIndex<>nil); - pIndex^.mark_read; - pLine^.AddParamAfter(pParam,ntReg,pIndex); + pLine^.AddParamAfter(pParam,pIndex); end; else - if IsVector(Parent^.dtype) then + if Parent^.dtype.isVector then begin - pReg:=FetchReg(FConsts.Fetchi(dtUint32,pField^.FID)); - pLine^.AddParamAfter(pParam,ntReg,pReg); + pReg:=NewReg_i(dtUint32,pField^.FID,@pLine); + pLine^.AddParamAfter(pParam,pReg); end; end; @@ -1139,158 +929,52 @@ var node:PsrConst; begin Result:=0; - node:=FConsts.FList.pTail; + node:=ConstList.FList.pTail; While (node<>nil) do begin - if (node^.read_count=0) then + if (not node^.IsUsed) then begin - node^.Clear; //delete links - FConsts.FList.Remove(node); //remove? + ConstList.FList.Remove(node); //remove? Inc(Result); - end else - if (node^.pType=nil) then - begin - node^.pType:=FSpirvTypes.Fetch(node^.key.dtype); - //Assert(node^.pTypeAlloc<>nil); end; - node:=node^.pPrev; + node:=node^.Prev; end; end; function TSprvEmit_post.PostVariableAnalize:Integer; var node:PsrVariable; - pType:PsrType; begin Result:=0; - node:=FVariables.pTail; + node:=VariableList.FList.pTail; While (node<>nil) do begin - if (node^.read_count=0) and (node^.write_count=0) then + if (not node^.IsUsed) then begin - node^.Clear; //delete links - FVariables.Remove(node); //remove? + VariableList.FList.Remove(node); //remove? Inc(Result); end else - if (node^.pType=nil) then begin - pType:=FSpirvTypes.Fetch(node^.dtype); - Assert(pType<>nil); - node^.pType:=FSpirvTypes.FetchPointer(pType,node^.GetStorageClass); + node^.UpdateType(Self); end; - node:=node^.pPrev; + node:=node^.Prev; end; end; -function TSprvEmit_post.PostTypeAnalize(first:Boolean):Integer; +function TSprvEmit_post.PostTypeAnalize:Integer; var node:PsrType; begin Result:=0; - node:=FSpirvTypes.FList.pTail; + node:=TypeList.FList.pTail; While (node<>nil) do begin - if (node^.read_count=0) then + if (not node^.IsUsed) then begin - node^.Clear; //delete links - FSpirvTypes.FList.Remove(node); //remove? + TypeList.FList.Remove(node); //remove? Inc(Result); - end else - begin - case node^.key.OpId of - - Op.OpTypeFloat: - begin - case node^.key.ext.float_size of - 16:AddCap(Capability.Float16); - 64:AddCap(Capability.Float64); - else; - end; - end; - - Op.OpTypeInt: - begin - case node^.key.ext.int_size of - 8:AddCap(Capability.Int8); - 16:AddCap(Capability.Int16); - 64:AddCap(Capability.Int64); - else; - end; - end; - - Op.OpTypeImage: - begin - - Case node^.key.ext.image.Dim of - Dim.Dim1D: - Case node^.key.ext.image.Sampled of - 0:; //runtime - 1:AddCap(Capability.Sampled1D); //sampling - 2:AddCap(Capability.Image1D); //read/write - else; - end; - Dim.Buffer: - Case node^.key.ext.image.Sampled of - 0:; //runtime - 1:AddCap(Capability.SampledBuffer); //sampling - 2:AddCap(Capability.ImageBuffer); //read/write - else; - end; - else; - end; - - if (node^.key.ext.image.Sampled=2) and - (node^.key.ext.image.Arrayed=1) then - begin - AddCap(Capability.ImageMSArray); - end; - - Case node^.key.ext.image.Format of - ImageFormat.Unknown :AddCap(Capability.StorageImageReadWithoutFormat); - - ImageFormat.Rg32f , - ImageFormat.Rg16f , - ImageFormat.R11fG11fB10f, - ImageFormat.R16f , - ImageFormat.Rgba16 , - ImageFormat.Rgb10A2 , - ImageFormat.Rg16 , - ImageFormat.Rg8 , - ImageFormat.R16 , - ImageFormat.R8 , - ImageFormat.Rgba16Snorm , - ImageFormat.Rg16Snorm , - ImageFormat.Rg8Snorm , - ImageFormat.R16Snorm , - ImageFormat.R8Snorm , - ImageFormat.Rg32i , - ImageFormat.Rg16i , - ImageFormat.Rg8i , - ImageFormat.R16i , - ImageFormat.R8i , - ImageFormat.Rgb10a2ui , - ImageFormat.Rg32ui , - ImageFormat.Rg16ui , - ImageFormat.Rg8ui , - ImageFormat.R16ui , - ImageFormat.R8ui :AddCap(Capability.StorageImageExtendedFormats); - - else; - end; - end; - - Op.OpTypeArray: - if not first then - begin - //make a const of count - if (node^.key.ext.array_count=0) then Assert(False); - FConsts.Fetchi(dtUInt32,node^.key.ext.array_count); //just increment - end; - - else; - end; end; - node:=node^.pPrev; + node:=node^.Prev; end; end; diff --git a/spirv/emit_post_op.pas b/spirv/emit_post_op.pas index 98f60884..7bfb7046 100644 --- a/spirv/emit_post_op.pas +++ b/spirv/emit_post_op.pas @@ -8,21 +8,20 @@ uses sysutils, bittype, Half16, - srLabel, - srNodes, + spirv, + srCFGLabel, + srNode, + srType, srTypes, srRefId, srConst, srReg, srOp, srOpUtils, - spirv, - SprvEmit, - emit_op, - emit_post; + emit_fetch; type - TEmitPostOp=object(TSprvEmit_post) + TEmitPostOp=class(TEmitFetch) function PostForward1(node:PSpirvOp):Integer; function PostForward2(node:PSpirvOp):Integer; // @@ -38,7 +37,10 @@ type function OnAbsDiff1(node:PSpirvOp):Integer; function OnWQM32__1(node:PSpirvOp):Integer; function OnPackOfs1(node:PSpirvOp):Integer; - function OnMakeCM1(node:PSpirvOp):Integer; + function _Fetch_PackAnc(node:PsrRegNode;index,count:Byte):PsrRegNode; + function OnBFEU32_1(node:PSpirvOp):Integer; + function OnBFIB32_1(node:PSpirvOp):Integer; + function OnMakeCub1(node:PSpirvOp):Integer; // function OnBitwiseAnd1(node:PSpirvOp):Integer; function OnLogicalAnd1(node:PSpirvOp):Integer; @@ -49,17 +51,16 @@ type // function OnSelect1(node:PSpirvOp):Integer; // - procedure MakeVecConst(rtype:TsrDataType;dst:PsrRegNode;count:Byte;src:PPsrRegNode); + procedure MakeVecConst(rtype:TsrDataType;dst:PsrRegNode;src:PPsrRegNode); procedure MakeVecOne(dst:PsrRegNode;src:PPsrRegNode); - function MakeVecComp(pLine:PSpirvOp;rtype:TsrDataType;dst:PsrRegNode;count:Byte;src:PPsrRegNode):PSpirvOp; + function MakeVecComp(pLine:PSpirvOp;rtype:TsrDataType;dst:PsrRegNode;src:PPsrRegNode):PSpirvOp; // function OnMakeVec2(node:PSpirvOp):Integer; function OnReturn_2(node:PSpirvOp):Integer; function OnMakeExp2(node:PSpirvOp):Integer; function OnIAddExt2(node:PSpirvOp):Integer; function OnISubExt2(node:PSpirvOp):Integer; - //function NewMED3F:PSpirvFunc; - //function OpMED3F__2(node:PSpirvOp):Integer; + function OnPackAnc2(node:PSpirvOp):Integer; end; implementation @@ -84,10 +85,12 @@ begin Op.OpShiftRightLogical, Op.OpShiftRightArithmetic:Result:=OnShr1(node); - OpAbsDiff :Result:=OnAbsDiff1(node); - OpWQM32 :Result:=OnWQM32__1(node); - OpPackOfs :Result:=OnPackOfs1(node); - OpMakeCM :Result:=OnMakeCM1(node); + srOpUtils.OpAbsDiff :Result:=OnAbsDiff1(node); + srOpUtils.OpWQM32 :Result:=OnWQM32__1(node); + srOpUtils.OpPackOfs :Result:=OnPackOfs1(node); + srOpUtils.OpBFEU32 :Result:=OnBFEU32_1(node); + srOpUtils.OpBFIB32 :Result:=OnBFIB32_1(node); + srOpUtils.OpMakeCub :Result:=OnMakeCub1(node); Op.OpSelect :Result:=OnSelect1(node); @@ -110,13 +113,11 @@ begin Case node^.OpId of - //Op.OpIAdd :Result:=OnIAdd1(node); - //Op.OpISub :Result:=OnISub1(node); + srOpUtils.OpIAddExt:Result:=OnIAddExt2(node); + srOpUtils.OpISubExt:Result:=OnISubExt2(node); + srOpUtils.OpMakeVec:Result:=OnMakeVec2(node); - OpIAddExt:Result:=OnIAddExt2(node); - OpISubExt:Result:=OnISubExt2(node); - OpMakeVec:Result:=OnMakeVec2(node); - //OpMED3F :Result:=OpMED3F__2(node); + srOpUtils.OpPackAnc:Result:=OnPackAnc2(node); Op.OpReturn:Result:=OnReturn_2(node); OpMakeExp :Result:=OnMakeExp2(node); @@ -136,7 +137,7 @@ begin begin Result:=0; end else - if (value=GetTypeHigh(dtype)) then //always true + if (value=dtype.High) then //always true begin Result:=1; end else @@ -147,7 +148,7 @@ end; function _classif_const(p:PsrConst):Integer; begin - Result:=_classif_const(p^.key.dtype,p^.GetData); + Result:=_classif_const(p^.dtype,p^.GetData); end; function BinType(t:TsrDataType):TsrDataType; @@ -170,18 +171,17 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin - dst^.SetConst(FConsts.Fetch(dtype,value)); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=ConstList.Fetch(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; procedure _SetReg(src:PsrRegNode); begin - src^.mark_read; - dst^.SetReg(src); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=src; + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; @@ -193,38 +193,29 @@ var node^.OpId:=OpId; Inc(Result); end; - Result:=Result+PrepTypeDst(node^.dst.pData,dtype); - dst:=node^.dst.pData; + dst:=node^.pDst^.AsType(ntReg); + Result:=Result+PrepTypeDst(dst,dtype); + node^.pDst:=dst; // dtype:=dst^.dtype; - if (node^.dst_type<>nil) then - begin - node^.dst_type^.mark_unread; - end; - node^.dst_type:=FSpirvTypes.Fetch(dtype); + node^.pType:=TypeList.Fetch(dtype); end; procedure _SetType(dtype:TsrDataType); begin - Result:=Result+PrepTypeDst(node^.dst.pData,dtype); - dst:=node^.dst.pData; + dst:=node^.pDst^.AsType(ntReg); + Result:=Result+PrepTypeDst(dst,dtype); + node^.pDst:=dst; // dtype:=dst^.dtype; - if (node^.dst_type<>nil) then - begin - node^.dst_type^.mark_unread; - end; - node^.dst_type:=FSpirvTypes.Fetch(dtype); + node^.pType:=TypeList.Fetch(dtype); end; begin Result:=0; - dst:=node^.dst.AsReg; - src[0]:=node^.ParamNode(0)^.AsReg; - src[1]:=node^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + dst:=node^.pDst^.AsType(ntReg); + src[0]:=RegDown(node^.ParamNode(0)^.AsReg); + src[1]:=RegDown(node^.ParamNode(1)^.AsReg); if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; @@ -245,7 +236,7 @@ begin if (src[0]^.is_const) then begin Case src[0]^.AsConst^.AsBool of - True :_SetReg(node^.ParamNode(1)^.pData); + True :_SetReg(src[1]); False:_SetConst(dtBool,0); end; Exit; @@ -253,7 +244,7 @@ begin if (src[1]^.is_const) then begin Case src[1]^.AsConst^.AsBool of - True :_SetReg(node^.ParamNode(0)^.pData); + True :_SetReg(src[0]); False:_SetConst(dtBool,0); end; Exit; @@ -269,14 +260,14 @@ begin begin case _classif_const(src[0]^.AsConst) of 0:_SetConst(dtype,0); //always false - 1:_SetReg(node^.ParamNode(1)^.pData); //always true + 1:_SetReg(src[1]); //always true end; end; if (src[1]^.is_const) then begin case _classif_const(src[1]^.AsConst) of 0:_SetConst(dtype,0); //always false - 1:_SetReg(node^.ParamNode(0)^.pData); //always true + 1:_SetReg(src[0]); //always true end; end; @@ -298,17 +289,15 @@ begin repeat - p:=node^.AsOp; + p:=node^.pWriter^.AsType(ntOp); if (p<>nil) then if (p^.OpId=Op.OpLogicalAnd) then begin - tmp:=p^.ParamNode(0)^.AsReg; - tmp:=RegDown(tmp); + tmp:=RegDown(p^.ParamNode(0)^.AsReg); if (tmp=src) then Exit(True); Result:=_FindNest_LAnd(tmp,src); //recursion if Result then Exit(True); - tmp:=p^.ParamNode(1)^.AsReg; - tmp:=RegDown(tmp); + tmp:=RegDown(p^.ParamNode(1)^.AsReg); if (tmp=src) then Exit(True); node:=tmp; Continue; //cycle @@ -327,29 +316,25 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin - dst^.SetConst(FConsts.Fetch(dtype,value)); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=ConstList.Fetch(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; procedure _SetReg(src:PsrRegNode); begin - src^.mark_read; - dst^.SetReg(src); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=src; + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; begin Result:=0; - dst:=node^.dst.AsReg; - src[0]:=node^.ParamNode(0)^.AsReg; - src[1]:=node^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + dst:=node^.pDst^.AsType(ntReg); + src[0]:=RegDown(node^.ParamNode(0)^.AsReg); + src[1]:=RegDown(node^.ParamNode(1)^.AsReg); if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; @@ -366,7 +351,7 @@ begin if (src[0]^.is_const) then begin Case src[0]^.AsConst^.AsBool of - True :_SetReg(node^.ParamNode(1)^.pData); + True :_SetReg(src[1]); False:_SetConst(dtBool,0); end; Exit; @@ -374,7 +359,7 @@ begin if (src[1]^.is_const) then begin Case src[1]^.AsConst^.AsBool of - True :_SetReg(node^.ParamNode(0)^.pData); + True :_SetReg(src[0]); False:_SetConst(dtBool,0); end; Exit; @@ -382,13 +367,13 @@ begin if _FindNest_LAnd(src[1],src[0]) then //Find src[0] in src[1] begin - _SetReg(node^.ParamNode(1)^.pData); + _SetReg(src[1]); Exit; end; if _FindNest_LAnd(src[0],src[1]) then //Find src[1] in src[0] begin - _SetReg(node^.ParamNode(0)^.pData); + _SetReg(src[0]); Exit; end; @@ -396,6 +381,62 @@ begin Result:=Result+PrepTypeParam(node^.ParamNode(1),dtBool); end; +function _Fetch_BitwiseOr_Const(node:PsrRegNode):PsrConst; +var + pLine:PSpirvOp; + src:array[0..1] of PsrRegNode; +begin + Result:=nil; + if (node=nil) then Exit; + pLine:=node^.pWriter^.AsType(ntOp); + if (pLine=nil) then Exit; + if (pLine^.OpId<>Op.OpBitwiseOr) then Exit; + + src[0]:=RegDown(pLine^.ParamNode(0)^.AsReg); + src[1]:=RegDown(pLine^.ParamNode(1)^.AsReg); + + if (src[0]=nil) or (src[1]=nil) then Exit; + + if src[0]^.is_const and src[1]^.is_const then Exit; + + if src[0]^.is_const then + begin + Result:=src[0]^.AsConst; + end else + if src[1]^.is_const then + begin + Result:=src[1]^.AsConst; + end; +end; + +function _Fetch_BitwiseOr_Value(node:PsrRegNode):PsrRegNode; +var + pLine:PSpirvOp; + src:array[0..1] of PsrRegNode; +begin + Result:=nil; + if (node=nil) then Exit; + pLine:=node^.pWriter^.AsType(ntOp); + if (pLine=nil) then Exit; + if (pLine^.OpId<>Op.OpBitwiseOr) then Exit; + + src[0]:=RegDown(pLine^.ParamNode(0)^.AsReg); + src[1]:=RegDown(pLine^.ParamNode(1)^.AsReg); + + if (src[0]=nil) or (src[1]=nil) then Exit; + + if src[0]^.is_const and src[1]^.is_const then Exit; + + if src[0]^.is_const then + begin + Result:=src[1]; + end else + if src[1]^.is_const then + begin + Result:=src[0]; + end; +end; + // function TEmitPostOp.OnBitwiseOr1(node:PSpirvOp):Integer; @@ -405,20 +446,21 @@ var src:array[0..1] of PsrRegNode; data:array[0..1] of QWORD; + pConst:PsrConst; + procedure _SetConst(dtype:TsrDataType;value:QWORD); begin - dst^.SetConst(FConsts.Fetch(dtype,value)); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=ConstList.Fetch(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; procedure _SetReg(src:PsrRegNode); begin - src^.mark_read; - dst^.SetReg(src); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=src; + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; @@ -430,38 +472,29 @@ var node^.OpId:=OpId; Inc(Result); end; - Result:=Result+PrepTypeDst(node^.dst.pData,dtype); - dst:=node^.dst.pData; + dst:=node^.pDst^.AsType(ntReg); + Result:=Result+PrepTypeDst(dst,dtype); + node^.pDst:=dst; // dtype:=dst^.dtype; - if (node^.dst_type<>nil) then - begin - node^.dst_type^.mark_unread; - end; - node^.dst_type:=FSpirvTypes.Fetch(dtype); + node^.pType:=TypeList.Fetch(dtype); end; procedure _SetType(dtype:TsrDataType); begin - Result:=Result+PrepTypeDst(node^.dst.pData,dtype); - dst:=node^.dst.pData; + dst:=node^.pDst^.AsType(ntReg); + Result:=Result+PrepTypeDst(dst,dtype); + node^.pDst:=dst; // dtype:=dst^.dtype; - if (node^.dst_type<>nil) then - begin - node^.dst_type^.mark_unread; - end; - node^.dst_type:=FSpirvTypes.Fetch(dtype); + node^.pType:=TypeList.Fetch(dtype); end; begin Result:=0; - dst:=node^.dst.AsReg; - src[0]:=node^.ParamNode(0)^.AsReg; - src[1]:=node^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + dst:=node^.pDst^.AsType(ntReg); + src[0]:=RegDown(node^.ParamNode(0)^.AsReg); + src[1]:=RegDown(node^.ParamNode(1)^.AsReg); if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; @@ -483,7 +516,7 @@ begin begin Case src[0]^.AsConst^.AsBool of True :_SetConst(dtBool,1); - False:_SetReg(node^.ParamNode(1)^.pData); + False:_SetReg(src[1]); end; Exit; end; @@ -491,13 +524,56 @@ begin begin Case src[1]^.AsConst^.AsBool of True :_SetConst(dtBool,1); - False:_SetReg(node^.ParamNode(0)^.pData); + False:_SetReg(src[0]); end; Exit; end; _SetOpType(Op.OpLogicalOr,dtBool); - end else + + Result:=Result+PrepTypeParam(node^.ParamNode(0),dst^.dtype); + Result:=Result+PrepTypeParam(node^.ParamNode(1),dst^.dtype); + + Exit; + end; + + // + pConst:=_Fetch_BitwiseOr_Const(src[0]); + if (pConst<>nil) and src[1]^.is_const then + begin + //need a const calc + data[0]:= pConst^.GetData; + data[1]:=src[1]^.AsConst^.GetData; + + dtype:=LazyType3(dst^.dtype,src[0]^.dtype,src[1]^.dtype); + src[1]:=NewReg_q(dtype,data[0] or data[1],@Node); + + src[0]:=_Fetch_BitwiseOr_Value(src[0]); + Assert(src[0]<>nil); + + node^.ParamNode(0)^.Value:=src[0]; + node^.ParamNode(1)^.Value:=src[1]; + end; + + // + pConst:=_Fetch_BitwiseOr_Const(src[1]); + if src[0]^.is_const and (pConst<>nil) then + begin + //need a const calc + data[0]:=src[0]^.AsConst^.GetData; + data[1]:= pConst^.GetData; + + dtype:=LazyType3(dst^.dtype,src[0]^.dtype,src[1]^.dtype); + src[0]:=NewReg_q(dtype,data[0] or data[1],@Node); + + src[1]:=_Fetch_BitwiseOr_Value(src[1]); + Assert(src[1]<>nil); + + node^.ParamNode(0)^.Value:=src[0]; + node^.ParamNode(1)^.Value:=src[1]; + end; + + //else begin dtype:=LazyType3(BinType(dst^.dtype),BinType(src[0]^.dtype),BinType(src[1]^.dtype)); dtype:=LazyType2(dtype,dtUint32); @@ -505,15 +581,15 @@ begin if (src[0]^.is_const) then begin case _classif_const(src[0]^.AsConst) of - 0:_SetReg(node^.ParamNode(1)^.pData); - 1:_SetConst(dtype,GetTypeHigh(dtype)); //is high + 0:_SetReg(src[1]); + 1:_SetConst(dtype,dtype.High); //is high end; end; if (src[1]^.is_const) then begin case _classif_const(src[1]^.AsConst) of - 0:_SetReg(node^.ParamNode(0)^.pData); - 1:_SetConst(dtype,GetTypeHigh(dtype)); //is high + 0:_SetReg(src[0]); + 1:_SetConst(dtype,dtype.High); //is high end; end; @@ -533,29 +609,25 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin - dst^.SetConst(FConsts.Fetch(dtype,value)); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=ConstList.Fetch(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; procedure _SetReg(src:PsrRegNode); begin - src^.mark_read; - dst^.SetReg(src); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=src; + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; begin Result:=0; - dst:=node^.dst.AsReg; - src[0]:=node^.ParamNode(0)^.AsReg; - src[1]:=node^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + dst:=node^.pDst^.AsType(ntReg); + src[0]:=RegDown(node^.ParamNode(0)^.AsReg); + src[1]:=RegDown(node^.ParamNode(1)^.AsReg); if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; @@ -573,7 +645,7 @@ begin begin Case src[0]^.AsConst^.AsBool of True :_SetConst(dtBool,1); - False:_SetReg(node^.ParamNode(1)^.pData); + False:_SetReg(src[1]); end; Exit; end; @@ -581,7 +653,7 @@ begin begin Case src[1]^.AsConst^.AsBool of True :_SetConst(dtBool,1); - False:_SetReg(node^.ParamNode(0)^.pData); + False:_SetReg(src[0]); end; Exit; end; @@ -599,9 +671,9 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin - dst^.SetConst(FConsts.Fetch(dtype,value)); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=ConstList.Fetch(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; @@ -613,35 +685,29 @@ var node^.OpId:=OpId; Inc(Result); end; - Result:=Result+PrepTypeDst(node^.dst.pData,dtype); - dst:=node^.dst.pData; + dst:=node^.pDst^.AsType(ntReg); + Result:=Result+PrepTypeDst(dst,dtype); + node^.pDst:=dst; // dtype:=dst^.dtype; - if (node^.dst_type<>nil) then - begin - node^.dst_type^.mark_unread; - end; - node^.dst_type:=FSpirvTypes.Fetch(dtype); + node^.pType:=TypeList.Fetch(dtype); end; procedure _SetType(dtype:TsrDataType); begin - Result:=Result+PrepTypeDst(node^.dst.pData,dtype); - dst:=node^.dst.pData; + dst:=node^.pDst^.AsType(ntReg); + Result:=Result+PrepTypeDst(dst,dtype); + node^.pDst:=dst; // dtype:=dst^.dtype; - if (node^.dst_type<>nil) then - begin - node^.dst_type^.mark_unread; - end; - node^.dst_type:=FSpirvTypes.Fetch(dtype); + node^.pType:=TypeList.Fetch(dtype); end; begin Result:=0; - dst:=node^.dst.AsReg; - src:=node^.ParamNode(0)^.AsReg; - src:=RegDown(src); + dst:=node^.pDst^.AsType(ntReg); + src:=RegDown(node^.ParamNode(0)^.AsReg); + if (dst=nil) or (src=nil) then Exit; if src^.is_const then @@ -650,7 +716,7 @@ begin //need a const calc data[0]:=src^.AsConst^.GetData; - data[1]:=GetTypeHigh(dtype); + data[1]:=dtype.High; _SetConst(dtype,(not data[0]) and data[1]); Exit; @@ -681,21 +747,20 @@ end; function TEmitPostOp.OnBranchConditional1(node:PSpirvOp):Integer; var - cur,src,prv:PsrRegNode; + src,prv:PsrRegNode; pOp:PSpirvOp; - pLabel:array[0..1] of PsrRefId; + pLabel:array[0..1] of PsrRefNode; begin Result:=0; - cur:=node^.ParamNode(0)^.AsReg; - if (cur=nil) then Exit; - src:=RegDown(cur); + src:=RegDown(node^.ParamNode(0)^.AsReg); - pOp:=src^.AsOp; + if (src=nil) then Exit; + + pOp:=src^.pWriter^.AsType(ntOp); if (pOp=nil) then Exit; Case pOp^.OpId of Op.OpLogicalNot:; - //Op.OpNot:; else Exit; end; @@ -703,16 +768,13 @@ begin prv:=pOp^.ParamNode(0)^.AsReg; if (prv=nil) then Exit; - node^.ParamNode(0)^.pData:=prv; //set new + node^.ParamNode(0)^.Value:=prv; //set new - pLabel[0]:=node^.ParamNode(1)^.pData; //read - pLabel[1]:=node^.ParamNode(2)^.pData; //read + pLabel[0]:=node^.ParamNode(1)^.Value^.AsType(ntRefId); //read + pLabel[1]:=node^.ParamNode(2)^.Value^.AsType(ntRefId); //read - node^.ParamNode(1)^.pData:=pLabel[1]; //swap - node^.ParamNode(2)^.pData:=pLabel[0]; //swap - - prv^.mark_read; - RegUnmark(cur); + node^.ParamNode(1)^.Value:=pLabel[1]; //swap + node^.ParamNode(2)^.Value:=pLabel[0]; //swap Inc(Result); end; @@ -727,30 +789,26 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin - dst^.SetConst(FConsts.Fetch(dtype,value)); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=ConstList.Fetch(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; - procedure _SetConst(dtype:TsrDataType;value:double); + procedure _SetConst_s(dtype:TsrDataType;value:Single); begin - Case dtype of - dtFloat32:dst^.SetConst(FConsts.Fetchf(dtype,value)); - else - Assert(false,'TODO'); - end; - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + Assert(dtype=dtFloat32); + dst^.pWriter:=ConstList.Fetch_s(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; procedure _SetReg(src:PsrRegNode); begin - src^.mark_read; - dst^.SetReg(src); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=src; + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; @@ -761,9 +819,9 @@ var begin Result:=0; - dst:=node^.dst.AsReg; - src:=node^.ParamNode(0)^.AsReg; - src:=RegDown(src); + dst:=node^.pDst^.AsType(ntReg); + src:=RegDown(node^.ParamNode(0)^.AsReg); + if (dst=nil) or (src=nil) then Exit; tmp:=src; @@ -774,11 +832,7 @@ begin if (tmp<>src) then begin - src:=node^.ParamNode(0)^.AsReg; - tmp^.mark_read; - node^.ParamNode(0)^.ntype:=ntReg; - node^.ParamNode(0)^.pData:=tmp; - src^.mark_unread; + node^.ParamNode(0)^.Value:=tmp; src:=tmp; Inc(Result); end; @@ -797,7 +851,7 @@ begin end; dtHalf16: case dst^.dtype of - dtFloat32:_SetConst(dst^.dtype,Single(pc^.AsHalf16)); + dtFloat32:_SetConst_s(dst^.dtype,Single(pc^.AsHalf16)); else; end; else; @@ -817,35 +871,34 @@ begin Op.OpConvertSToF: case src^.dtype of - dtInt32 :_SetConst(dst^.dtype,double(pc^.AsInt)); - dtUint32:_SetConst(dst^.dtype,double(pc^.AsInt)); + dtInt32 :_SetConst_s(dst^.dtype,pc^.AsInt32); + dtUint32:_SetConst_s(dst^.dtype,pc^.AsInt32); - dtInt64 :_SetConst(dst^.dtype,double(pc^.AsInt64)); - dtUint64:_SetConst(dst^.dtype,double(pc^.AsInt64)); + dtInt64 :_SetConst_s(dst^.dtype,pc^.AsInt64); + dtUint64:_SetConst_s(dst^.dtype,pc^.AsInt64); else; end; Op.OpConvertUToF: case src^.dtype of - dtInt32 :_SetConst(dst^.dtype,double(pc^.AsUint)); - dtUint32:_SetConst(dst^.dtype,double(pc^.AsUint)); + dtInt32 :_SetConst_s(dst^.dtype,pc^.AsUint32); + dtUint32:_SetConst_s(dst^.dtype,pc^.AsUint32); - dtInt64 :_SetConst(dst^.dtype,double(pc^.AsUint64)); - dtUint64:_SetConst(dst^.dtype,double(pc^.AsUint64)); + dtInt64 :_SetConst_s(dst^.dtype,pc^.AsUint64); + dtUint64:_SetConst_s(dst^.dtype,pc^.AsUint64); else; end; end; end else begin - pLine:=src^.AsOp; + pLine:=src^.pWriter^.AsType(ntOp); if (pLine=nil) then Exit; Case pLine^.OpId of Op.OpFConvert: begin - tmp:=pLine^.ParamNode(0)^.AsReg; - tmp:=RegDown(tmp); + tmp:=RegDown(pLine^.ParamNode(0)^.AsReg); Case node^.OpId of Op.OpFConvert: @@ -868,27 +921,27 @@ function TEmitPostOp.OnCompositeExtract1(node:PSpirvOp):Integer; var pc:PsrConst; dst,src:PsrRegNode; - pos:DWORD; + pos:PtrUint; begin Result:=0; - dst:=node^.dst.AsReg; - src:=node^.ParamNode(0)^.AsReg; - src:=RegDown(src); + dst:=node^.pDst^.AsType(ntReg); + src:=RegDown(node^.ParamNode(0)^.AsReg); + if (dst=nil) or (src=nil) then Exit; + pos:=0; if not node^.ParamNode(1)^.TryGetValue(pos) then Exit; if src^.is_const then begin pc:=src^.AsConst; - if (posdtype) then begin - dtype:=LazyType3(dst^.dtype,src[0]^.dtype,src[1]^.dtype); - node^.dst_type:=FSpirvTypes.Fetch(dtype); - Result:=Result+PrepTypeDst(node^.dst.pData,dtype); - dst:=node^.dst.pData; - Inc(Result); + node^.pType:=TypeList.Fetch(dtype); + if (node^.pType^.dtype=dtype) then + begin + Inc(Result); + end; + end; + + if (dst^.dtype<>dtype) then + begin + Result:=Result+PrepTypeDst(dst,dtype); + node^.pDst:=dst; end; Result:=Result+PrepTypeParam(node^.ParamNode(1),dst^.dtype); @@ -961,26 +1023,20 @@ var src:array[0..1] of PsrRegNode; pCon:array[0..1] of PsrConst; - procedure _SetConst(dtype:TsrDataType;value:Single); + procedure _SetConst_s(dtype:TsrDataType;value:Single); begin - Case dtype of - dtFloat32:dst^.SetConst(FConsts.Fetchf(dtype,value)); - else - Assert(false,'TODO'); - end; - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + Assert(dtype=dtFloat32); + dst^.pWriter:=ConstList.Fetch_s(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; begin Result:=0; - dst:=node^.dst.AsReg; - src[0]:=node^.ParamNode(0)^.AsReg; - src[1]:=node^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + dst:=node^.pDst^.AsType(ntReg); + src[0]:=RegDown(node^.ParamNode(0)^.AsReg); + src[1]:=RegDown(node^.ParamNode(1)^.AsReg); if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; @@ -995,7 +1051,7 @@ begin Case src[0]^.dtype of dtFloat32: begin - _SetConst(dst^.dtype,pCon[0]^.AsFloat32/pCon[1]^.AsFloat32); + _SetConst_s(dst^.dtype,pCon[0]^.AsFloat32/pCon[1]^.AsFloat32); end; else; end; @@ -1011,29 +1067,25 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin - dst^.SetConst(FConsts.Fetch(dtype,value)); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=ConstList.Fetch(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; procedure _SetReg(src:PsrRegNode); begin - src^.mark_read; - dst^.SetReg(src); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=src; + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; begin Result:=0; - dst:=node^.dst.AsReg; - src[0]:=node^.ParamNode(0)^.AsReg; - src[1]:=node^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + dst:=node^.pDst^.AsType(ntReg); + src[0]:=RegDown(node^.ParamNode(0)^.AsReg); + src[1]:=RegDown(node^.ParamNode(1)^.AsReg); if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; @@ -1069,20 +1121,17 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin - dst^.SetConst(FConsts.Fetch(dtype,value)); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=ConstList.Fetch(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; begin Result:=0; - dst:=node^.dst.AsReg; - src[0]:=node^.ParamNode(0)^.AsReg; - src[1]:=node^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + dst:=node^.pDst^.AsType(ntReg); + src[0]:=RegDown(node^.ParamNode(0)^.AsReg); + src[1]:=RegDown(node^.ParamNode(1)^.AsReg); if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; @@ -1104,20 +1153,17 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin - dst^.SetConst(FConsts.Fetch(dtype,value)); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=ConstList.Fetch(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; begin Result:=0; - dst:=node^.dst.AsReg; - src[0]:=node^.ParamNode(0)^.AsReg; - src[1]:=node^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + dst:=node^.pDst^.AsType(ntReg); + src[0]:=RegDown(node^.ParamNode(0)^.AsReg); + src[1]:=RegDown(node^.ParamNode(1)^.AsReg); if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; @@ -1131,7 +1177,7 @@ begin end else if (src[1]^.is_const) then begin - Result:=_OnShr_ext1(node,src[0]^.AsOp,src[1]^.AsConst); + Result:=_OnShr_ext1(node,src[0]^.pWriter^.AsType(ntOp),src[1]^.AsConst); end; end; @@ -1146,11 +1192,8 @@ begin Case pOp^.OpId of Op.OpBitwiseAnd: begin - src[0]:=pOp^.ParamNode(0)^.AsReg; - src[1]:=pOp^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + src[0]:=RegDown(pOp^.ParamNode(0)^.AsReg); + src[1]:=RegDown(pOp^.ParamNode(1)^.AsReg); if (src[0]=nil) or (src[1]=nil) then Exit; @@ -1166,15 +1209,12 @@ begin Op.OpIAdd: begin - src[0]:=pOp^.ParamNode(0)^.AsReg; - src[1]:=pOp^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + src[0]:=RegDown(pOp^.ParamNode(0)^.AsReg); + src[1]:=RegDown(pOp^.ParamNode(1)^.AsReg); if (src[0]=nil) or (src[1]=nil) then Exit; - Result:=_OnShr_ext_add(node,src[0]^.AsOp,src[1]^.AsOp,pShrVal); + Result:=_OnShr_ext_add(node,src[0]^.pWriter^.AsType(ntOp),src[1]^.pWriter^.AsType(ntOp),pShrVal); end; else; @@ -1189,9 +1229,9 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin - dst^.SetConst(FConsts.Fetch(dtype,value)); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=ConstList.Fetch(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; @@ -1204,7 +1244,7 @@ begin if (data[0] and data[1]=0) then begin - dst:=node^.dst.AsReg; + dst:=node^.pDst^.AsType(ntReg); _SetConst(dst^.dtype,0); end; end; @@ -1230,11 +1270,8 @@ begin Case pOp^.OpId of Op.OpIMul: begin - src[0]:=pOp^.ParamNode(0)^.AsReg; - src[1]:=pOp^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + src[0]:=RegDown(pOp^.ParamNode(0)^.AsReg); + src[1]:=RegDown(pOp^.ParamNode(1)^.AsReg); if (src[0]=nil) or (src[1]=nil) then Exit; @@ -1261,11 +1298,8 @@ begin Op.OpShiftLeftLogical: begin - src[0]:=pOp^.ParamNode(0)^.AsReg; - src[1]:=pOp^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + src[0]:=RegDown(pOp^.ParamNode(0)^.AsReg); + src[1]:=RegDown(pOp^.ParamNode(1)^.AsReg); if (src[0]=nil) or (src[1]=nil) then Exit; @@ -1293,11 +1327,8 @@ begin Case pOp^.OpId of Op.OpIMul: begin - src[0]:=pOp^.ParamNode(0)^.AsReg; - src[1]:=pOp^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + src[0]:=RegDown(pOp^.ParamNode(0)^.AsReg); + src[1]:=RegDown(pOp^.ParamNode(1)^.AsReg); if (src[0]=nil) or (src[1]=nil) then Exit; @@ -1313,11 +1344,8 @@ begin Op.OpShiftLeftLogical: begin - src[0]:=pOp^.ParamNode(0)^.AsReg; - src[1]:=pOp^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + src[0]:=RegDown(pOp^.ParamNode(0)^.AsReg); + src[1]:=RegDown(pOp^.ParamNode(1)^.AsReg); if (src[0]=nil) or (src[1]=nil) then Exit; @@ -1336,14 +1364,12 @@ var procedure _SetReg(src:PsrRegNode); begin - src^.mark_read; - dst^.SetReg(src); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=src; + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; - begin Result:=0; data[0]:=0; @@ -1357,11 +1383,10 @@ begin dst_shr[0]:=_GetShrOptReg(pOp0); end else begin - dst:=pOp0^.dst.AsReg; - dst_shr[0]:=NewReg(dst^.dtype); + dst:=pOp0^.pDst^.AsType(ntReg); + src:=_GetShrOptReg(pOp0); - src^.mark_read; - _emit_OpShl(pOp0,dst_shr[0],src,FetchReg(FConsts.Fetch(dst^.dtype,data[0]))); + dst_shr[0]:=OpShlTo(src,data[0],@pOp0) end; if (data[1]=0) then @@ -1369,21 +1394,17 @@ begin dst_shr[1]:=_GetShrOptReg(pOp1); end else begin - dst:=pOp1^.dst.AsReg; - dst_shr[1]:=NewReg(dst^.dtype); + dst:=pOp1^.pDst^.AsType(ntReg); + src:=_GetShrOptReg(pOp1); - src^.mark_read; - _emit_OpShl(pOp1,dst_shr[1],src,FetchReg(FConsts.Fetch(dst^.dtype,data[1]))); + dst_shr[1]:=OpShlTo(src,data[1],@pOp0) end; - dst:=node^.dst.AsReg; - pOp0:=dst^.AsOp; //OpIAdd - src:=NewReg(dst^.dtype); + dst:=node^.pDst^.AsType(ntReg); + pOp0:=dst^.pWriter^.AsType(ntOp); //OpIAdd - dst_shr[0]^.mark_read; - dst_shr[1]^.mark_read; - _emit_OpIAdd(pOp0,src,dst_shr[0],dst_shr[1]); + src:=OpIAddTo(dst_shr[0],dst_shr[1],@pOp0); _SetReg(src); //Writeln(data[0],' ',data[1]); @@ -1400,20 +1421,25 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin - dst^.SetConst(FConsts.Fetch(dtype,value)); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=ConstList.Fetch(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; + Inc(Result); + end; + + procedure _SetReg(src:PsrRegNode); + begin + dst^.pWriter:=src; + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; begin Result:=0; - dst:=node^.dst.AsReg; - src[0]:=node^.ParamNode(0)^.AsReg; - src[1]:=node^.ParamNode(1)^.AsReg; - - src[0]:=RegDown(src[0]); - src[1]:=RegDown(src[1]); + dst:=node^.pDst^.AsType(ntReg); + src[0]:=RegDown(node^.ParamNode(0)^.AsReg); + src[1]:=RegDown(node^.ParamNode(1)^.AsReg); if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; @@ -1427,28 +1453,38 @@ begin _SetConst(dst^.dtype,data[0]-data[1]) else _SetConst(dst^.dtype,data[1]-data[0]); + Exit; end else + if src[0]^.is_const then begin - src[0]:=node^.ParamNode(0)^.AsReg; //get original - src[1]:=node^.ParamNode(1)^.AsReg; //get original - - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); - - rmax:=NewReg(dst^.dtype); - src[0]^.mark_read; - src[1]^.mark_read; - node:=_emit_OpUMax(node,rmax,src[0],src[1]); - - rmin:=NewReg(dst^.dtype); - src[0]^.mark_read; - src[1]^.mark_read; - node:=_emit_OpUMin(node,rmin,src[0],src[1]); - - rmax^.mark_read; - rmin^.mark_read; - node:=_emit_OpISub(node,dst,rmax,rmin); + if src[0]^.AsConst^.isZeroVal then + begin + //src[1]-0 + src[1]:=node^.ParamNode(1)^.AsReg; //get original + _SetReg(src[1]); + Exit; + end; + end else + if src[1]^.is_const then + begin + if src[1]^.AsConst^.isZeroVal then + begin + //src[0]-0 + src[0]:=node^.ParamNode(0)^.AsReg; //get original + _SetReg(src[0]); + Exit; + end; end; + + //else + + node^.mark_not_used; + node^.pDst:=nil; + + rmax:=OpUMaxTo(src[0],src[1],@node); //update line + rmin:=OpUMinTo(src[0],src[1],@node); //update line + + _Op2(node,Op.OpISub,dst,rmax,rmin); end; function F_WQM_32(D:DWORD):DWORD; @@ -1474,26 +1510,25 @@ var procedure _SetConst(dtype:TsrDataType;value:QWORD); begin - dst^.SetConst(FConsts.Fetch(dtype,value)); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=ConstList.Fetch(dtype,value); + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; procedure _SetReg(src:PsrRegNode); begin - src^.mark_read; - dst^.SetReg(src); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=src; + node^.mark_not_used; + node^.pDst:=nil; Inc(Result); end; begin Result:=0; - dst:=node^.dst.AsReg; - src:=node^.ParamNode(0)^.AsReg; - src:=RegDown(src); + dst:=node^.pDst^.AsType(ntReg); + src:=RegDown(node^.ParamNode(0)^.AsReg); + if (dst=nil) or (src=nil) then Exit; if src^.is_const then @@ -1537,26 +1572,21 @@ var data:QWORD; P:Ppacked_offset; - rtype:TsrDataType; - count:DWORD; + count:PtrUint; ret:PsrConst; vec:array[0..2] of PsrConst; begin Result:=0; - dst:=node^.dst.AsReg; + dst:=node^.pDst^.AsType(ntReg); if (dst=nil) then Exit; count:=0; if not node^.ParamNode(0)^.TryGetValue(count) then Exit; - rtype:=TsrDataType(count); - count:=0; - if not node^.ParamNode(1)^.TryGetValue(count) then Exit; + src:=RegDown(node^.ParamNode(1)^.AsReg); - src:=node^.ParamNode(2)^.AsReg; - src:=RegDown(src); if (src=nil) then Exit; if src^.is_const then @@ -1569,30 +1599,32 @@ begin Case count of 1: begin - ret:=FConsts.Fetchi(dtInt32,int6(P^.x)); + ret:=ConstList.Fetch_i(dtInt32,int6(P^.x)); end; 2: begin - vec[0]:=FConsts.Fetchi(dtInt32,int6(P^.x)); - vec[1]:=FConsts.Fetchi(dtInt32,int6(P^.y)); + vec[0]:=ConstList.Fetch_i(dtInt32,int6(P^.x)); + vec[1]:=ConstList.Fetch_i(dtInt32,int6(P^.y)); - ret:=FConsts.Fetch_vec(dtVec2i,2,@vec); + ret:=ConstList.FetchVector(dtVec2i,@vec,true); end; 3: begin - vec[0]:=FConsts.Fetchi(dtInt32,int6(P^.x)); - vec[1]:=FConsts.Fetchi(dtInt32,int6(P^.y)); - vec[2]:=FConsts.Fetchi(dtInt32,int6(P^.z)); + vec[0]:=ConstList.Fetch_i(dtInt32,int6(P^.x)); + vec[1]:=ConstList.Fetch_i(dtInt32,int6(P^.y)); + vec[2]:=ConstList.Fetch_i(dtInt32,int6(P^.z)); - ret:=FConsts.Fetch_vec(dtVec3i,3,@vec); + ret:=ConstList.FetchVector(dtVec3i,@vec,true); end; else Assert(False); end; - dst^.SetConst(ret); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + dst^.pWriter:=ret; + + node^.mark_not_used; + node^.pDst:=nil; + Inc(Result); end else begin @@ -1600,9 +1632,247 @@ begin end; end; +//////// + +function TEmitPostOp._Fetch_PackAnc(node:PsrRegNode;index,count:Byte):PsrRegNode; +var + pLine:PSpirvOp; + src:array[0..2] of PsrRegNode; + prim,smid,rtid:Boolean; +begin + Result:=nil; + + if (node=nil) then Exit; + if (count=0) then Exit; + + pLine:=node^.pWriter^.AsType(ntOp); + if (pLine=nil) then Exit; + if (pLine^.OpId<>srOpUtils.OpPackAnc) then Exit; + + src[0]:=pLine^.ParamNode(0)^.AsReg; + src[1]:=pLine^.ParamNode(1)^.AsReg; + src[2]:=pLine^.ParamNode(2)^.AsReg; + + if (src[0]=nil) or (src[1]=nil) or (src[2]=nil) then Exit; + + prim:= (index+count<= 2); //[ 1: 0] + smid:=(index>= 8) and (index+count<=12); //[11: 8] + rtid:=(index>=16) and (index+count<=27); //[26:16] + + count:=ord(prim)+ord(smid)+ord(rtid); + + if (count=0) then + begin + Result:=NewReg_q(node^.dtype,0); + end else + if (count=1) then + begin + if prim then + begin + Result:=src[0]; + end else + if smid then + begin + Result:=src[1]; + end else + if rtid then + begin + Result:=src[2]; + end; + end; + +end; + +function TEmitPostOp.OnBFEU32_1(node:PSpirvOp):Integer; +var + dst:PsrRegNode; + rBase,rIndex,rCount:PsrRegNode; + rsl:PsrRegNode; + num_31:PsrRegNode; + data:array[0..1] of QWORD; + index,count:Byte; +begin + Result:=0; + dst:=node^.pDst^.AsType(ntReg); + if (dst=nil) then Exit; + + rBase :=node^.ParamNode(0)^.AsReg; + rIndex:=RegDown(node^.ParamNode(1)^.AsReg); + rCount:=RegDown(node^.ParamNode(2)^.AsReg); + + if (rBase=nil) or (rIndex=nil) or (rCount=nil) then Exit; + + //else + node^.mark_not_used; + node^.pDst:=nil; + + if (rIndex^.is_const) and (rCount^.is_const) then + begin + data[0]:=rIndex^.AsConst^.GetData; + data[1]:=rCount^.AsConst^.GetData; + // + index:=Byte(data[0] and 31); + count:=Byte(data[1] and 31); + // + rsl:=_Fetch_PackAnc(rBase,index,count); + + if (rsl<>nil) then + begin + + rBase:=RegDown(rsl); + if (rBase^.is_const) then + begin + data[0]:=rBase^.AsConst^.GetData; + data[1]:=(1 shl count)-1; + data[0]:=data[0] and data[1]; + // + if (data[0]<>rBase^.AsConst^.GetData) then + begin + rsl:=NewReg_q(dtUInt32,data[0],@Node); + end; + end else + begin + data[1]:=(1 shl count)-1; + num_31:=NewReg_q(dtUInt32,data[1],@Node); + // + rsl:=OpBitwiseAndTo(rsl,num_31,@node); + rsl^.PrepType(ord(dtUInt32)); + end; + + dst^.pWriter:=rsl; + dst^.pLine :=rsl^.pLine; + + Exit; + end; + + end; + + num_31:=nil; + + // + if (rIndex^.is_const) then + begin + data[0]:=rIndex^.AsConst^.GetData; + data[0]:=data[0] and 31; + // + if (data[0]<>rIndex^.AsConst^.GetData) then + begin + rIndex:=NewReg_q(dtUInt32,data[0],@Node); + end else + begin + rIndex:=node^.ParamNode(1)^.AsReg; //orig + end; + end else + begin + num_31:=NewReg_q(dtUInt32,31,@Node); + // + rIndex:=node^.ParamNode(1)^.AsReg; //orig + rIndex:=OpBitwiseAndTo(rIndex,num_31,@node); + rIndex^.PrepType(ord(dtUInt32)); + end; + + // + if (rCount^.is_const) then + begin + data[1]:=rCount^.AsConst^.GetData; + data[1]:=data[1] and 31; + // + if (data[1]<>rCount^.AsConst^.GetData) then + begin + rCount:=NewReg_q(dtUInt32,data[1],@Node); + end else + begin + rCount:=node^.ParamNode(2)^.AsReg; //orig + end; + end else + begin + if (num_31<>nil) then + begin + num_31:=NewReg_q(dtUInt32,31,@Node); + end; + // + rCount:=node^.ParamNode(2)^.AsReg; //orig + rCount:=OpBitwiseAndTo(rCount,num_31,@node); + rCount^.PrepType(ord(dtUInt32)); + end; + + _Op3(node,Op.OpBitFieldUExtract,dst,rBase,rIndex,rCount); +end; + +function TEmitPostOp.OnBFIB32_1(node:PSpirvOp):Integer; +var + dst:PsrRegNode; + bitmsk:PsrRegNode; + src:array[0..1] of PsrRegNode; + rIndex,rCount:PsrRegNode; + data:array[0..1] of QWORD; + index,count:Byte; +begin + Result:=0; + dst:=node^.pDst^.AsType(ntReg); + if (dst=nil) then Exit; + + bitmsk:=RegDown(node^.ParamNode(0)^.AsReg); + src[0]:=RegDown(node^.ParamNode(1)^.AsReg); + src[1]:=RegDown(node^.ParamNode(2)^.AsReg); + + if (bitmsk=nil) or (src[0]=nil) or (src[1]=nil) then Exit; + + if bitmsk^.is_const then + begin + data[0]:=bitmsk^.AsConst^.GetData; + + index:=BsfQWord(data[0]); + count:=PopCnt (data[0]); + + data[1]:=((1 shl count)-1) shl index; + + if (data[0]=data[1]) then + begin + + if (index<>0) then + begin + Assert(false,'TODO'); + end; + + node^.mark_not_used; + node^.pDst:=nil; + + rIndex:=NewReg_q(dtUint32,index,@Node); + rCount:=NewReg_q(dtUint32,count,@Node); + + src[0]:=node^.ParamNode(1)^.AsReg; + src[1]:=node^.ParamNode(2)^.AsReg; + + _Op4(node,Op.OpBitFieldInsert,dst,src[1],src[0],rIndex,rCount); + + Exit; + end; + + end; + + //else + node^.mark_not_used; + node^.pDst:=nil; + + src[0]:=node^.ParamNode(1)^.AsReg; + src[1]:=node^.ParamNode(2)^.AsReg; + + src[0]:=OpBitwiseAndTo(src[0],bitmsk,@node); + src[0]^.PrepType(ord(dtUInt32)); + + bitmsk:=OpNotTo(bitmsk,@node); + bitmsk^.PrepType(ord(dtUInt32)); + + src[1]:=OpBitwiseAndTo(src[1],bitmsk,@node); + src[1]^.PrepType(ord(dtUInt32)); + + _Op2(node,Op.OpBitwiseOr,dst,src[0],src[1]); +end; + function _IsFma(node:PSpirvOp):Boolean; var - OpId:DWORD; + OpId:PtrUint; begin Result:=False; if (node=nil) then Exit; @@ -1622,31 +1892,31 @@ end; function _IsConstFloat_1_0(pReg:PsrRegNode):Boolean; var - pCon:PsrConst; + pConst:PsrConst; begin Result:=False; if (pReg=nil) then Exit; - pCon:=pReg^.AsConst; - if (pCon=nil) then Exit; - if (pCon^.key.dtype<>dtFloat32) then Exit; - Result:=(Round(PSingle(@pCon^.Data)^*10)=10); + pConst:=pReg^.AsConst; + if (pConst=nil) then Exit; + if (pConst^.dtype<>dtFloat32) then Exit; + Result:=(Round(pConst^.AsFloat32*10)=10); end; function _IsConstFloat_1_5(pReg:PsrRegNode):Boolean; var - pCon:PsrConst; + pConst:PsrConst; begin Result:=False; if (pReg=nil) then Exit; - pCon:=pReg^.AsConst; - if (pCon=nil) then Exit; - if (pCon^.key.dtype<>dtFloat32) then Exit; - Result:=(Round(PSingle(@pCon^.Data)^*10)=15); + pConst:=pReg^.AsConst; + if (pConst=nil) then Exit; + if (pConst^.dtype<>dtFloat32) then Exit; + Result:=(Round(pConst^.AsFloat32*10)=15); end; function _Fetch_FAbs_Value(node:PSpirvOp):PSpirvOp; var - OpId:DWORD; + OpId:PtrUint; pReg:PsrRegNode; begin Result:=nil; @@ -1655,9 +1925,9 @@ begin OpId:=0; node^.ParamNode(1)^.TryGetValue(OpId); if (OpId<>GlslOp.FAbs) then Exit; - pReg:=node^.ParamNode(2)^.AsReg; + pReg:=RegDown(node^.ParamNode(2)^.AsReg); if (pReg=nil) then Exit; - Result:=pReg^.AsOp; + Result:=pReg^.pWriter^.AsType(ntOp); end; function _cmp_src_cube_op3(node0,node1:PSpirvOp):Boolean; @@ -1689,7 +1959,7 @@ end; function is_all_in_one_comp(src:PPsrRegNode;rtype:TsrDataType;count:byte):Boolean; var i:Byte; - pos:DWORD; + pos:PtrUint; pLine:PspirvOp; pReg,tmp:PsrRegNode; begin @@ -1697,7 +1967,7 @@ begin Result:=True; For i:=0 to count-1 do begin - pLine:=src[i]^.AsOp; + pLine:=src[i]^.pWriter^.AsType(ntOp); if (pLine=nil) then Exit(false); if (pLine^.OpId<>Op.OpCompositeExtract) then Exit(false); @@ -1705,7 +1975,7 @@ begin if not pLine^.ParamNode(1)^.TryGetValue(pos) then Exit; if (pos<>i) then Exit(false); - tmp:=pLine^.ParamNode(0)^.AsReg; + tmp:=RegDown(pLine^.ParamNode(0)^.AsReg); if (tmp=nil) then Exit(false); if (tmp^.dtype<>rtype) then Exit(false); @@ -1723,31 +1993,31 @@ end; function try_get_comp_bridge(var src:PsrRegNode):Integer; var pLine:PspirvOp; - pos:DWORD; + pos:PtrUint; pReg:PsrRegNode; begin Result:=0; - pLine:=src^.AsOp; + pLine:=src^.pWriter^.AsType(ntOp); if (pLine=nil) then Exit; if (pLine^.OpId<>Op.OpCompositeExtract) then Exit; pos:=0; if not pLine^.ParamNode(1)^.TryGetValue(pos) then Exit; - pReg:=pLine^.ParamNode(0)^.AsReg; + pReg:=RegDown(pLine^.ParamNode(0)^.AsReg); if (pReg=nil) then Exit; - pLine:=pReg^.AsOp; + pLine:=pReg^.pWriter^.AsType(ntOp); if (pLine=nil) then Exit; if (pLine^.OpId<>Op.OpCompositeConstruct) then Exit; - pReg:=pLine^.ParamNode(pos)^.AsReg; + pReg:=RegDown(pLine^.ParamNode(pos)^.AsReg); if (pReg=nil) then Exit; src:=pReg; Result:=1; end; -function TEmitPostOp.OnMakeCM1(node:PSpirvOp):Integer; +function TEmitPostOp.OnMakeCub1(node:PSpirvOp):Integer; var dst:PsrRegNode; src:array[0..2] of PsrRegNode; @@ -1765,28 +2035,21 @@ var pOp:PspirvOp; rtype:TsrDataType; - i,count:DWORD; + i:Byte; begin Result:=0; - dst:=node^.dst.AsReg; + dst:=node^.pDst^.AsType(ntReg); if (dst=nil) then Exit; - count:=0; - if not node^.ParamNode(0)^.TryGetValue(count) then Exit; - rtype:=TsrDataType(count); + rtype:=dst^.dtype; - if GetVecChild(rtype)<>dtFloat32 then Assert(false,'TODO'); + if (rtype.Child<>dtFloat32) then Assert(false,'TODO'); + if (rtype.Count=4) then Assert(false,'TODO'); - count:=0; - if not node^.ParamNode(1)^.TryGetValue(count) then Exit; - if (count=0) then Exit; - - if (count=4) then Assert(false,'TODO'); - - m_x:=RegDown(node^.ParamNode(2)^.AsReg)^.AsOp; //param1 - m_y:=RegDown(node^.ParamNode(3)^.AsReg)^.AsOp; //param2 - m_f:=RegDown(node^.ParamNode(4)^.AsReg)^.AsOp; //param3 + m_x:=RegDown(node^.ParamNode(0)^.AsReg)^.pWriter^.AsType(ntOp); //param1 + m_y:=RegDown(node^.ParamNode(1)^.AsReg)^.pWriter^.AsType(ntOp); //param2 + m_f:=RegDown(node^.ParamNode(2)^.AsReg)^.pWriter^.AsType(ntOp); //param3 if not _IsFma(m_x) then Exit; if not _IsFma(m_y) then Exit; @@ -1796,19 +2059,19 @@ begin //m_x pReg:=RegDown(m_x^.ParamNode(2)^.AsReg); //param1 - pOp:=pReg^.AsOp; + pOp:=pReg^.pWriter^.AsType(ntOp); if not _IsOp(pOp,OpCUBESC) then Exit; m_CUBE_SC:=pOp; pReg:=RegDown(m_x^.ParamNode(3)^.AsReg); //param2 - pOp:=pReg^.AsOp; + pOp:=pReg^.pWriter^.AsType(ntOp); if not _IsOp(pOp,Op.OpFDiv) then Exit; pReg:=RegDown(pOp^.ParamNode(0)^.AsReg); //div if not _IsConstFloat_1_0(pReg) then Exit; //1.0 pReg:=RegDown(pOp^.ParamNode(1)^.AsReg); - pOp:=_Fetch_FAbs_Value(pReg^.AsOp); + pOp:=_Fetch_FAbs_Value(pReg^.pWriter^.AsType(ntOp)); if not _IsOp(pOp,OpCUBEMA) then Exit; m_x_CUBE_MA:=pOp; @@ -1817,19 +2080,19 @@ begin //m_y pReg:=RegDown(m_y^.ParamNode(2)^.AsReg); //param1 - pOp:=pReg^.AsOp; + pOp:=pReg^.pWriter^.AsType(ntOp); if not _IsOp(pOp,OpCUBETC) then Exit; m_CUBE_TC:=pOp; pReg:=RegDown(m_x^.ParamNode(3)^.AsReg); //param2 - pOp:=pReg^.AsOp; + pOp:=pReg^.pWriter^.AsType(ntOp); if not _IsOp(pOp,Op.OpFDiv) then Exit; pReg:=RegDown(pOp^.ParamNode(0)^.AsReg); //div if not _IsConstFloat_1_0(pReg) then Exit; //1.0 pReg:=RegDown(pOp^.ParamNode(1)^.AsReg); - pOp:=_Fetch_FAbs_Value(pReg^.AsOp); + pOp:=_Fetch_FAbs_Value(pReg^.pWriter^.AsType(ntOp)); if not _IsOp(pOp,OpCUBEMA) then Exit; m_y_CUBE_MA:=pOp; @@ -1838,8 +2101,8 @@ begin // - if not _cmp_src_cube_op3(m_CUBE_SC,m_CUBE_TC) then Exit; - if not _cmp_src_cube_op3(m_CUBE_SC,m_CUBE_ID) then Exit; + if not _cmp_src_cube_op3(m_CUBE_SC,m_CUBE_TC ) then Exit; + if not _cmp_src_cube_op3(m_CUBE_SC,m_CUBE_ID ) then Exit; if not _cmp_src_cube_op3(m_CUBE_SC,m_x_CUBE_MA) then Exit; if not _cmp_src_cube_op3(m_CUBE_SC,m_y_CUBE_MA) then Exit; @@ -1848,26 +2111,26 @@ begin src[i]:=RegDown(m_CUBE_SC^.ParamNode(i)^.AsReg); end; - MakeVecComp(node,dtVec3f,dst,3,@src); + MakeVecComp(node,dtVec3f,dst,@src); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + node^.mark_not_used; + node^.pDst:=nil; Result:=1; end; -procedure TEmitPostOp.MakeVecConst(rtype:TsrDataType;dst:PsrRegNode;count:Byte;src:PPsrRegNode); +procedure TEmitPostOp.MakeVecConst(rtype:TsrDataType;dst:PsrRegNode;src:PPsrRegNode); var nodes:array[0..3] of PsrConst; h:PsrConst; i:Byte; begin - For i:=0 to count-1 do + For i:=0 to rtype.Count-1 do begin nodes[i]:=src[i]^.AsConst; end; - h:=FConsts.Fetch_vec(rtype,count,@nodes); - dst^.SetConst(h); + h:=ConstList.FetchVector(rtype,@nodes,true); + dst^.pWriter:=h; end; procedure TEmitPostOp.MakeVecOne(dst:PsrRegNode;src:PPsrRegNode); @@ -1875,13 +2138,12 @@ var pLine:PspirvOp; rsrc:PsrRegNode; begin - pLine:=src[0]^.AsOp; - rsrc:=pLine^.ParamNode(0)^.AsReg; - rsrc^.mark_read; - dst^.SetReg(rsrc); + pLine:=src[0]^.pWriter^.AsType(ntOp); + rsrc:=RegDown(pLine^.ParamNode(0)^.AsReg); + dst^.pWriter:=rsrc; end; -function TEmitPostOp.MakeVecComp(pLine:PSpirvOp;rtype:TsrDataType;dst:PsrRegNode;count:Byte;src:PPsrRegNode):PSpirvOp; +function TEmitPostOp.MakeVecComp(pLine:PSpirvOp;rtype:TsrDataType;dst:PsrRegNode;src:PPsrRegNode):PSpirvOp; var r:Integer; i:Byte; @@ -1890,18 +2152,18 @@ begin repeat r:=0; - For i:=0 to count-1 do + For i:=0 to rtype.Count-1 do begin r:=r+try_get_comp_bridge(src[i]); end; - if is_all_const(src,count) then + if is_all_const(src,rtype.Count) then begin - MakeVecConst(rtype,dst,count,src); + MakeVecConst(rtype,dst,src); Exit; // end; - if is_all_in_one_comp(src,rtype,count) then + if is_all_in_one_comp(src,rtype,rtype.Count) then begin MakeVecOne(dst,src); Exit; // @@ -1909,11 +2171,7 @@ begin until (r=0); - For i:=0 to count-1 do - begin - src[i]^.mark_read; //strict type later - end; - Result:=emit_OpMakeConstruct(pLine,dst,count,src); + Result:=OpMakeCon(pLine,dst,src); end; function TEmitPostOp.OnMakeVec2(node:PSpirvOp):Integer; @@ -1922,43 +2180,37 @@ var dst:PsrRegNode; src:array[0..3] of PsrRegNode; rtype:TsrDataType; - i,count:DWORD; + i:Byte; begin Result:=1; - dst:=node^.dst.AsReg; + dst:=node^.pDst^.AsType(ntReg); if (dst=nil) then Exit; - pParam:=node^.pParam.pHead; + pParam:=node^.ParamFirst; - count:=0; - if not pParam^.TryGetValue(count) then Exit; - rtype:=TsrDataType(count); + rtype:=dst^.dtype; - pParam:=pParam^.pNext; - count:=0; - if not pParam^.TryGetValue(count) then Exit; - - For i:=0 to count-1 do + For i:=0 to rtype.Count-1 do begin - pParam:=pParam^.pNext; src[i]:=pParam^.AsReg; + pParam:=pParam^.Next; if (src[i]=nil) then Assert(false,'OnMakeVec2'); end; - MakeVecComp(node,rtype,dst,count,@src); + MakeVecComp(node,rtype,dst,@src); - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + node^.mark_not_used; + node^.pDst:=nil; end; function TEmitPostOp.OnReturn_2(node:PSpirvOp):Integer; begin Result:=0; - if is_term_op(node^.pPrev) then + if is_term_op(node^.Prev) then begin - node^.OpId:=OpLinks; //mark remove + node^.mark_not_used; Inc(Result); end; @@ -1970,74 +2222,75 @@ var pOpBlock:PsrOpBlock; pChild:PsrOpBlock; pOpLabel:array[0..2] of PspirvOp; - exc,tmp:PsrRegNode; + exc:PsrRegNode; b_adr:TSrcAdr; begin Result:=1; - pOpBlock:=node^.pParent; + pOpBlock:=node^.Parent; - exc:=node^.ParamNode(0)^.AsReg; + exc:=RegDown(node^.ParamNode(0)^.AsReg); if (exc=nil) then Exit; - tmp:=RegDown(exc); - if tmp^.is_const then + if exc^.is_const then begin - node^.OpId:=OpLinks; - //node^.OpId:=Op.OpNop; - //NodeOpClear(node); //clear + node^.mark_not_used; - Case tmp^.AsConst^.AsBool of + Case exc^.AsConst^.AsBool of True : //is always store begin - pLine:=node^.pNext; + pLine:=node^.Next; if (pLine<>nil) then begin - pChild:=pLine^.dst.AsBlock; + pChild:=pLine^.AsType(ntOpBlock); if (pChild<>nil) then begin - Dec(pChild^.FLevel); //up + //up + pOpBlock^.Remove(pChild); + pLine:=PspirvOp(pOpBlock); + pLine^.InsertAfter(PspirvOp(pChild)); + pChild^.UpdateLevel; end; end; end; False: //is always kill begin - pOpBlock^.dummy.OpId:=Op.OpKill; //add kill + AddSpirvOp(@pOpBlock^.dummy,Op.OpKill); //add kill //clear all - node:=pOpBlock^.pHead; + node:=pOpBlock^.First; While (node<>nil) do begin - Case node^.OpId of - Op.OpNop:; - OpLinks:; - Op.OpKill:; - OpBlock: - begin - pChild:=node^.dst.AsBlock; - node:=pChild^.pHead; - Continue; - end; - else - node^.OpId:=OpLinks; //mark remove + if node^.IsType(ntOpBlock) then + begin + pChild:=node^.AsType(ntOpBlock); + node:=pChild^.First; + Continue; + end else + begin + Case node^.OpId of + Op.OpNop:; + Op.OpKill:; + else + node^.mark_not_used; + end; end; - node:=node^.pNext; + node:=node^.Next; end; end; end; Exit; end else begin - node^.OpId:=OpLinks; //mark remove + node^.mark_not_used; - exc^.mark_read; b_adr:=pOpBlock^.Block.b_adr; - pLine:=node^.pNext; + pLine:=node^.Next; if (pLine=nil) then //kill or nop begin - pOpLabel[0]:=NewLabelOp; //current - pOpLabel[1]:=NewLabelOp; //end + pOpLabel[0]:=NewLabelOp(False); //current + pOpLabel[1]:=NewLabelOp(False); //end pOpLabel[0]^.Adr:=b_adr; pOpLabel[1]^.Adr:=b_adr; @@ -2047,26 +2300,27 @@ begin pOpBlock^.SetCond(nil,true); pLine:=node; - pLine:=emit_OpCondMerge(pLine,pOpLabel[1]); - pLine:=emit_OpBranchCond(pLine,pOpLabel[1],pOpLabel[0],exc); //reverse + pLine:=OpCondMerge(pLine,pOpLabel[1]); + pLine:=OpBranchCond(pLine,pOpLabel[1],pOpLabel[0],exc); //reverse pLine:=AddSpirvOp(pLine,pOpLabel[0]); pChild:=AllocBlockOp; //create new pChild^.SetInfo(btOther,b_adr,b_adr); - pChild^.dummy.OpId:=Op.OpKill; + pChild^.dummy.OpId:=Op.OpKill; //set kill to dummy + pLine:=InsertBlockOp(pLine,pChild); - //emit_OpBranch not need from kill - pLine:=emit_OpBranch(pLine,pOpLabel[1]); + //OpBranch not need from kill + pLine:=OpBranch(pLine,pOpLabel[1]); pLine:=AddSpirvOp(pLine,pOpLabel[1]); end else begin //kill or store - Assert(pLine^.OpId=OpBlock); + Assert(pLine^.IsType(ntOpBlock)); - pOpLabel[0]:=NewLabelOp; //current - pOpLabel[1]:=NewLabelOp; //else - pOpLabel[2]:=NewLabelOp; //end + pOpLabel[0]:=NewLabelOp(False); //current + pOpLabel[1]:=NewLabelOp(False); //else + pOpLabel[2]:=NewLabelOp(False); //end pOpLabel[0]^.Adr:=b_adr; pOpLabel[1]^.Adr:=b_adr; @@ -2077,22 +2331,23 @@ begin pOpBlock^.SetCond(nil,true); pLine:=node; - pLine:=emit_OpCondMerge(pLine,pOpLabel[2]); - pLine:=emit_OpBranchCond(pLine,pOpLabel[1],pOpLabel[0],exc); //reverse + pLine:=OpCondMerge(pLine,pOpLabel[2]); + pLine:=OpBranchCond(pLine,pOpLabel[1],pOpLabel[0],exc); //reverse pLine:=AddSpirvOp(pLine,pOpLabel[0]); pChild:=AllocBlockOp; //create new pChild^.SetInfo(btOther,b_adr,b_adr); - pChild^.dummy.OpId:=Op.OpKill; + pChild^.dummy.OpId:=Op.OpKill; //set kill to dummy + pLine:=InsertBlockOp(pLine,pChild); - //emit_OpBranch not need from kill + //OpBranch not need from kill pLine:=AddSpirvOp(pLine,pOpLabel[1]); //OpStore child - pLine:=pOpBlock^.pTail; - pLine:=emit_OpBranch(pLine,pOpLabel[2]); + pLine:=pOpBlock^.Last; + pLine:=OpBranch(pLine,pOpLabel[2]); pLine:=AddSpirvOp(pLine,pOpLabel[2]); //end end; @@ -2103,304 +2358,100 @@ end; function TEmitPostOp.OnIAddExt2(node:PSpirvOp):Integer; var + rsl:PsrRegPair; dst,car:PsrRegNode; src:array[0..1] of PsrRegNode; begin Result:=1; - dst:=node^.dst.AsReg; - car:=node^.ParamNode(0)^.AsReg; + rsl:=node^.pDst^.AsType(ntRegPair); + if (rsl=nil) then Exit; + + dst:=rsl^.pDst0^.AsType(ntReg); + car:=rsl^.pDst1^.AsType(ntReg); if (dst=nil) or (car=nil) then Exit; - src[0]:=node^.ParamNode(1)^.AsReg; - src[1]:=node^.ParamNode(2)^.AsReg; + src[0]:=RegDown(node^.ParamNode(0)^.AsReg); + src[1]:=RegDown(node^.ParamNode(1)^.AsReg); + if (src[0]=nil) or (src[1]=nil) then Exit; - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + node^.mark_not_used; + node^.pDst:=nil; - if (car^.read_count>1) then //carry is use + if (car^.IsUsed) then //carry is use begin - src[0]^.mark_read; //strict type later - src[1]^.mark_read; //strict type later - _emit_OpIAddC(node,dst,car,src[0],src[1]); + OpIAddCar(node,dst,car,src[0],src[1]); end else begin - src[0]^.mark_read; - src[1]^.mark_read; - _emit_OpIAdd(node,dst,src[0],src[1]); + _Op2(node,Op.OpIAdd,dst,src[0],src[1]); end; end; function TEmitPostOp.OnISubExt2(node:PSpirvOp):Integer; var + rsl:PsrRegPair; dst,bor:PsrRegNode; src:array[0..1] of PsrRegNode; begin Result:=1; - dst:=node^.dst.AsReg; - bor:=node^.ParamNode(0)^.AsReg; + rsl:=node^.pDst^.AsType(ntRegPair); + if (rsl=nil) then Exit; + + dst:=rsl^.pDst0^.AsType(ntReg); + bor:=rsl^.pDst1^.AsType(ntReg); if (dst=nil) or (bor=nil) then Exit; - src[0]:=node^.ParamNode(1)^.AsReg; - src[1]:=node^.ParamNode(2)^.AsReg; + src[0]:=RegDown(node^.ParamNode(0)^.AsReg); + src[1]:=RegDown(node^.ParamNode(1)^.AsReg); + if (src[0]=nil) or (src[1]=nil) then Exit; - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + node^.mark_not_used; + node^.pDst:=nil; - if (bor^.read_count>1) then //borrow is use + if (bor^.IsUsed) then //borrow is use begin - src[0]^.mark_read; //strict type later - src[1]^.mark_read; //strict type later - _emit_OpISubB(node,dst,bor,src[0],src[1]); + OpISubBor(node,dst,bor,src[0],src[1]); end else begin - src[0]^.mark_read; - src[1]^.mark_read; - _emit_OpISub(node,dst,src[0],src[1]); + _Op2(node,Op.OpISub,dst,src[0],src[1]); end; end; -{ -If (isNan(S0.f) || isNan(S1.f) || isNan(S2.f)) - D.f = MIN3(S0.f, S1.f, S2.f) -Else if (MAX3(S0.f,S1.f,S2.f) == S0.f) - D.f = MAX(S1.f, S2.f) -Else if (MAX3(S0.f,S1.f,S2.f) == S1.f) - D.f = MAX(S0.f, S2.f) -Else - D.f = MAX(S0.f, S1.f) -} - -{ -float MED3F(vec3 s) { - - float s0=s.x; - float s1=s.y; - float s2=s.z; - - if (any(isnan(s))) { - return min(s0,min(s1,s2)); - } - - return max(min(s0,s1), min(max(s0,s1), s2)); -} -} - -//%MED3F_vf3_ = OpFunction %float None %9 -// %s = OpFunctionParameter %_ptr_Function_v3float -// %12 = OpLabel - -// %17 = OpAccessChain %_ptr_Function_float %s %uint_0 -// %21 = OpAccessChain %_ptr_Function_float %s %uint_1 -// %25 = OpAccessChain %_ptr_Function_float %s %uint_2 - -// %s0 = OpLoad %float %17 -// %s1 = OpLoad %float %21 -// %s2 = OpLoad %float %25 - -// %27 = OpLoad %v3float %s -// %30 = OpIsNan %v3bool %27 -// %31 = OpAny %bool %30 - -// OpSelectionMerge %33 None -// OpBranchConditional %31 %32 %33 -// %32 = OpLabel -// %37 = OpExtInst %float %1 FMin %s1 %s2 -// %38 = OpExtInst %float %1 FMin %s0 %37 -// OpReturnValue %38 -// %33 = OpLabel - -// %min = OpExtInst %float %1 FMin %s0 %s1 -// %max = OpExtInst %float %1 FMax %s0 %s1 -// %tmp = OpExtInst %float %1 FMin %max %s2 -// %ret = OpExtInst %float %1 FMax %min %tmp -// OpReturnValue %ret -// OpFunctionEnd - -{ -function TEmitPostOp.NewMED3F:PSpirvFunc; -var - pFunc:PSpirvFunc; - - node:PSpirvOp; - - tvec3f:PsrType; - pvec3f:PsrType; - tfloat:PsrType; - tftype:PsrType; - - vparam:TOpParamSingle; - - rparam:PsrRegNode; - visnan:PsrRegNode; - bisnan:PsrRegNode; - max:PsrRegNode; - min:PsrRegNode; - tmp:PsrRegNode; - ret:PsrRegNode; - - src:array[0..2] of PsrRegNode; - - pOpLabel:array[0..1] of PspirvOp; - -begin - pFunc:=FSpirvFuncs.Search('MED3F'); - if (pFunc<>nil) then - begin - pFunc^.mark_read; - Exit(pFunc); - end; - - pFunc:=Alloc(SizeOf(TSpirvFunc)); - pFunc^.Init('MED3F',@Alloc); - pFunc^.mark_read; - - tvec3f:=FSpirvTypes.Fetch(dtVec3f); - pvec3f:=FSpirvTypes.FetchPointer(tvec3f,StorageClass.Function_); - tfloat:=FSpirvTypes.Fetch(dtFloat32); - tftype:=FSpirvTypes.FetchFunction1(tfloat,pvec3f); - - //OpFunction - node:=pFunc^.AddSpirvOp(Op.OpFunction); - node^.dst_type:=FSpirvTypes.Fetch(dtFloat32); - node^.dst.SetParam(ntFunc,pFunc); //self - node^.AddLiteral(FunctionControl.None,'None'); - node^.AddParam(ntType,tftype); - - vparam:=Default(TOpParamSingle); - vparam.SetParam(ntRefId,NewRefId); - pvec3f^.mark_read; - //OpFunctionParameter - node:=pFunc^.AddSpirvOp(Op.OpFunctionParameter); - node^.dst_type:=pvec3f; - node^.dst:=vparam; - - //OpLabel - node:=NewLabelOp; - node^.Adr:=Default(TSrcAdr); - pFunc^.AddSpirvOp(node); - - rparam:=NewReg(dtVec3f); //load - tvec3f^.mark_read; - emit_OpLoad(pFunc^.line,tvec3f,rparam,vparam)^.Adr:=Default(TSrcAdr); - - src[0]:=NewReg(dtFloat32); - src[1]:=NewReg(dtFloat32); - src[2]:=NewReg(dtFloat32); - - rparam^.mark_read; - emit_OpCompExtract(pFunc^.line,src[0],rparam,0)^.Adr:=Default(TSrcAdr); - - rparam^.mark_read; - emit_OpCompExtract(pFunc^.line,src[1],rparam,1)^.Adr:=Default(TSrcAdr); - - rparam^.mark_read; - emit_OpCompExtract(pFunc^.line,src[2],rparam,2)^.Adr:=Default(TSrcAdr); - - // - visnan:=NewReg(dtVec3b); //OpIsNan - rparam^.mark_read; - _emit_OpIsNan(pFunc^.line,visnan,rparam)^.Adr:=Default(TSrcAdr); - - bisnan:=NewReg(dtBool); //OpAny - visnan^.mark_read; - _emit_Op1(pFunc^.line,Op.OpAny,bisnan,visnan)^.Adr:=Default(TSrcAdr); - - // - pOpLabel[0]:=NewLabelOp; - pOpLabel[1]:=NewLabelOp; - pOpLabel[0]^.Adr:=Default(TSrcAdr); - pOpLabel[1]^.Adr:=Default(TSrcAdr); - emit_OpCondMerge(pFunc^.line,pOpLabel[1])^.Adr:=Default(TSrcAdr); //merge - bisnan^.mark_read; - emit_OpBranchCond(pFunc^.line,pOpLabel[0],pOpLabel[1],bisnan)^.Adr:=Default(TSrcAdr); //branch - pFunc^.AddSpirvOp(pOpLabel[0]); //OpLabel - - tmp:=NewReg(dtFloat32); - src[0]^.mark_read; - src[1]^.mark_read; - _emit_OpFMin(pFunc^.line,tmp,src[0],src[1])^.Adr:=Default(TSrcAdr); //min(s0,s1) - - ret:=NewReg(dtFloat32); - tmp^.mark_read; - src[2]^.mark_read; - _emit_OpFMin(pFunc^.line,ret,tmp,src[2])^.Adr:=Default(TSrcAdr); //min(min(s0,s1),s2) - - ret^.mark_read; - emit_OpReturnValue(pFunc^.line,ret)^.Adr:=Default(TSrcAdr); //ret - - pFunc^.AddSpirvOp(pOpLabel[1]); //end branch - - // - min:=NewReg(dtFloat32); - src[0]^.mark_read; - src[1]^.mark_read; - _emit_OpFMin(pFunc^.line,min,src[0],src[1])^.Adr:=Default(TSrcAdr); //min(s0,s1) - - max:=NewReg(dtFloat32); - src[0]^.mark_read; - src[1]^.mark_read; - _emit_OpFMax(pFunc^.line,max,src[0],src[1])^.Adr:=Default(TSrcAdr); //max(s0,s1) - - tmp:=NewReg(dtFloat32); - max^.mark_read; - src[2]^.mark_read; - _emit_OpFMin(pFunc^.line,tmp,max,src[2])^.Adr:=Default(TSrcAdr); //min(max(s0,s1),s2) - - ret:=NewReg(dtFloat32); - min^.mark_read; - tmp^.mark_read; - _emit_OpFMax(pFunc^.line,ret,min,tmp)^.Adr:=Default(TSrcAdr); //max(min(s0,s1),min(max(s0,s1),s2)) - - ret^.mark_read; - emit_OpReturnValue(pFunc^.line,ret)^.Adr:=Default(TSrcAdr); //ret - - pFunc^.AddSpirvOp(Op.OpFunctionEnd); //end - - FSpirvFuncs.Insert(pFunc); - - pFunc^.mark_read; - Result:=pFunc; -end; -} - -//%114 = OpFunctionCall %float %MED3F_vf3_ %param - -{ -function TEmitPostOp.OpMED3F__2(node:PSpirvOp):Integer; +function TEmitPostOp.OnPackAnc2(node:PSpirvOp):Integer; var dst:PsrRegNode; - vec:PsrRegNode; src:array[0..2] of PsrRegNode; - pFunc:PSpirvFunc; + num4 :PsrRegNode; + num8 :PsrRegNode; + num11:PsrRegNode; + num16:PsrRegNode; begin - Result:=1; + Result:=0; + dst:=node^.pDst^.AsType(ntReg); + if (dst=nil) then Exit; - dst:=node^.dst.pData; - src[0]:=node^.ParamNode(0)^.pData; - src[1]:=node^.ParamNode(1)^.pData; - src[2]:=node^.ParamNode(2)^.pData; + src[0]:=node^.ParamNode(0)^.AsReg; + src[1]:=node^.ParamNode(1)^.AsReg; + src[2]:=node^.ParamNode(2)^.AsReg; - node^.OpId:=OpLinks; //mark remove - node^.dst:=Default(TOpParamSingle); + if (src[0]=nil) or (src[0]=nil) or (src[1]=nil) then Exit; - //build vec - vec:=NewReg(dtVec3f); - node:=MakeVecComp(node,dtVec3f,vec,3,@src); + node^.mark_not_used; + node^.pDst:=nil; - pFunc:=NewMED3F; + num4 :=NewReg_q(dtUint32, 4); + num8 :=NewReg_q(dtUint32, 8); + num11:=NewReg_q(dtUint32,11); + num16:=NewReg_q(dtUint32,16); - vec^.mark_read; - //OpFunctionCall - node:=AddSpirvOp(node,Op.OpFunctionCall); - node^.dst_type:=FSpirvTypes.Fetch(dtFloat32); - node^.dst.SetParam(ntReg,dst); //dst - node^.AddParam(ntFunc,pFunc); //func id - node^.AddParam(ntReg,vec); //vec3f + //Base,Insert,Offset,Count + src[0]:=OpBFITo(src[0],src[1],num8 ,num4 ,@node); + src[0]:=OpBFITo(src[0],src[2],num16,num11,@node); + dst^.pWriter:=src[0]; + dst^.pLine :=src[0]^.pLine; end; -} // diff --git a/spirv/emit_print.pas b/spirv/emit_print.pas index 51637f78..f0956c8a 100644 --- a/spirv/emit_print.pas +++ b/spirv/emit_print.pas @@ -7,32 +7,27 @@ interface uses sysutils, spirv, - srNodes, + srNode, + srType, srTypes, srConst, - srReg, - srLayout, srVariable, srOp, srOpUtils, - srCap, - srRefId, - Half16, - SprvEmit; + srCapability, + emit_fetch; type - TSprvEmit_print=object(TSprvEmit) + TSprvEmit_print=class(TEmitFetch) procedure Print; procedure PrintCaps; - procedure PrintOpList(node:PspirvOp); + procedure PrintOpBlock(pBlock:PsrOpBlock); procedure PrintHeaderInfo; procedure PrintTypes; - procedure PrintConst(node:PsrConst); procedure PrintConst; procedure PrintVariable; procedure PrintFunc; procedure PrintOp(node:PSpirvOp;print_offset:Boolean); - procedure PrintOpBlock(pBlock:PsrOpBlock); end; implementation @@ -42,637 +37,141 @@ begin PrintCaps; Writeln; PrintHeaderInfo; - Writeln; PrintTypes; Writeln; PrintConst; - Writeln; PrintVariable; PrintFunc; end; -procedure PrintRefId(P:PsrRefId); -begin - Assert(P<>nil ,'PrintRefId$1'); - Assert(P^.Alloc,'PrintRefId$2'); - Write('%',P^.ID); -end; - -procedure PrintConstId(P:PsrConst); +procedure PrintNode(Node:PsrNode); var - s:Single; - i:Int64; - u:QWORD; + name:RawByteString; begin - Assert(P<>nil ,'PrintConstId$1'); - Assert(P^.ID.Alloc,'PrintConstId$2'); - - Case P^.key.dtype of - dtBool: - begin - Case P^.AsBool of - true :Write('%true'); - False:Write('%false'); - end; - end; - - dtHalf16: - begin - s:=Single(P^.AsHalf16); - i:=Trunc(s); - if (s=i) then - begin - Case i of - 0..99:Write('%ch',i); - else - Write('%c',P^.ID.ID); - end; - end else - begin - Write('%c',P^.ID.ID); - end; - end; - - dtFloat32: - begin - s:=P^.AsFloat32; - i:=Trunc(s); - if (s=i) then - begin - Case i of - 0..99:Write('%cf',i); - -9..-1:Write('%cfm',abs(i)); - else - Write('%c',P^.ID.ID); - end; - end else - begin - Write('%c',P^.ID.ID); - end; - end; - - dtInt32 : - begin - i:=P^.AsInt; - Case i of - 0..99:Write('%ci',i); - -9..-1:Write('%cim',abs(i)); - else - Write('%c',P^.ID.ID); - end; - end; - - dtUint32: - begin - u:=P^.AsUint; - Case u of - 0..99:Write('%cu',u); - else - Write('%c',P^.ID.ID); - end; - end; - - else - Write('%c',P^.ID.ID); - end; - -end; - -procedure PrintVar(P:PsrVariable); -Var - n:RawByteString; -begin - Assert(P<>nil ,'PrintVar$1'); - Assert(P^.ID.Alloc,'PrintVar$2'); - if (P^.pSource.pData<>nil) then + Assert(Node<>nil,'PrintNode$1'); + name:=node^.GetPrintName; + if (name<>'') then begin - n:=P^.GetName; - if (n<>'') then - begin - Write('%',n); - end else - begin - Write('%v',P^.ID.ID); - end; + Write('%',name); end else begin - Write('%v',P^.ID.ID); - end; -end; - -function type_get_base_name(dtype:TsrDataType):RawByteString; -begin - Result:=''; - case dtype of - - dtBool :Result:='bool'; - - dtFloat32 :Result:='float'; - dtHalf16 :Result:='half'; - - dtInt8 :Result:='int8'; - dtUint8 :Result:='uint8'; - - dtInt16 :Result:='int16'; - dtUint16 :Result:='uint16'; - - dtInt32 :Result:='int'; - dtUint32 :Result:='uint'; - - dtInt64 :Result:='int64'; - dtUint64 :Result:='uint64'; - - //Composite types - dtVec2b :Result:='bvec2'; - dtVec3b :Result:='bvec3'; - dtVec4b :Result:='bvec4'; - - dtStruct2u :Result:='rec2u'; - - dtVec2u8 :Result:='u8vec2'; - dtVec4u8 :Result:='u8vec4'; - - dtVec2i8 :Result:='i8vec2'; - dtVec4i8 :Result:='i8vec4'; - - dtVec2u16 :Result:='u16vec2'; - dtVec4u16 :Result:='u16vec4'; - - dtVec2i16 :Result:='i16vec2'; - dtVec4i16 :Result:='i16vec4'; - - dtVec2u :Result:='uvec2'; - dtVec3u :Result:='uvec3'; - dtVec4u :Result:='uvec4'; - - dtVec2i :Result:='ivec2'; - dtVec3i :Result:='ivec3'; - dtVec4i :Result:='ivec4'; - - dtVec2f :Result:='vec2'; - dtVec3f :Result:='vec3'; - dtVec4f :Result:='vec4'; - - dtVec2h :Result:='hvec2'; - dtVec4h :Result:='hvec4'; - - dtTypeVoid :Result:='void'; - - dtTypeSampler:Result:='samp'; - - else; - end; -end; - -function type_get_base_name(node:PsrType):RawByteString; -var - n:PsrType; -begin - Result:=''; - case node^.dtype of - {dtTypeImage: - begin - if DWORD(node^.key.ext.image)=DWORD(ExtImgBuf) then - begin - Result:='buf'; - end else - if DWORD(node^.key.ext.image)=DWORD(ExtImage2D) then - begin - Result:='img2D'; - end; - end;} - dtTypeSampledImage: - begin - if (node^.key.count<>1) then Exit; - n:=node^.GetCompItem(0); - Result:=type_get_base_name(n); - if (Result='') then Exit; - Result:='sm'+Result; - end; - dtTypeArray: - begin - n:=node^.GetCompItem(0); - Result:=type_get_base_name(n); - if (Result='') then Exit; - Result:='ar'+IntToStr(node^.key.ext.array_count)+Result; - end; - dtTypeRuntimeArray: - begin - n:=node^.GetCompItem(0); - Result:=type_get_base_name(n); - if (Result='') then Exit; - Result:='ra'+Result; - end; - dtTypeStruct: - begin - if (node^.key.count<>1) then Exit; - n:=node^.GetCompItem(0); - Result:=type_get_base_name(n); - if (Result='') then Exit; - Result:='st'+Result; - end; - dtTypeFunction: - begin - if (node^.key.count<>1) then Exit; - n:=node^.GetCompItem(0); - Result:=type_get_base_name(n); - if (Result='') then Exit; - Result:='fn'+Result; - end; - else - Result:=type_get_base_name(node^.dtype); - end; -end; - -procedure PrintTypeId(node:PsrType); -var - s:RawByteString; - n:PsrType; -begin - case node^.dtype of - dtTypePointer: - begin - n:=node^.GetCompItem(0); - S:=type_get_base_name(n); - if (S='') then - PrintRefId(@node^.ID) - else - begin - S:='p'+S; - Case node^.key.ext.storage_class of - StorageClass.UniformConstant :S:=S+'_uc'; - StorageClass.Input :S:=S+'_in'; - StorageClass.Uniform :S:=S+'_uf'; - StorageClass.Output :S:=S+'_ot'; - StorageClass.Workgroup :S:=S+'_wg'; - StorageClass.CrossWorkgroup :S:=S+'_cw'; - StorageClass.Private_ :S:=S+'_pv'; - StorageClass.Function_ :S:=S+'_fc'; - StorageClass.PushConstant :S:=S+'_pc'; - StorageClass.Image :S:=S+'_im'; - StorageClass.StorageBuffer :S:=S+'_sb'; - else - S:=''; - end; - if (S='') then - PrintRefId(@node^.ID) - else - Write('%',S); - end; - end; - else - begin - S:=type_get_base_name(node); - if (S='') then - PrintRefId(@node^.ID) - else - Write('%',S); - end; - end; -end; - -procedure PrintChain(P:PsrChain); -begin - Assert(P<>nil ,'PrintChain$1'); - Assert(P^.ID.Alloc,'PrintChain$2'); - Write('%ac',P^.ID.ID); -end; - -procedure PrintReg(P:PsrRegNode); -begin - Assert(P<>nil,'PrintReg$1'); - Case P^.pWriter.ntype of - ntConst: - begin - PrintConstId(P^.pWriter.pData); - end; - ntOp: - begin - if (not P^.ID.Alloc) then Assert(false,'PrintReg$2'); - Write('%r',P^.ID.ID); - //Write('(',P^.read_count,')'); - end; - else - Assert(false,'PrintReg$3'); + name:=node^.GetPrintData; + Assert(name<>'','PrintNode$2'); + Write(name); end; end; procedure TSprvEmit_print.PrintCaps; var - node:PSpirvCap; + node:PsrCapability; begin - node:=FSpirvCaps.First; + node:=CapabilityList.First; While (node<>nil) do begin Writeln(Op.GetStr(Op.OpCapability),' ',Capability.GetStr(node^.ID)); - node:=FSpirvCaps.Next(node); + node:=CapabilityList.Next(node); end; end; -procedure TSprvEmit_print.PrintOpList(node:PspirvOp); +procedure TSprvEmit_print.PrintOpBlock(pBlock:PsrOpBlock); +var + node:PSpirvOp; begin + if (pBlock=nil) then Exit; + node:=pBlock^.First; + While (node<>nil) do begin - PrintOp(node,false); - node:=node^.pNext; + if node^.IsType(ntOp) then + begin + pBlock:=node^.Parent; + Write(Space(pBlock^.Level)); + PrintOp(node,false); + end; + node:=flow_down_next_up(node); end; end; procedure TSprvEmit_print.PrintHeaderInfo; begin - PrintOpList(FHeader.pHead); - Writeln; - PrintOpList(FDebugInfo.pHead); - if (FDebugInfo.pHead<>nil) then Writeln; - PrintOpList(FDecorates.pHead); -end; - -function Dim_GetStr(w:Word):RawByteString; -begin - Result:=''; - Case w of - Dim.Dim1D :Result:='1D'; - Dim.Dim2D :Result:='2D'; - Dim.Dim3D :Result:='3D'; - Dim.Cube :Result:='Cube'; - Dim.Rect :Result:='Rect'; - Dim.Buffer :Result:='Buffer'; - Dim.SubpassData:Result:='SubpassData'; - else - Assert(False,'Dim_GetStr'); - end; + PrintOpBlock(@HeaderList); + if (HeaderList.First<>nil) then Writeln; + PrintOpBlock(@DebugInfoList); + if (DebugInfoList.First<>nil) then Writeln; + PrintOpBlock(@DecorateList); + if (DecorateList.First<>nil) then Writeln; end; procedure TSprvEmit_print.PrintTypes; var node:PsrType; - pConst:PsrConst; - i:dword; - ie:Boolean; + i:Word; begin - node:=FSpirvTypes.FList.pHead; + node:=TypeList.First; While (node<>nil) do begin - ie:=True; - - pConst:=nil; - case node^.dtype of - dtTypeArray: - begin - //find a const - pConst:=FConsts.Fetchi(dtUInt32,node^.key.ext.array_count); - PrintConst(pConst); - end; - else; - end; - - PrintTypeId(node); - Write(' = '); - - Write(Op.GetStr(node^.key.OpId)); - - case node^.key.OpId of - - Op.OpTypeFloat: - begin - Write(' ',node^.key.ext.float_size); - end; - - Op.OpTypeInt: - begin - Write(' ',node^.key.ext.int_size); - Write(' ',node^.key.ext.int_sign); - end; - - Op.OpTypeVector: - begin - ie:=False; - Write(' '); - PrintTypeId(node^.GetCompItem(0)); - Write(' ',node^.key.ext.array_count); - end; - - Op.OpTypePointer: - begin - Write(' ',StorageClass.GetStr(node^.key.ext.Storage_Class)); - end; - - Op.OpTypeArray: - begin - ie:=False; - Write(' '); - PrintTypeId(node^.GetCompItem(0)); - Write(' '); - PrintConstId(pConst); - end; - - Op.OpTypeRuntimeArray: - begin - ie:=False; - Write(' '); - PrintTypeId(node^.GetCompItem(0)); - end; - - Op.OpTypeImage: - begin - ie:=False; - Write(' '); - PrintTypeId(node^.GetCompItem(0)); - With node^.key.ext.image do - Write(' ', - Dim_GetStr(Dim),' ', - Depth,' ', - Arrayed,' ', - MS,' ', - Sampled,' ', - Spirv.ImageFormat.GetStr(Format)); - end; - - - end; - - if ie then - if (node^.key.count<>0) then + PrintNode(node); + Write(' = ',Op.GetStr(node^.OpId)); + if (node^.ItemCount<>0) then + begin + For i:=0 to node^.ItemCount-1 do begin - For i:=0 to node^.key.count-1 do - begin - Write(' '); - PrintTypeId(node^.GetCompItem(i)); - end; + Write(' '); + PrintNode(node^.GetItem(i)); end; - + end; Writeln; - - node:=node^.pNext; + node:=node^.Next; end; end; -const - DefaultFormatSettings : TFormatSettings = ( - CurrencyFormat: 1; - NegCurrFormat: 5; - ThousandSeparator: ','; - DecimalSeparator: '.'; - CurrencyDecimals: 2; - DateSeparator: '-'; - TimeSeparator: ':'; - ListSeparator: ','; - CurrencyString: '$'; - ShortDateFormat: 'd/m/y'; - LongDateFormat: 'dd" "mmmm" "yyyy'; - TimeAMString: 'AM'; - TimePMString: 'PM'; - ShortTimeFormat: 'hh:nn'; - LongTimeFormat: 'hh:nn:ss'; - ShortMonthNames: ('Jan','Feb','Mar','Apr','May','Jun', - 'Jul','Aug','Sep','Oct','Nov','Dec'); - LongMonthNames: ('January','February','March','April','May','June', - 'July','August','September','October','November','December'); - ShortDayNames: ('Sun','Mon','Tue','Wed','Thu','Fri','Sat'); - LongDayNames: ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'); - TwoDigitYearCenturyWindow: 50; - ); - -procedure TSprvEmit_print.PrintConst(node:PsrConst); -var - i:dword; -begin - PrintConstId(node); - Write(' = '); - - if (node^.key.count=0) then - begin - if (node^.key.dtype=dtBool) then - begin - Case node^.AsBool of - True :Write(Op.GetStr(Op.OpConstantTrue)); - False:Write(Op.GetStr(Op.OpConstantFalse)); - end; - Write(' '); - PrintTypeId(node^.pType); - end else - begin - Write(Op.GetStr(Op.OpConstant)); - Write(' '); - PrintTypeId(node^.pType); - Write(' '); - case node^.key.dtype of - dtFloat32:Write(FloatToStr(node^.AsFloat32,DefaultFormatSettings)); - dtHalf16 :Write(FloatToStr(Single(node^.AsHalf16),DefaultFormatSettings)); - dtInt32 :Write(node^.AsInt); - dtUint32 :Write(node^.AsUint); - dtInt64 :Write(node^.AsInt64); - dtUint64 :Write(node^.AsUint64); - else - Assert(false,'PrintConst'); - end; - end; - end else - begin - Write(Op.GetStr(Op.OpConstantComposite)); - Write(' '); - PrintTypeId(node^.pType); - For i:=0 to node^.key.count-1 do - begin - Write(' '); - PrintConstId(node^.GetCompItem(i)); - end; - end; - - Writeln; -end; - procedure TSprvEmit_print.PrintConst; var node:PsrConst; + i:Word; begin - node:=FConsts.FList.pHead; + node:=ConstList.First; While (node<>nil) do begin - - //if not node^.is_first then - //begin - if (node^.key.dtype=dtUnknow) then + if (node^.dtype=dtUnknow) then + begin + Write('; '); + Writeln(' = dtUnknow: read_count=',node^.read_count,' value=',node^.GetData); + end else + begin + PrintNode(node); + Write(' = ',Op.GetStr(node^.OpId),' '); + PrintNode(node^.pType); + if (node^.dtype<>dtBool) then begin - Write('; '); - //PrintConstId(node); - Writeln(' = dtUnknow: read_count=',node^.read_count,' value=',node^.Data); - end else - //Assert(node^.dtype<>dtUnknow); - PrintConst(node); - //end; - - node:=node^.pNext; + For i:=0 to node^.ItemCount-1 do + begin + Write(' '); + PrintNode(node^.GetItem(i)); + end; + end; + Writeln; + end; + node:=node^.Next; end; + if (ConstList.First<>nil) then Writeln; end; procedure TSprvEmit_print.PrintVariable; var node:PsrVariable; begin - node:=FVariables.pHead; + node:=VariableList.First; While (node<>nil) do begin if (node^.pType<>nil) then begin - PrintVar(node); + PrintNode(node); Write(' = ',Op.GetStr(Op.OpVariable),' '); - PrintTypeId(node^.pType); + PrintNode(node^.pType); Writeln(' ',StorageClass.GetStr(node^.GetStorageClass)); end; - node:=node^.pNext; - end; -end; - -procedure PrintFuncId(P:PSpirvFunc); -begin - Assert(P<>nil,'PrintFuncId'); - if (P^.name<>'') then - begin - Write('%',P^.name); - end else - begin - PrintRefId(@P^.ID); - end; -end; - -procedure PrintOpParamSingle(const Param:TOpParamSingle); -begin - Assert(Param.pData<>nil,'PrintOpParamSingle$1'); - Case Param.ntype of - ntFunc :PrintFuncId(Param.pData); - ntRefId:PrintRefId(Param.pData); - ntType :PrintTypeId(Param.pData); - ntReg :PrintReg(Param.pData); - ntVar :PrintVar(Param.pData); - ntChain:PrintChain(Param.pData); - ntConst:PrintConstId(Param.pData); - else - Assert(false,'PrintOpParamSingle$2'); - end; -end; - -procedure PrintOpParamNode(node:POpParamNode); -begin - Case node^.ntype of - ntLiteral: - begin - if StrLen(@node^.name)=0 then - begin - Write(node^.Value); - end else - begin - Write(PChar(@node^.name)); - end; - end; - ntString: - begin - Write('"',PChar(@node^.name),'"'); - end; - else - begin - PrintOpParamSingle(node^.AsParam); - end; + node:=node^.Next; end; end; @@ -680,12 +179,12 @@ procedure TSprvEmit_print.PrintFunc; var pFunc:PSpirvFunc; begin - pFunc:=FSpirvFuncs.FList.pHead; + pFunc:=FuncList.First; While (pFunc<>nil) do begin Writeln; - PrintOpBlock(@pFunc^.FTop); - pFunc:=pFunc^.pNext; + PrintOpBlock(pFunc^.pTop); + pFunc:=pFunc^.Next; end; end; @@ -700,35 +199,39 @@ begin if Info.result then //dst begin - Assert(node^.dst.ntype<>ntUnknow,'PrintOp$1'); - Assert(node^.dst.pData<>nil,'PrintOp$2'); - PrintOpParamSingle(node^.dst); + Assert(node^.pDst<>nil,'PrintOp$1'); + if (node^.pDst<>nil) then + begin + PrintNode(node^.pDst); + end; Write(' = '); Write(Op.GetStr(node^.OpId)); end else begin //no dst Write(Op.GetStr(node^.OpId)); - if (node^.dst.ntype<>ntUnknow) then + if (node^.pDst<>nil) then begin - Assert(node^.dst.pData<>nil,'PrintOp$3'); Write(' '); - PrintOpParamSingle(node^.dst); + PrintNode(node^.pDst); end; end; if Info.rstype then //dst type begin - Assert(node^.dst_type<>nil,'PrintOp$4'); + Assert(node^.pType<>nil,'PrintOp$2'); Write(' '); - PrintTypeId(node^.dst_type); + if (node^.pType<>nil) then + begin + PrintNode(node^.pType); + end; end; - Param:=node^.pParam.pHead; + Param:=node^.ParamFirst; While (Param<>nil) do begin Write(' '); - PrintOpParamNode(Param); - Param:=Param^.pNext; + PrintNode(Param^.Value); + Param:=Param^.Next; end; if (node^.OpId=Op.OpLabel) then @@ -742,31 +245,6 @@ begin end; end; -procedure TSprvEmit_print.PrintOpBlock(pBlock:PsrOpBlock); -var - node:PSpirvOp; -begin - if (pBlock=nil) then Exit; - node:=pBlock^.pHead; - While (node<>nil) do - begin - - if (node^.OpId=OpBlock) then - begin - if (node^.dst.ntype=ntBlock) then - begin - PrintOpBlock(node^.dst.pData); - end; - end else - begin - Write(Space(pBlock^.FLevel)); - PrintOp(node,false); - end; - - node:=node^.pNext; - end; -end; - end. diff --git a/spirv/emit_smrd.pas b/spirv/emit_smrd.pas index d13df3b0..e4ddb63e 100644 --- a/spirv/emit_smrd.pas +++ b/spirv/emit_smrd.pas @@ -7,30 +7,29 @@ interface uses sysutils, ps4_pssl, - srTypes, + srType, srReg, srLayout, - SprvEmit, - emit_op; + emit_fetch; type - TEmit_SMRD=object(TEmitOp) - procedure _emit_SMRD; - procedure _emit_LOAD_DWORDX(grp:PsrDataLayout;count:Byte); + TEmit_SMRD=class(TEmitFetch) + procedure emit_SMRD; + procedure emit_LOAD_DWORDX(grp:PsrDataLayout;count:Byte); procedure emit_LOAD_DWORDX(count:Byte); procedure emit_BUFFER_LOAD_DWORDX(count:Byte); end; implementation -procedure TEmit_SMRD._emit_LOAD_DWORDX(grp:PsrDataLayout;count:Byte); +procedure TEmit_SMRD.emit_LOAD_DWORDX(grp:PsrDataLayout;count:Byte); var dst:PsrRegSlot; ofs_r,idx_r:PsrRegNode; - dtype:TsrDataType; - ext:TsrChainExt; + lvl_0:TsrChainLvl_0; + lvl_1:TsrChainLvl_1; i:Byte; @@ -40,22 +39,23 @@ begin begin For i:=0 to count-1 do begin - dst:=FRegsStory.get_sdst7(FSPI.SMRD.SDST+i); + dst:=get_sdst7(FSPI.SMRD.SDST+i); Assert(dst<>nil); - MakeChain(dst,grp,(FSPI.SMRD.OFFSET+i)*4,4,nil); + + lvl_0.offset:=(FSPI.SMRD.OFFSET+i)*4; + lvl_0.size :=4; + + MakeChain(dst,grp,@lvl_0,nil); end; end else begin ofs_r:=fetch_ssrc9(FSPI.SMRD.OFFSET,dtUint32); - dtype:=ofs_r^.dtype; - idx_r:=NewReg(dtype); - - _emit_OpShr(line,idx_r,ofs_r,FetchReg(FConsts.Fetchi(dtype,2))); + idx_r:=OpShrTo(ofs_r,2); For i:=0 to count-1 do begin - dst:=FRegsStory.get_sdst7(FSPI.SMRD.SDST+i); + dst:=get_sdst7(FSPI.SMRD.SDST+i); Assert(dst<>nil); if (i=0) then @@ -63,17 +63,16 @@ begin ofs_r:=idx_r; end else begin - ofs_r:=NewReg(dtype); - idx_r^.mark_read; - _emit_OpIAdd(line,ofs_r,idx_r,FetchReg(FConsts.Fetchi(dtype,i))); + ofs_r:=OpIAddTo(idx_r,i); end; - ofs_r^.mark_read; + lvl_0.offset:=0; + lvl_0.size :=4; - ext:=Default(TsrChainExt); - ext.pIndex:=ofs_r; - ext.stride:=4; - MakeChain(dst,grp,0,4,@ext); + lvl_1.pIndex:=ofs_r; + lvl_1.stride:=4; + + MakeChain(dst,grp,@lvl_0,@lvl_1); end; end; @@ -84,9 +83,9 @@ var src:array[0..3] of PsrRegSlot; grp:PsrDataLayout; begin - if not FRegsStory.get_sbase(FSPI.SMRD.SBASE,2,@src) then Assert(false); + if not get_sbase(FSPI.SMRD.SBASE,2,@src) then Assert(false); grp:=GroupingSharp(@src,rtBufPtr2); - _emit_LOAD_DWORDX(grp,count); + emit_LOAD_DWORDX(grp,count); end; procedure TEmit_SMRD.emit_BUFFER_LOAD_DWORDX(count:Byte); @@ -94,56 +93,26 @@ var src:array[0..3] of PsrRegSlot; grp:PsrDataLayout; begin - if not FRegsStory.get_sbase(FSPI.SMRD.SBASE,4,@src) then Assert(false); + if not get_sbase(FSPI.SMRD.SBASE,4,@src) then Assert(false); grp:=GroupingSharp(@src,rtVSharp4); - _emit_LOAD_DWORDX(grp,count); + emit_LOAD_DWORDX(grp,count); end; -procedure TEmit_SMRD._emit_SMRD; +procedure TEmit_SMRD.emit_SMRD; begin Case FSPI.SMRD.OP of - S_BUFFER_LOAD_DWORD: - begin - emit_BUFFER_LOAD_DWORDX(1); - end; - S_BUFFER_LOAD_DWORDX2: - begin - emit_BUFFER_LOAD_DWORDX(2); - end; - S_BUFFER_LOAD_DWORDX4: - begin - emit_BUFFER_LOAD_DWORDX(4); - end; - S_BUFFER_LOAD_DWORDX8: - begin - emit_BUFFER_LOAD_DWORDX(8); - end; - S_BUFFER_LOAD_DWORDX16: - begin - emit_BUFFER_LOAD_DWORDX(16); - end; + S_BUFFER_LOAD_DWORD : emit_BUFFER_LOAD_DWORDX(1); + S_BUFFER_LOAD_DWORDX2 : emit_BUFFER_LOAD_DWORDX(2); + S_BUFFER_LOAD_DWORDX4 : emit_BUFFER_LOAD_DWORDX(4); + S_BUFFER_LOAD_DWORDX8 : emit_BUFFER_LOAD_DWORDX(8); + S_BUFFER_LOAD_DWORDX16: emit_BUFFER_LOAD_DWORDX(16); - S_LOAD_DWORD: - begin - emit_LOAD_DWORDX(1); - end; - S_LOAD_DWORDX2: - begin - emit_LOAD_DWORDX(2); - end; - S_LOAD_DWORDX4: - begin - emit_LOAD_DWORDX(4); - end; - S_LOAD_DWORDX8: - begin - emit_LOAD_DWORDX(8); - end; - S_LOAD_DWORDX16: - begin - emit_LOAD_DWORDX(16); - end; + S_LOAD_DWORD : emit_LOAD_DWORDX(1); + S_LOAD_DWORDX2 : emit_LOAD_DWORDX(2); + S_LOAD_DWORDX4 : emit_LOAD_DWORDX(4); + S_LOAD_DWORDX8 : emit_LOAD_DWORDX(8); + S_LOAD_DWORDX16: emit_LOAD_DWORDX(16); else Assert(false,'SMRD?'+IntToStr(FSPI.SMRD.OP)); diff --git a/spirv/emit_sop1.pas b/spirv/emit_sop1.pas index decd8c56..38c335f2 100644 --- a/spirv/emit_sop1.pas +++ b/spirv/emit_sop1.pas @@ -7,172 +7,148 @@ interface uses sysutils, ps4_pssl, - srLabel, - srTypes, + srCFGLabel, + srFlow, + srType, srConst, srReg, srLayout, - SprvEmit, - emit_op; + srOpUtils, + emit_fetch; type - TEmit_SOP1=object(TEmitOp) - procedure _emit_SOP1; - Function _GetFuncPtr(src:PPsrRegSlot):Pointer; - procedure _emit_S_MOV_B32; - procedure _emit_S_MOV_B64; - procedure _emit_S_SWAPPC_B64; - procedure _emit_S_SETPC_B64; - procedure _emit_S_AND_SAVEEXEC_B64; - procedure _emit_S_WQM_B64; + TEmit_SOP1=class(TEmitFetch) + procedure emit_SOP1; + Function GetFuncPtr(src:PPsrRegNode):Pointer; + procedure emit_S_MOV_B32; + procedure emit_S_MOV_B64; + procedure emit_S_SWAPPC_B64; + procedure emit_S_SETPC_B64; + procedure emit_S_AND_SAVEEXEC_B64; + procedure emit_S_WQM_B64; end; implementation -Function TEmit_SOP1._GetFuncPtr(src:PPsrRegSlot):Pointer; +Function TEmit_SOP1.GetFuncPtr(src:PPsrRegNode):Pointer; var chain:TsrChains; + pConst:array[0..1] of PsrConst; pLayout:PsrDataLayout; - begin Result:=nil; - chain:=Default(TsrChains); - chain[0]:=GetChainRegNode(src[0]^.current); - chain[1]:=GetChainRegNode(src[1]^.current); + src[0]:=RegDown(src[0]); + src[1]:=RegDown(src[1]); - pLayout:=FDataLayouts.Grouping(chain,rtFunPtr2); - Result:=pLayout^.pData; + Assert(src[0]<>nil); + Assert(src[1]<>nil); + + if (src[0]^.is_const) and (src[1]^.is_const) then + begin + pConst[0]:=src[0]^.AsConst; + pConst[1]:=src[1]^.AsConst; + + QWORD(Result):=QWORD(pConst[0]^.AsUint32) or (QWORD(pConst[1]^.AsUint32) shl 32); + end else + begin + chain:=Default(TsrChains); + chain[0]:=GetChainRegNode(src[0]); + chain[1]:=GetChainRegNode(src[1]); + + pLayout:=DataLayoutList.Grouping(chain,rtFunPtr2); + Result:=pLayout^.pData; + end; Assert(Result<>nil); end; -procedure TEmit_SOP1._emit_S_MOV_B32; +procedure TEmit_SOP1.emit_S_MOV_B32; Var dst:PsrRegSlot; src:PsrRegNode; begin - dst:=FRegsStory.get_sdst7(FSPI.SOP1.SDST); + dst:=get_sdst7(FSPI.SOP1.SDST); src:=fetch_ssrc9(FSPI.SOP1.SSRC,dtUnknow); - _MakeCopy(dst,src); + MakeCopy(dst,src); end; -procedure TEmit_SOP1._emit_S_MOV_B64; +procedure TEmit_SOP1.emit_S_MOV_B64; Var dst:array[0..1] of PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst[0]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+0); - dst[1]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+1); + dst[0]:=get_sdst7(FSPI.SOP1.SDST+0); + dst[1]:=get_sdst7(FSPI.SOP1.SDST+1); src[0]:=fetch_ssrc9(FSPI.SOP1.SSRC+0,dtUnknow); src[1]:=fetch_ssrc9(FSPI.SOP1.SSRC+1,dtUnknow); - _MakeCopy(dst[0],src[0]); - _MakeCopy(dst[1],src[1]); + MakeCopy(dst[0],src[0]); + MakeCopy(dst[1],src[1]); end; -procedure TEmit_SOP1._emit_S_SWAPPC_B64; +procedure TEmit_SOP1.emit_S_SWAPPC_B64; Var dst:array[0..1] of PsrRegSlot; - src:array[0..1] of PsrRegSlot; + src:array[0..1] of PsrRegNode; oldptr,newptr:Pointer; - begin - if not FRegsStory.get_sdst7_pair(FSPI.SOP1.SDST,@dst) then Assert(false); + if not get_sdst7_pair(FSPI.SOP1.SDST,@dst) then Assert(false); - Assert(not is_const_ssrc9(FSPI.SOP1.SSRC)); + if not fetch_ssrc9_pair(FSPI.SOP1.SSRC,@src,dtUnknow) then Assert(false); - if not FRegsStory.get_ssrc9_pair(FSPI.SOP1.SSRC,@src) then Assert(false); + newptr:=GetFuncPtr(@src); - newptr:=_GetFuncPtr(@src); - Assert(newptr<>nil); + oldptr:=GetPtr; - oldptr:=FCursor.Adr.get_pc; - - SetConst(dst[0],dtUint32,{%H-}QWORD(oldptr)); - SetConst(dst[1],dtUint32,{%H-}QWORD(oldptr) shr 32); + SetConst_q(dst[0],dtUint32,QWORD(oldptr)); + SetConst_q(dst[1],dtUint32,QWORD(oldptr) shr 32); SetPtr(newptr,btSetpc); end; -procedure TEmit_SOP1._emit_S_SETPC_B64; +procedure TEmit_SOP1.emit_S_SETPC_B64; Var - src:array[0..1] of PsrRegSlot; - node:array[0..1] of PsrRegNode; - pConst:array[0..1] of PsrConst; + src:array[0..1] of PsrRegNode; newptr:Pointer; - begin - Assert(not is_const_ssrc9(FSPI.SOP1.SSRC)); - if not FRegsStory.get_ssrc9_pair(FSPI.SOP1.SSRC,@src) then Assert(false); + if not fetch_ssrc9_pair(FSPI.SOP1.SSRC,@src,dtUnknow) then Assert(false); - node[0]:=RegDown(src[0]^.current); - node[1]:=RegDown(src[1]^.current); - - Assert(node[0]<>nil); - Assert(node[1]<>nil); - - if (node[0]^.is_const) and (node[1]^.is_const) then - begin - //ret of func - pConst[0]:=node[0]^.AsConst; - pConst[1]:=node[1]^.AsConst; - - {%H-}QWORD(newptr):=QWORD(pConst[0]^.AsUint) or (QWORD(pConst[1]^.AsUint) shl 32); - - SetPtr(newptr,btMain); - end else - begin - Assert(false); - end; + newptr:=GetFuncPtr(@src); + SetPtr(newptr,btMain); end; -procedure TEmit_SOP1._emit_S_AND_SAVEEXEC_B64; //sdst.du = EXEC;| EXEC = (ssrc.du & EXEC);| SCC = (sdst != 0) +procedure TEmit_SOP1.emit_S_AND_SAVEEXEC_B64; //sdst.du = EXEC;| EXEC = (ssrc.du & EXEC);| SCC = (sdst != 0) Var dst:array[0..1] of PsrRegSlot; src:array[0..1] of PsrRegNode; exc:array[0..1] of PsrRegNode; - begin + if not get_sdst7_pair(FSPI.SOP1.SDST,@dst) then Assert(False); - dst[0]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+0); - dst[1]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+1); + if not fetch_ssrc9_pair(FSPI.SOP1.SSRC,@src,dtUnknow) then Assert(False); //ssrc8 - Assert(dst[0]<>nil); - Assert(dst[1]<>nil); - - if not fetch_ssrc9_pair(@src,FSPI.SOP1.SSRC,dtUnknow) then Assert(False); //ssrc8 - - PrepTypeSlot(@FRegsStory.EXEC[0],dtUnknow); - PrepTypeSlot(@FRegsStory.EXEC[1],dtUnknow); - - exc[0]:=FRegsStory.EXEC[0].current; - exc[1]:=FRegsStory.EXEC[1].current; + exc[0]:=MakeRead(get_exec0,dtUnknow); + exc[1]:=MakeRead(get_exec1,dtUnknow); MakeCopy(dst[0],exc[0]); MakeCopy(dst[1],exc[1]); - exc[0]^.mark_read; - exc[1]^.mark_read; - - emit_OpBitwiseAnd(@FRegsStory.EXEC[0],src[0],exc[0]); - emit_OpBitwiseAnd(@FRegsStory.EXEC[1],src[1],exc[1]); + OpBitwiseAnd(get_exec0,src[0],exc[0]); + OpBitwiseAnd(get_exec1,src[1],exc[1]); //SCC = ((exc[0] != 0) or ((exc[1] != 0)) - exc[0]^.mark_read; - exc[1]^.mark_read; - - emit_OpLogicalOr(@FRegsStory.SCC,exc[0],exc[1]); //implict cast (int != 0) + OpLogicalOr(get_scc,exc[0],exc[1]); //implict cast (int != 0) //SCC = (sdst != 0) SCC = ((exc[0] != 0) or ((exc[1] != 0)) end; -procedure TEmit_SOP1._emit_S_WQM_B64; +procedure TEmit_SOP1.emit_S_WQM_B64; Var dst:array[0..1] of PsrRegSlot; src:array[0..1] of PsrRegNode; @@ -184,51 +160,24 @@ begin //dst[63:60].du = (ssrc[63:60].du != 0) ? 0xF : 0 //if (ssrc[3:0].du != 0) then dst[63:60].du=0xF else dst[63:60].du=0 - dst[0]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+0); - dst[1]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+1); + if not get_sdst7_pair(FSPI.SOP1.SDST,@dst) then Assert(False); - Assert(dst[0]<>nil); - Assert(dst[1]<>nil); + if not fetch_ssrc9_pair(FSPI.SOP1.SSRC,@src,dtUnknow) then Assert(False); //ssrc8 - if not fetch_ssrc9_pair(@src,FSPI.SOP1.SSRC,dtUnknow) then Assert(False); //ssrc8 - - emit_WQM_32(dst[0],src[0]); - emit_WQM_32(dst[1],src[1]); + OpWQM32(dst[0],src[0]); + OpWQM32(dst[1],src[1]); end; -procedure TEmit_SOP1._emit_SOP1; +procedure TEmit_SOP1.emit_SOP1; begin Case FSPI.SOP1.OP of - S_MOV_B32: - begin - _emit_S_MOV_B32; - end; - - S_MOV_B64: - begin - _emit_S_MOV_B64; - end; - - S_WQM_B64: - begin - _emit_S_WQM_B64; - end; - - S_SWAPPC_B64: - begin - _emit_S_SWAPPC_B64; - end; - - S_SETPC_B64: - begin - _emit_S_SETPC_B64; - end; - - S_AND_SAVEEXEC_B64: - begin - _emit_S_AND_SAVEEXEC_B64; - end; + S_MOV_B32 : emit_S_MOV_B32; + S_MOV_B64 : emit_S_MOV_B64; + S_WQM_B64 : emit_S_WQM_B64; + S_SWAPPC_B64 : emit_S_SWAPPC_B64; + S_SETPC_B64 : emit_S_SETPC_B64; + S_AND_SAVEEXEC_B64: emit_S_AND_SAVEEXEC_B64; else Assert(false,'SOP1?'+IntToStr(FSPI.SOP1.OP)); diff --git a/spirv/emit_sop2.pas b/spirv/emit_sop2.pas index 6e6ea51d..083720d2 100644 --- a/spirv/emit_sop2.pas +++ b/spirv/emit_sop2.pas @@ -6,359 +6,276 @@ interface uses sysutils, + spirv, ps4_pssl, - srTypes, - srConst, + srType, srReg, - SprvEmit, - emit_op; + emit_fetch; type - TEmit_SOP2=object(TEmitOp) - procedure _emit_SOP2; - procedure _emit_S_ADD_I32; - procedure _emit_S_MUL_I32; - procedure _emit_S_LSHL_B32; - procedure _emit_S_LSHR_B32; - procedure _emit_S_AND_B32; - procedure _emit_S_AND_B64; - procedure _emit_S_ANDN2_B64; - procedure _emit_S_OR_B64; - procedure _emit_S_NOR_B64; - procedure _emit_S_CSELECT_B32; - procedure _emit_S_CSELECT_B64; - procedure _emit_S_BFE_U32; + TEmit_SOP2=class(TEmitFetch) + procedure emit_SOP2; + procedure emit_S_ADD_I32; + procedure emit_S_MUL_I32; + procedure OpISccNotZero(src:PsrRegNode); + procedure emit_S_LSHL_B32; + procedure emit_S_LSHR_B32; + procedure emit_S_AND_B32; + procedure emit_S_AND_B64; + procedure emit_S_ANDN2_B64; + procedure emit_S_OR_B64; + procedure emit_S_NOR_B64; + procedure emit_S_CSELECT_B32; + procedure emit_S_CSELECT_B64; + procedure emit_S_BFE_U32; end; implementation -procedure TEmit_SOP2._emit_S_ADD_I32; +procedure TEmit_SOP2.emit_S_ADD_I32; Var dst,car:PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST); - car:=@FRegsStory.SCC; + dst:=get_sdst7(FSPI.SOP2.SDST); + car:=get_scc; src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtInt32); src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtInt32); - emit_OpIAddExt(dst,car,src[0],src[1]); + OpIAddExt(dst,car,src[0],src[1]); end; -procedure TEmit_SOP2._emit_S_MUL_I32; +procedure TEmit_SOP2.emit_S_MUL_I32; Var dst:PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST); + dst:=get_sdst7(FSPI.SOP2.SDST); src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtInt32); src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtInt32); - emit_OpIMul(dst,src[0],src[1]); + OpIMul(dst,src[0],src[1]); end; -procedure TEmit_SOP2._emit_S_LSHL_B32; //SCC = (sdst.u != 0) -Var - dst,tmp:PsrRegSlot; - src:array[0..2] of PsrRegNode; +procedure TEmit_SOP2.OpISccNotZero(src:PsrRegNode); //SCC = (sdst.u != 0) begin - dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST); - tmp:=@FRegsStory.FUnattach; - - src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUInt32); - src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUInt32); - - src[2]:=FetchReg(FConsts.Fetch(dtUInt32,31)); - emit_OpBitwiseAnd(tmp,src[1],src[2]); - src[1]:=MakeRead(tmp,dtUInt32); - - emit_OpShl(dst,src[0],src[1]); - - //dst = dtUint32 - - tmp:=@FRegsStory.SCC; - MakeCopy(tmp,dst^.current); - tmp^.current^.dtype:=dtBool; - - //dst^.current^.mark_read; - //emit_IntToBool(line,FRegsStory.SCC.New(dtBool),dst^.current); + MakeCopy(get_scc,src); + get_scc^.current^.dtype:=dtBool; //implict cast (int != 0) end; -procedure TEmit_SOP2._emit_S_LSHR_B32; //SCC = (sdst.u != 0) +procedure TEmit_SOP2.emit_S_LSHL_B32; Var - dst,tmp:PsrRegSlot; - src:array[0..2] of PsrRegNode; -begin - dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST); - tmp:=@FRegsStory.FUnattach; - - src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUInt32); - src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUInt32); - - src[2]:=FetchReg(FConsts.Fetch(dtUInt32,31)); - emit_OpBitwiseAnd(tmp,src[1],src[2]); - src[1]:=MakeRead(tmp,dtUInt32); - - emit_OpShr(dst,src[0],src[1]); - - tmp:=@FRegsStory.SCC; - MakeCopy(tmp,dst^.current); - tmp^.current^.dtype:=dtBool; -end; - -procedure TEmit_SOP2._emit_S_AND_B32; //SCC = (sdst.u != 0) -Var - dst,tmp:PsrRegSlot; + dst:PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST); + dst:=get_sdst7(FSPI.SOP2.SDST); src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUInt32); src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUInt32); - emit_OpBitwiseAnd(dst,src[0],src[1]); + src[1]:=OpBitwiseAndTo(src[1],31); + src[1]^.PrepType(ord(dtUInt32)); - tmp:=@FRegsStory.SCC; - MakeCopy(tmp,dst^.current); - tmp^.current^.dtype:=dtBool; + Op2(Op.OpShiftLeftLogical,src[0]^.dtype,dst,src[0],src[1]); + + OpISccNotZero(dst^.current); //SCC = (sdst.u != 0) end; -procedure TEmit_SOP2._emit_S_AND_B64; //SCC = (sdst[2] != 0) +procedure TEmit_SOP2.emit_S_LSHR_B32; +Var + dst:PsrRegSlot; + src:array[0..1] of PsrRegNode; +begin + dst:=get_sdst7(FSPI.SOP2.SDST); + + src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUInt32); + src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUInt32); + + src[1]:=OpBitwiseAndTo(src[1],31); + src[1]^.PrepType(ord(dtUInt32)); + + Op2(Op.OpShiftRightLogical,src[0]^.dtype,dst,src[0],src[1]); + + OpISccNotZero(dst^.current); //SCC = (sdst.u != 0) +end; + +procedure TEmit_SOP2.emit_S_AND_B32; +Var + dst:PsrRegSlot; + src:array[0..1] of PsrRegNode; +begin + dst:=get_sdst7(FSPI.SOP2.SDST); + + src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUInt32); + src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUInt32); + + OpBitwiseAnd(dst,src[0],src[1]); + + OpISccNotZero(dst^.current); //SCC = (sdst.u != 0) +end; + +procedure TEmit_SOP2.emit_S_AND_B64; //SCC = (sdst[2] != 0) Var dst:array[0..1] of PsrRegSlot; src0,src1,src2:array[0..1] of PsrRegNode; begin - if not FRegsStory.get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False); + if not get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False); - if not fetch_ssrc9_pair(@src0,FSPI.SOP2.SSRC0,dtUInt32) then Assert(False); - if not fetch_ssrc9_pair(@src1,FSPI.SOP2.SSRC1,dtUInt32) then Assert(False); + if not fetch_ssrc9_pair(FSPI.SOP2.SSRC0,@src0,dtUInt32) then Assert(False); + if not fetch_ssrc9_pair(FSPI.SOP2.SSRC1,@src1,dtUInt32) then Assert(False); - emit_OpBitwiseAnd(dst[0],src0[0],src1[0]); - emit_OpBitwiseAnd(dst[1],src0[1],src1[1]); + OpBitwiseAnd(dst[0],src0[0],src1[0]); + OpBitwiseAnd(dst[1],src0[1],src1[1]); src2[0]:=dst[0]^.current; src2[1]:=dst[1]^.current; - src2[0]^.mark_read; - src2[1]^.mark_read; - emit_OpLogicalOr(@FRegsStory.SCC,src2[0],src2[1]); //implict cast (int != 0) + OpLogicalOr(get_scc,src2[0],src2[1]); //implict cast (int != 0) end; -procedure TEmit_SOP2._emit_S_ANDN2_B64; //SCC = (sdst[2] != 0) -Var - dst:array[0..1] of PsrRegSlot; - tmp:PsrRegSlot; - src0,src1,src2:array[0..1] of PsrRegNode; -begin - if not FRegsStory.get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False); - - if not fetch_ssrc9_pair(@src0,FSPI.SOP2.SSRC0,dtUInt32) then Assert(False); - if not fetch_ssrc9_pair(@src1,FSPI.SOP2.SSRC1,dtUInt32) then Assert(False); - - tmp:=@FRegsStory.FUnattach; - - emit_OpNot(tmp,src1[0]); - src1[0]:=MakeRead(tmp,dtUnknow); - - emit_OpNot(tmp,src1[1]); - src1[1]:=MakeRead(tmp,dtUnknow); - - emit_OpBitwiseAnd(dst[0],src0[0],src1[0]); - emit_OpBitwiseAnd(dst[1],src0[1],src1[1]); - - src2[0]:=dst[0]^.current; - src2[1]:=dst[1]^.current; - - src2[0]^.mark_read; - src2[1]^.mark_read; - emit_OpLogicalOr(@FRegsStory.SCC,src2[0],src2[1]); //implict cast (int != 0) -end; - -procedure TEmit_SOP2._emit_S_OR_B64; //SCC = (sdst[2] != 0) +procedure TEmit_SOP2.emit_S_ANDN2_B64; //SCC = (sdst[2] != 0) Var dst:array[0..1] of PsrRegSlot; src0,src1,src2:array[0..1] of PsrRegNode; begin - if not FRegsStory.get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False); + if not get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False); - if not fetch_ssrc9_pair(@src0,FSPI.SOP2.SSRC0,dtUInt32) then Assert(False); - if not fetch_ssrc9_pair(@src1,FSPI.SOP2.SSRC1,dtUInt32) then Assert(False); + if not fetch_ssrc9_pair(FSPI.SOP2.SSRC0,@src0,dtUInt32) then Assert(False); + if not fetch_ssrc9_pair(FSPI.SOP2.SSRC1,@src1,dtUInt32) then Assert(False); - emit_OpBitwiseOr(dst[0],src0[0],src1[0]); - emit_OpBitwiseOr(dst[1],src0[1],src1[1]); + src1[0]:=OpNotTo(src1[0]); + src1[1]:=OpNotTo(src1[1]); + + OpBitwiseAnd(dst[0],src0[0],src1[0]); + OpBitwiseAnd(dst[1],src0[1],src1[1]); src2[0]:=dst[0]^.current; src2[1]:=dst[1]^.current; - src2[0]^.mark_read; - src2[1]^.mark_read; - emit_OpLogicalOr(@FRegsStory.SCC,src2[0],src2[1]); //implict cast (int != 0) + OpLogicalOr(get_scc,src2[0],src2[1]); //implict cast (int != 0) end; -procedure TEmit_SOP2._emit_S_NOR_B64; //SCC = (sdst[2] != 0) +procedure TEmit_SOP2.emit_S_OR_B64; //SCC = (sdst[2] != 0) Var dst:array[0..1] of PsrRegSlot; src0,src1,src2:array[0..1] of PsrRegNode; begin - if not FRegsStory.get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False); + if not get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False); - if not fetch_ssrc9_pair(@src0,FSPI.SOP2.SSRC0,dtUInt32) then Assert(False); - if not fetch_ssrc9_pair(@src1,FSPI.SOP2.SSRC1,dtUInt32) then Assert(False); + if not fetch_ssrc9_pair(FSPI.SOP2.SSRC0,@src0,dtUInt32) then Assert(False); + if not fetch_ssrc9_pair(FSPI.SOP2.SSRC1,@src1,dtUInt32) then Assert(False); - emit_OpBitwiseOr(dst[0],src0[0],src1[0]); - emit_OpBitwiseOr(dst[1],src0[1],src1[1]); + OpBitwiseOr(dst[0],src0[0],src1[0]); + OpBitwiseOr(dst[1],src0[1],src1[1]); src2[0]:=dst[0]^.current; src2[1]:=dst[1]^.current; - src2[0]^.mark_read; - src2[1]^.mark_read; - - emit_OpNot(dst[0],src2[0]); - emit_OpNot(dst[1],src2[1]); - - src2[0]:=dst[0]^.current; - src2[1]:=dst[1]^.current; - - src2[0]^.mark_read; - src2[1]^.mark_read; - - emit_OpLogicalOr(@FRegsStory.SCC,src2[0],src2[1]); //implict cast (int != 0) + OpLogicalOr(get_scc,src2[0],src2[1]); //implict cast (int != 0) end; -procedure TEmit_SOP2._emit_S_CSELECT_B32; //sdst = SCC ? ssrc0 : ssrc1 +procedure TEmit_SOP2.emit_S_NOR_B64; //SCC = (sdst[2] != 0) +Var + dst:array[0..1] of PsrRegSlot; + src0,src1,src2:array[0..1] of PsrRegNode; +begin + if not get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False); + + if not fetch_ssrc9_pair(FSPI.SOP2.SSRC0,@src0,dtUInt32) then Assert(False); + if not fetch_ssrc9_pair(FSPI.SOP2.SSRC1,@src1,dtUInt32) then Assert(False); + + src2[0]:=OpBitwiseOrTo(src0[0],src1[0]); + src2[1]:=OpBitwiseOrTo(src0[1],src1[1]); + + OpNot(dst[0],src2[0]); + OpNot(dst[1],src2[1]); + + src2[0]:=dst[0]^.current; + src2[1]:=dst[1]^.current; + + OpLogicalOr(get_scc,src2[0],src2[1]); //implict cast (int != 0) +end; + +procedure TEmit_SOP2.emit_S_CSELECT_B32; //sdst = SCC ? ssrc0 : ssrc1 Var dst:PsrRegSlot; src:array[0..1] of PsrRegNode; scc:PsrRegNode; begin - dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST); + dst:=get_sdst7(FSPI.SOP2.SDST); src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUnknow); src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUnknow); - scc:=MakeRead(@FRegsStory.SCC,dtBool); + scc:=MakeRead(get_scc,dtBool); - emit_OpSelect(dst,src[0],src[1],scc); + OpSelect(dst,src[0],src[1],scc); end; -procedure TEmit_SOP2._emit_S_CSELECT_B64; //sdst[2] = SCC ? ssrc0[2] : ssrc1[2] +procedure TEmit_SOP2.emit_S_CSELECT_B64; //sdst[2] = SCC ? ssrc0[2] : ssrc1[2] Var dst:array[0..1] of PsrRegSlot; src0,src1:array[0..1] of PsrRegNode; scc:PsrRegNode; begin - if not FRegsStory.get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False); + if not get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False); - if not fetch_ssrc9_pair(@src0,FSPI.SOP2.SSRC0,dtUnknow) then Assert(False); - if not fetch_ssrc9_pair(@src1,FSPI.SOP2.SSRC1,dtUnknow) then Assert(False); + if not fetch_ssrc9_pair(FSPI.SOP2.SSRC0,@src0,dtUnknow) then Assert(False); + if not fetch_ssrc9_pair(FSPI.SOP2.SSRC1,@src1,dtUnknow) then Assert(False); - scc:=MakeRead(@FRegsStory.SCC,dtBool); - scc^.mark_read; + scc:=MakeRead(get_scc,dtBool); - emit_OpSelect(dst[0],src0[0],src1[0],scc); - emit_OpSelect(dst[1],src0[1],src1[1],scc); + OpSelect(dst[0],src0[0],src1[0],scc); + OpSelect(dst[1],src0[1],src1[1],scc); end; //offset = ssrc1[4:0].u and 31 //width = ssrc1[22:16].u shr 16 -procedure TEmit_SOP2._emit_S_BFE_U32; //sdst.u = bitFieldExtract(ssrc0); SCC = (sdst.u != 0) +procedure TEmit_SOP2.emit_S_BFE_U32; //sdst.u = bitFieldExtract(ssrc0); SCC = (sdst.u != 0) Var - dst,tmp:PsrRegSlot; + dst:PsrRegSlot; src:array[0..1] of PsrRegNode; - num_31,num_16:PsrRegNode; offset,count:PsrRegNode; begin - dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST); - tmp:=@FRegsStory.FUnattach; + dst:=get_sdst7(FSPI.SOP2.SDST); src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUint32); src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUint32); - num_31:=FetchReg(FConsts.Fetch(dtUInt32,31)); + offset:=OpBitwiseAndTo(src[1],31); + count :=OpShrTo(src[1],16); - emit_OpBitwiseAnd(tmp,src[1],num_31); - offset:=MakeRead(tmp,dtUInt32); + Op3(Op.OpBitFieldUExtract,dtUInt32,dst,src[0],offset,count); - num_16:=FetchReg(FConsts.Fetch(dtUInt32,16)); - - src[1]^.mark_read; - emit_OpShr(tmp,src[1],num_16); - count:=MakeRead(tmp,dtUInt32); - - emit_OpBfeU(dst,src[0],offset,count); - - tmp:=@FRegsStory.SCC; - MakeCopy(tmp,dst^.current); - tmp^.current^.dtype:=dtBool; + OpISccNotZero(dst^.current); //SCC = (sdst.u != 0) end; -procedure TEmit_SOP2._emit_SOP2; +procedure TEmit_SOP2.emit_SOP2; begin Case FSPI.SOP2.OP of - S_ADD_I32: - begin - _emit_S_ADD_I32; - end; + S_ADD_I32: emit_S_ADD_I32; + S_MUL_I32: emit_S_MUL_I32; - S_MUL_I32: //& 0xFFFFFFFF - begin - _emit_S_MUL_I32; - end; + S_LSHL_B32: emit_S_LSHL_B32; + S_LSHR_B32: emit_S_LSHR_B32; - S_LSHL_B32: //SCC = (sdst.u != 0) - begin - _emit_S_LSHL_B32; - end; + S_AND_B32: emit_S_AND_B32; + S_AND_B64: emit_S_AND_B64; - S_LSHR_B32: - begin - _emit_S_LSHR_B32; - end; + S_ANDN2_B64: emit_S_ANDN2_B64; - S_AND_B32: - begin - _emit_S_AND_B32; - end; + S_OR_B64: emit_S_OR_B64; - S_AND_B64: - begin - _emit_S_AND_B64; - end; + S_NOR_B64: emit_S_NOR_B64; - S_ANDN2_B64: - begin - _emit_S_ANDN2_B64; - end; + S_CSELECT_B32: emit_S_CSELECT_B32; + S_CSELECT_B64: emit_S_CSELECT_B64; - S_OR_B64: - begin - _emit_S_OR_B64; - end; - - S_NOR_B64: - begin - _emit_S_NOR_B64; - end; - - S_CSELECT_B32: - begin - _emit_S_CSELECT_B32; - end; - - S_CSELECT_B64: - begin - _emit_S_CSELECT_B64; - end; - - S_BFE_U32: - begin - _emit_S_BFE_U32; - end; + S_BFE_U32: emit_S_BFE_U32; else Assert(False,'SOP2?'+IntToStr(FSPI.SOP2.OP)); diff --git a/spirv/emit_sopc.pas b/spirv/emit_sopc.pas index 03d1cc47..60b7665e 100644 --- a/spirv/emit_sopc.pas +++ b/spirv/emit_sopc.pas @@ -8,48 +8,47 @@ uses sysutils, spirv, ps4_pssl, - srTypes, + srType, srReg, - SprvEmit, - emit_op; + emit_fetch; type - TEmit_SOPC=object(TEmitOp) - procedure _emit_SOPC; - procedure _emit_S_CMP_32(OpId:DWORD;rtype:TsrDataType); + TEmit_SOPC=class(TEmitFetch) + procedure emit_SOPC; + procedure emit_S_CMP_32(OpId:DWORD;rtype:TsrDataType); end; implementation -procedure TEmit_SOPC._emit_S_CMP_32(OpId:DWORD;rtype:TsrDataType); +procedure TEmit_SOPC.emit_S_CMP_32(OpId:DWORD;rtype:TsrDataType); Var dst:PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst:=@FRegsStory.SCC; + dst:=get_scc; src[0]:=fetch_ssrc9(FSPI.SOPC.SSRC0,rtype); src[1]:=fetch_ssrc9(FSPI.SOPC.SSRC1,rtype); - emit_OpCmpS(OpId,dst,src[0],src[1]); + OpCmpS(OpId,dst,src[0],src[1]); end; -procedure TEmit_SOPC._emit_SOPC; +procedure TEmit_SOPC.emit_SOPC; begin Case FSPI.SOPC.OP of - S_CMP_EQ_I32 :_emit_S_CMP_32(Op.OpIEqual ,dtInt32); - S_CMP_LG_I32 :_emit_S_CMP_32(Op.OpINotEqual ,dtInt32); - S_CMP_GT_I32 :_emit_S_CMP_32(Op.OpSGreaterThan ,dtInt32); - S_CMP_GE_I32 :_emit_S_CMP_32(Op.OpSGreaterThanEqual,dtInt32); - S_CMP_LT_I32 :_emit_S_CMP_32(Op.OpSLessThan ,dtInt32); - S_CMP_LE_I32 :_emit_S_CMP_32(Op.OpSLessThanEqual ,dtInt32); + S_CMP_EQ_I32 :emit_S_CMP_32(Op.OpIEqual ,dtInt32); + S_CMP_LG_I32 :emit_S_CMP_32(Op.OpINotEqual ,dtInt32); + S_CMP_GT_I32 :emit_S_CMP_32(Op.OpSGreaterThan ,dtInt32); + S_CMP_GE_I32 :emit_S_CMP_32(Op.OpSGreaterThanEqual,dtInt32); + S_CMP_LT_I32 :emit_S_CMP_32(Op.OpSLessThan ,dtInt32); + S_CMP_LE_I32 :emit_S_CMP_32(Op.OpSLessThanEqual ,dtInt32); - S_CMP_EQ_U32 :_emit_S_CMP_32(Op.OpIEqual ,dtUint32); - S_CMP_LG_U32 :_emit_S_CMP_32(Op.OpINotEqual ,dtUint32); - S_CMP_GT_U32 :_emit_S_CMP_32(Op.OpUGreaterThan ,dtUint32); - S_CMP_GE_U32 :_emit_S_CMP_32(Op.OpUGreaterThanEqual,dtUint32); - S_CMP_LT_U32 :_emit_S_CMP_32(Op.OpULessThan ,dtUint32); - S_CMP_LE_U32 :_emit_S_CMP_32(Op.OpULessThanEqual ,dtUint32); + S_CMP_EQ_U32 :emit_S_CMP_32(Op.OpIEqual ,dtUint32); + S_CMP_LG_U32 :emit_S_CMP_32(Op.OpINotEqual ,dtUint32); + S_CMP_GT_U32 :emit_S_CMP_32(Op.OpUGreaterThan ,dtUint32); + S_CMP_GE_U32 :emit_S_CMP_32(Op.OpUGreaterThanEqual,dtUint32); + S_CMP_LT_U32 :emit_S_CMP_32(Op.OpULessThan ,dtUint32); + S_CMP_LE_U32 :emit_S_CMP_32(Op.OpULessThanEqual ,dtUint32); //S_BITCMP0_B32:; //S_BITCMP1_B32:; diff --git a/spirv/emit_sopk.pas b/spirv/emit_sopk.pas index 0b9918af..840f7a14 100644 --- a/spirv/emit_sopk.pas +++ b/spirv/emit_sopk.pas @@ -7,39 +7,32 @@ interface uses sysutils, ps4_pssl, - srTypes, - srConst, + srType, srReg, - SprvEmit, - emit_op; + emit_fetch; type - TEmit_SOPK=object(TEmitOp) - procedure _emit_SOPK; - procedure _emit_S_MOVK_I32; + TEmit_SOPK=class(TEmitFetch) + procedure emit_SOPK; + procedure emit_S_MOVK_I32; end; implementation -procedure TEmit_SOPK._emit_S_MOVK_I32; +procedure TEmit_SOPK.emit_S_MOVK_I32; Var dst:PsrRegSlot; - src:PsrRegNode; begin - dst:=FRegsStory.get_sdst7(FSPI.SOPK.SDST); - src:=FetchReg(FConsts.Fetchi(dtInt32,SmallInt(FSPI.SOPK.SIMM))); - _MakeCopy(dst,src); + dst:=get_sdst7(FSPI.SOPK.SDST); + SetConst_i(dst,dtInt32,SmallInt(FSPI.SOPK.SIMM)); end; -procedure TEmit_SOPK._emit_SOPK; +procedure TEmit_SOPK.emit_SOPK; begin Case FSPI.SOPK.OP of - S_MOVK_I32: - begin - _emit_S_MOVK_I32; - end; + S_MOVK_I32: emit_S_MOVK_I32; else Assert(false,'SOPK?'+IntToStr(FSPI.SOPK.OP)); diff --git a/spirv/emit_sopp.pas b/spirv/emit_sopp.pas index 73ad8e8d..8b18ab81 100644 --- a/spirv/emit_sopp.pas +++ b/spirv/emit_sopp.pas @@ -7,22 +7,23 @@ interface uses sysutils, ps4_pssl, - srTypes, - srParser, - srLabel, - srCFG, + srType, + srCFGParser, + srCFGLabel, + srCFGCursor, + srFlow, srReg, srOp, srOpUtils, spirv, - SprvEmit, - emit_op; + emit_fetch; type - TEmit_SOPP=object(TEmitOp) - procedure _emit_SOPP; - procedure _emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean); - procedure _emit_S_BRANCH; + TEmit_SOPP=class(TEmitFetch) + procedure emit_SOPP; + procedure emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean); + procedure emit_S_BRANCH; + procedure mark_end_of; function IsBegLoop(Adr:TSrcAdr):Boolean; function IsEndLoop(Adr:TSrcAdr):Boolean; function IsUnknow(Adr:TSrcAdr):Boolean; @@ -35,9 +36,6 @@ type implementation -uses - srVolatile; - procedure TEmit_SOPP.emit_cond_block(pSlot:PsrRegSlot;n:Boolean;adr:TSrcAdr); var src:PsrRegNode; @@ -49,11 +47,11 @@ var begin src:=MakeRead(pSlot,dtBool); //get before OpBranchConditional - pOpLabel[0]:=NewLabelOp; - pOpLabel[1]:=NewLabelOp; + pOpLabel[0]:=NewLabelOp(False); + pOpLabel[1]:=NewLabelOp(False); - pLBlock:=FCursor.pCode^.FTop.DownBlock(adr); - Assert(pLBlock<>@FCursor.pCode^.FTop,'not found'); + pLBlock:=Cursor.pCode^.FTop.DownBlock(adr); + Assert(pLBlock<>@Cursor.pCode^.FTop,'not found'); Info[0]:=Default(TsrBlockInfo); Info[1]:=Default(TsrBlockInfo); @@ -61,8 +59,8 @@ begin Case pLBlock^.bType of btAdr: //set new adr begin - Info[0].b_adr:=FCursor.Adr; - Info[0].e_adr:=FCursor.Adr; + Info[0].b_adr:=Cursor.Adr; + Info[0].e_adr:=Cursor.Adr; Info[0].bType:=btCond; // Info[1].b_adr:=pLBlock^.pBLabel^.Adr; @@ -86,18 +84,18 @@ begin pOpLabel[0]^.Adr:=Info[0].b_adr; pOpLabel[1]^.Adr:=Info[0].e_adr; - pOpBlock:=NewBlockOp(FRegsStory.get_snapshot); + pOpBlock:=NewBlockOp(get_snapshot); pOpBlock^.SetLabels(pOpLabel[0],pOpLabel[1],nil); pOpBlock^.SetInfo(Info[0]); pOpBlock^.SetCond(src,not n); PushBlockOp(line,pOpBlock,pLBlock); - emit_OpCondMerge(line,pOpLabel[1]); + OpCondMerge(line,pOpLabel[1]); Case n of - True :emit_OpBranchCond(line,pOpLabel[1],pOpLabel[0],src); - False:emit_OpBranchCond(line,pOpLabel[0],pOpLabel[1],src); + True :OpBranchCond(line,pOpLabel[1],pOpLabel[0],src); + False:OpBranchCond(line,pOpLabel[0],pOpLabel[1],src); end; AddSpirvOp(line,pOpLabel[0]); @@ -117,57 +115,56 @@ procedure TEmit_SOPP.UpBuildVol(last:PsrOpBlock); var node:PsrOpBlock; begin - node:=FMain^.pBlock; + node:=Main^.pBlock; While (node<>nil) do begin Case node^.Block.bType of - btCond:TEmitVolatile(Self).build_volatile_cur(node^.Regs.pSnap); - btLoop:TEmitVolatile(Self).build_volatile_old(node^.Regs.pSnap); + btCond:PrivateList.build_volatile_cur(node^.Regs.pSnap); + btLoop:PrivateList.build_volatile_old(node^.Regs.pSnap); else; end; if (node=last) then Break; - node:=node^.pParent; + node:=node^.Parent; end; end; procedure TEmit_SOPP.emit_loop(adr:TSrcAdr); var node,pOpBlock:PsrOpBlock; - pOpLabel:array[0..1] of PspirvOp; + pOpLabel:PspirvOp; FVolMark:TsrVolMark; bnew:Boolean; begin - - node:=FMain^.pBlock; + node:=Main^.pBlock; pOpBlock:=node^.FindUpLoop; Assert(pOpBlock<>nil,'not found'); - pOpLabel[0]:=nil; + pOpLabel:=nil; FVolMark:=vmNone; if (pOpBlock^.Block.b_adr.get_pc=adr.get_pc) then //is continue? begin - pOpLabel[0]:=pOpBlock^.Labels.pMrgOp; //-> OpLoopMerge end -> OpLoopMerge before + pOpLabel:=pOpBlock^.Labels.pMrgOp; //-> OpLoopMerge end -> OpLoopMerge before pOpBlock^.Cond.FUseCont:=True; FVolMark:=vmCont; end else if (pOpBlock^.Block.b_adr.get_pc=adr.get_pc) then //is break? begin - pOpLabel[0]:=pOpBlock^.Labels.pEndOp; + pOpLabel:=pOpBlock^.Labels.pEndOp; FVolMark:=vmBreak; end else begin Assert(false,'emit_loop'); end; - Assert(pOpLabel[0]<>nil); + Assert(pOpLabel<>nil); bnew:=true; - if FCursor.pBlock^.IsEndOf(FCursor.Adr) then //is last + if Cursor.pBlock^.IsEndOf(Cursor.Adr) then //is last begin - Assert(node^.Block.e_adr.get_pc=FCursor.Adr.get_pc); + Assert(node^.Block.e_adr.get_pc=Cursor.Adr.get_pc); Case node^.Block.bType of btSetpc:; else @@ -180,11 +177,10 @@ begin UpBuildVol(pOpBlock); node^.Regs.FVolMark:=FVolMark; //mark end of - emit_OpBranch(line,pOpLabel[0]); + OpBranch(line,pOpLabel); if bnew then begin - pOpLabel[1]:=NewLabelOp; - AddSpirvOp(line,pOpLabel[1]); + AddSpirvOp(line,NewLabelOp(True)); end; end; @@ -197,7 +193,7 @@ var begin src:=MakeRead(pSlot,dtBool); - node:=FMain^.pBlock; + node:=Main^.pBlock; pOpBlock:=node^.FindUpLoop; Assert(pOpBlock<>nil,'not found'); @@ -220,16 +216,16 @@ begin end; Assert(pOpLabel[0]<>nil); - pOpLabel[1]:=NewLabelOp; + pOpLabel[1]:=NewLabelOp(False); UpBuildVol(pOpBlock); node^.Regs.FVolMark:=FVolMark; //mark end of - emit_OpCondMerge(line,pOpLabel[1]); + OpCondMerge(line,pOpLabel[1]); Case n of - True :emit_OpBranchCond(line,pOpLabel[0],pOpLabel[1],src); - False:emit_OpBranchCond(line,pOpLabel[1],pOpLabel[0],src); + True :OpBranchCond(line,pOpLabel[0],pOpLabel[1],src); + False:OpBranchCond(line,pOpLabel[1],pOpLabel[0],src); end; AddSpirvOp(line,pOpLabel[1]); @@ -240,7 +236,7 @@ var node:PsrCFGBlock; begin Result:=false; - node:=FCursor.pBlock^.FindUpLoop; + node:=Cursor.pBlock^.FindUpLoop; if (node<>nil) then begin Result:=node^.pBLabel^.Adr.get_pc=Adr.get_pc; @@ -252,7 +248,7 @@ var node:PsrCFGBlock; begin Result:=false; - node:=FCursor.pBlock^.FindUpLoop; + node:=Cursor.pBlock^.FindUpLoop; if (node<>nil) then begin Result:=node^.pELabel^.Adr.get_pc=Adr.get_pc; @@ -269,13 +265,12 @@ begin Result:=pLabel^.IsType(ltUnknow); end; -procedure TEmit_SOPP._emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean); +procedure TEmit_SOPP.emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean); var c_adr,b_adr:TSrcAdr; pLabel:PsrLabel; - begin - c_adr:=FCursor.Adr; + c_adr:=Cursor.Adr; b_adr:=c_adr; b_adr.Offdw:=get_branch_offset(FSPI); @@ -293,7 +288,7 @@ begin emit_loop_cond(pSlot,n,b_adr); end else begin //down - if FCursor.pBlock^.IsBigOf(b_adr) then + if Cursor.pBlock^.IsBigOf(b_adr) then begin //break? if not IsEndLoop(b_adr) then Assert(false,'Unknow'); emit_loop_cond(pSlot,n,b_adr); @@ -314,9 +309,9 @@ var begin Info:=Default(TsrBlockInfo); - c_adr:=FCursor.Adr; //get current + c_adr:=Cursor.Adr; //get current SetPtr(adr.get_pc,btAdrBranch); //set new - e_adr:=FCursor.pCode^.FTop.pELabel^.Adr; //get end of code + e_adr:=Cursor.pCode^.FTop.pELabel^.Adr; //get end of code SetPtr(c_adr.get_pc,btMain); //ret current Info.b_adr:=adr; @@ -331,12 +326,12 @@ begin SetPtr(adr.get_pc,btAdrBranch); end; -procedure TEmit_SOPP._emit_S_BRANCH; +procedure TEmit_SOPP.emit_S_BRANCH; var c_adr,b_adr:TSrcAdr; begin - c_adr:=FCursor.Adr; + c_adr:=Cursor.Adr; b_adr:=c_adr; b_adr.Offdw:=get_branch_offset(FSPI); @@ -356,7 +351,12 @@ begin end; -procedure TEmit_SOPP._emit_SOPP; +procedure TEmit_SOPP.mark_end_of; +begin + Main^.pBlock^.Regs.FVolMark:=vmEnd; //mark end of +end; + +procedure TEmit_SOPP.emit_SOPP; begin Case FSPI.SOPP.OP of S_NOP, @@ -368,17 +368,17 @@ begin begin AddSpirvOp(Op.OpReturn); end; - FMain^.pBlock^.Regs.FVolMark:=vmEnd; //mark end of + mark_end_of; end; - S_CBRANCH_SCC0 :_emit_S_BRANCH_COND(@FRegsStory.SCC,false); - S_CBRANCH_SCC1 :_emit_S_BRANCH_COND(@FRegsStory.SCC,true); - S_CBRANCH_VCCZ :_emit_S_BRANCH_COND(@FRegsStory.VCC[0],false); - S_CBRANCH_VCCNZ :_emit_S_BRANCH_COND(@FRegsStory.VCC[0],true); - S_CBRANCH_EXECZ :_emit_S_BRANCH_COND(@FRegsStory.EXEC[0],false); - S_CBRANCH_EXECNZ:_emit_S_BRANCH_COND(@FRegsStory.EXEC[0],true); + S_CBRANCH_SCC0 :emit_S_BRANCH_COND(get_scc ,false); + S_CBRANCH_SCC1 :emit_S_BRANCH_COND(get_scc ,true); + S_CBRANCH_VCCZ :emit_S_BRANCH_COND(get_vcc0 ,false); + S_CBRANCH_VCCNZ :emit_S_BRANCH_COND(get_vcc0 ,true); + S_CBRANCH_EXECZ :emit_S_BRANCH_COND(get_exec0,false); + S_CBRANCH_EXECNZ:emit_S_BRANCH_COND(get_exec0,true); - S_BRANCH :_emit_S_BRANCH; + S_BRANCH :emit_S_BRANCH; else Assert(false,'SOPP?'+IntToStr(FSPI.SOPP.OP)); diff --git a/spirv/emit_vbuf_chain.pas b/spirv/emit_vbuf_chain.pas index 875616c8..f3981215 100644 --- a/spirv/emit_vbuf_chain.pas +++ b/spirv/emit_vbuf_chain.pas @@ -8,12 +8,12 @@ uses sysutils, ps4_shader, ps4_pssl, - srTypes, + srType, srConst, srReg, srLayout, - SprvEmit, - emit_op, + srConfig, + emit_fetch, srVBufInfo; type @@ -30,11 +30,7 @@ type data:array[0..1] of Pointer; end; - TEmit_vbuf_chain=object(TEmitOp) - function OpDivTo(pReg:PsrRegNode;i:QWORD):PsrRegNode; - function OpMulTo(pReg:PsrRegNode;i:QWORD):PsrRegNode; - function OpAddTo(pReg:PsrRegNode;i:QWORD):PsrRegNode; - function OpAddTo(pReg0,pReg1:PsrRegNode):PsrRegNode; + TEmit_vbuf_chain=class(TEmitFetch) procedure get_reg_adr(var adr:TBuf_adr); function get_sum_ofs(var adr:TBuf_adr):PsrRegNode; function get_idx_elm(var adr:TBuf_adr):PsrRegNode; @@ -44,76 +40,6 @@ type implementation -function isPowerOfTwo(x:QWORD):Boolean; inline; -begin - Result:=((x-1) and x)=0; -end; - -function fastIntLog2(i:QWORD):QWORD; inline; -begin - Result:=BsfQWORD(i); -end; - -function TEmit_vbuf_chain.OpDivTo(pReg:PsrRegNode;i:QWORD):PsrRegNode; -begin - if (pReg=nil) or (i<=1) then Exit(pReg); - Result:=NewReg(pReg^.dtype); - pReg^.mark_read; - if isPowerOfTwo(i) then - begin - i:=fastIntLog2(i); - if (SignType(pReg^.dtype)<>0) then - begin - _emit_OpShrA(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i))); - end else - begin - _emit_OpShr(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i))); - end; - end else - begin - if (SignType(pReg^.dtype)<>0) then - begin - _emit_OpSDiv(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i))); - end else - begin - _emit_OpUDiv(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i))); - end; - end; -end; - -function TEmit_vbuf_chain.OpMulTo(pReg:PsrRegNode;i:QWORD):PsrRegNode; -begin - if (pReg=nil) or (i<=1) then Exit(pReg); - Result:=NewReg(pReg^.dtype); - pReg^.mark_read; - if isPowerOfTwo(i) then - begin - i:=fastIntLog2(i); - _emit_OpShl(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i))); - end else - begin - _emit_OpIMul(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i))); - end; -end; - -function TEmit_vbuf_chain.OpAddTo(pReg:PsrRegNode;i:QWORD):PsrRegNode; -begin - if (pReg=nil) or (i=0) then Exit(pReg); - Result:=NewReg(pReg^.dtype); - pReg^.mark_read; - _emit_OpIAdd(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i))); -end; - -function TEmit_vbuf_chain.OpAddTo(pReg0,pReg1:PsrRegNode):PsrRegNode; -begin - if (pReg0=nil) then Exit(pReg1); - if (pReg1=nil) then Exit(pReg0); - Result:=NewReg(pReg0^.dtype); - pReg0^.mark_read; - pReg1^.mark_read; - _emit_OpIAdd(line,Result,pReg0,pReg1); -end; - procedure TEmit_vbuf_chain.get_reg_adr(var adr:TBuf_adr); var ofs:PsrRegSlot; @@ -123,7 +49,7 @@ begin adr.soffset:=get_soffset_const_int(FSPI.MUBUF.SOFFSET); end else begin - ofs:=FRegsStory.get_ssrc8(FSPI.MUBUF.SOFFSET); + ofs:=get_ssrc8(FSPI.MUBUF.SOFFSET); if (ofs<>nil) then begin adr.sof:=ofs^.current; @@ -131,7 +57,7 @@ begin begin if (adr.sof^.is_const) then begin - adr.soffset:=adr.sof^.AsConst^.AsInt; + adr.soffset:=adr.sof^.AsConst^.AsInt32; adr.sof:=nil; end else begin @@ -147,12 +73,12 @@ begin adr.idx:=fetch_vsrc8(FSPI.MUBUF.VADDR+0,dtInt32); if (FSPI.MUBUF.OFFEN=1) then begin - ofs:=FRegsStory.get_vsrc8(FSPI.MUBUF.VADDR+1); + ofs:=get_vsrc8(FSPI.MUBUF.VADDR+1); end; end else if (FSPI.MUBUF.OFFEN=1) then begin - ofs:=FRegsStory.get_vsrc8(FSPI.MUBUF.VADDR+0); + ofs:=get_vsrc8(FSPI.MUBUF.VADDR+0); end; if (ofs<>nil) then @@ -162,7 +88,7 @@ begin begin if (adr.ofs^.is_const) then begin - adr.voffset:=adr.ofs^.AsConst^.AsInt; + adr.voffset:=adr.ofs^.AsConst^.AsInt32; adr.ofs:=nil; end else begin @@ -190,15 +116,13 @@ begin //(stride is Align) //result=(foffset/Align+ofs/Align+idx*(stride/Align)) in elem - adr.ofs^.mark_unread; - ofs_d:=OpDivTo(adr.ofs,adr.align); //ofs/Align - sum_d:=OpAddTo(ofs_d,foffset div adr.align); //foffset/Align+ofs/Align + ofs_d:=OpIDivTo(adr.ofs,adr.align); //ofs/Align + sum_d:=OpIAddTo(ofs_d,foffset div adr.align); //foffset/Align+ofs/Align if (adr.idx<>nil) then begin - adr.idx^.mark_unread; - idx_m:=OpMulTo(adr.idx,adr.stride div adr.align); //idx*(stride/Align) - sum_d:=OpAddTo(sum_d,idx_m); + idx_m:=OpIMulTo(adr.idx,adr.stride div adr.align); //idx*(stride/Align) + sum_d:=OpIAddTo(sum_d,idx_m); end; end else @@ -206,17 +130,15 @@ begin //result=(foffset+ofs+idx*stride)/Align in elem - adr.ofs^.mark_unread; - sum_d:=OpAddTo(adr.ofs,foffset); //foffset+ofs + sum_d:=OpIAddTo(adr.ofs,foffset); //foffset+ofs if (adr.idx<>nil) then begin - adr.idx^.mark_unread; - idx_m:=OpMulTo(adr.idx,adr.stride); //idx*stride - sum_d:=OpAddTo(sum_d,idx_m); + idx_m:=OpIMulTo(adr.idx,adr.stride); //idx*stride + sum_d:=OpIAddTo(sum_d,idx_m); end; - sum_d:=OpDivTo(sum_d,adr.align); // sum/Align + sum_d:=OpIDivTo(sum_d,adr.align); // sum/Align end; Result:=sum_d; @@ -236,13 +158,11 @@ begin if (adr.idx=nil) then begin - sum_d:=FetchReg(FConsts.Fetchi(dtUint32,foffset)); - sum_d^.mark_unread; + sum_d:=NewReg_q(dtUint32,foffset); end else begin - adr.idx^.mark_unread; - idx_m:=OpMulTo(adr.idx,adr.stride div adr.align); //idx*(stride/Align) - sum_d:=OpAddTo(idx_m,foffset); + idx_m:=OpIMulTo(adr.idx,adr.stride div adr.align); //idx*(stride/Align) + sum_d:=OpIAddTo(idx_m,foffset); end; Result:=sum_d; @@ -262,13 +182,11 @@ begin if (adr.idx=nil) then begin - sum_d:=FetchReg(FConsts.Fetchi(dtUint32,foffset)); - sum_d^.mark_unread; + sum_d:=NewReg_q(dtUint32,foffset); end else begin - adr.idx^.mark_unread; - idx_m:=OpMulTo(adr.idx,adr.stride div adr.fsize); //idx*(stride/size) - sum_d:=OpAddTo(idx_m,foffset); + idx_m:=OpIMulTo(adr.idx,adr.stride div adr.fsize); //idx*(stride/size) + sum_d:=OpIAddTo(idx_m,foffset); end; Result:=sum_d; @@ -288,7 +206,8 @@ var sum_d:PsrRegNode; - ext:TsrChainExt; + lvl_0:TsrChainLvl_0; + lvl_1:TsrChainLvl_1; img:TsrImageInfo; @@ -322,9 +241,11 @@ begin if (adr.ofs=nil) and (adr.idx=nil) then //simple begin - Result.vType :=vcChainVector; - Result.data[0]:=info.grp^.Fetch(foffset,adr.csize,nil); + lvl_0.offset:=foffset; + lvl_0.size :=adr.csize; + Result.data[0]:=info.grp^.Fetch(@lvl_0,nil); + Result.vType :=vcChainVector; Exit; end; @@ -335,7 +256,7 @@ begin sum_d:=get_sum_ofs(adr); //minTexelBufferOffsetAlignment - if FUseTexelBuffer then + if Config.UseTexelBuffer then if (info.IsComp) and (adr.stride div adr.align=0) then begin @@ -350,21 +271,21 @@ begin Exit; end; - sum_d^.mark_read; - ext:=Default(TsrChainExt); - ext.pIndex:=sum_d; - ext.stride:=adr.align; + lvl_0.offset:=0; + lvl_0.size :=adr.align; + + lvl_1.pIndex:=sum_d; + lvl_1.stride:=adr.align; + + Result.data[0]:=info.grp^.Fetch(@lvl_0,@lvl_1); - Result:=Default(TvarChain); Result.vType :=vcChainElement; - Result.data[0]:=info.grp^.Fetch(0,adr.align,@ext); - Exit; end else begin //idx<>nil //minTexelBufferOffsetAlignment - if FUseTexelBuffer then + if Config.UseTexelBuffer then if (info.IsComp) and (adr.stride mod adr.fsize=0) and (foffset mod adr.fsize=0) then @@ -383,7 +304,7 @@ begin end; //minTexelBufferOffsetAlignment - if FUseTexelBuffer then + if Config.UseTexelBuffer then if (info.IsComp) and (adr.stride div adr.align=0) then begin @@ -400,14 +321,15 @@ begin Exit; end; - //adr.idx^.mark_read; - ext:=Default(TsrChainExt); - ext.pIndex:=adr.idx; - ext.stride:=adr.stride; + lvl_0.offset:=foffset; + lvl_0.size :=adr.csize; + + lvl_1.pIndex:=adr.idx; + lvl_1.stride:=adr.stride; + + Result.data[0]:=info.grp^.Fetch(@lvl_0,@lvl_1); Result.vType :=vcChainVector; - Result.data[0]:=info.grp^.Fetch(foffset,adr.csize,@ext); - Exit; end; diff --git a/spirv/emit_vbuf_load.pas b/spirv/emit_vbuf_load.pas index 5c59915a..cf6ecd0f 100644 --- a/spirv/emit_vbuf_load.pas +++ b/spirv/emit_vbuf_load.pas @@ -6,14 +6,11 @@ interface uses sysutils, - spirv, ps4_pssl, - srTypes, - srConst, + srType, srReg, srLayout, - SprvEmit, - emit_op, + emit_fetch, srVBufInfo, emit_vbuf_chain; @@ -29,21 +26,15 @@ type elm:array[0..3] of PsrRegNode; end; - TEmit_vbuf_load=object(TEmitOp) + TEmit_vbuf_load=class(TEmitFetch) procedure buf_load(info:TBuf_info); - function OpMulF(pReg:PsrRegNode;s:Single):PsrRegNode; - function OpAddF(pReg:PsrRegNode;s:Single):PsrRegNode; - function OpUToF(pReg:PsrRegNode):PsrRegNode; - function OpSToF(pReg:PsrRegNode):PsrRegNode; - function OpShlI(pReg:PsrRegNode;i:DWORD):PsrRegNode; - function OpAddI(pReg:PsrRegNode;i:DWORD):PsrRegNode; - 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); + 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; @@ -53,7 +44,7 @@ procedure TEmit_vbuf_load.buf_load(info:TBuf_info); var v:TvarChain; begin - v:=TEmit_vbuf_chain(Self).get_chain(info); + v:=TEmit_vbuf_chain(TObject(Self)).get_chain(info); if (v.vType=vcUniformVector) then begin @@ -64,131 +55,77 @@ begin buf_load_cv(info,v); end; -function TEmit_vbuf_load.OpMulF(pReg:PsrRegNode;s:Single):PsrRegNode; -begin - if (pReg=nil) or (s=1) then Exit(pReg); - Result:=NewReg(pReg^.dtype); - pReg^.mark_read; - _emit_Op2(line,Op.OpFMul,Result,pReg,FetchReg(FConsts.Fetchf(dtFloat32,s))); -end; - -function TEmit_vbuf_load.OpAddF(pReg:PsrRegNode;s:Single):PsrRegNode; -begin - if (pReg=nil) or (s=0) then Exit(pReg); - Result:=NewReg(pReg^.dtype); - pReg^.mark_read; - _emit_Op2(line,Op.OpFAdd,Result,pReg,FetchReg(FConsts.Fetchf(dtFloat32,s))); -end; - -function TEmit_vbuf_load.OpUToF(pReg:PsrRegNode):PsrRegNode; -begin - if (pReg=nil) then Exit(pReg); - Result:=NewReg(dtFloat32); - pReg^.mark_read; - _emit_Op1(line,Op.OpConvertUToF,Result,pReg); -end; - -function TEmit_vbuf_load.OpSToF(pReg:PsrRegNode):PsrRegNode; -begin - if (pReg=nil) then Exit(pReg); - Result:=NewReg(dtFloat32); - pReg^.mark_read; - _emit_Op1(line,Op.OpConvertSToF,Result,pReg); -end; - -function TEmit_vbuf_load.OpShlI(pReg:PsrRegNode;i:DWORD):PsrRegNode; -begin - if (pReg=nil) or (i=0) then Exit(pReg); - Result:=NewReg(pReg^.dtype); - pReg^.mark_read; - _emit_OpShl(line,Result,pReg,FetchReg(FConsts.Fetchi(dtUint32,i))); -end; - -function TEmit_vbuf_load.OpAddI(pReg:PsrRegNode;i:DWORD):PsrRegNode; -begin - if (pReg=nil) or (i=0) then Exit(pReg); - Result:=NewReg(pReg^.dtype); - pReg^.mark_read; - _emit_OpIAdd(line,Result,pReg,FetchReg(FConsts.Fetchi(dtUint32,i))); -end; - -function TEmit_vbuf_load._convert_e(var lc:Tload_cache;src:PsrRegNode):PsrRegNode; +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<csize) then //refetch + if (orig^.size<>csize) then //refetch begin - idx:=orig^.key.ext.pIndex; + idx:=orig^.pIndex; if (idx<>nil) then begin - idx^.mark_read; - ext:=Default(TsrChainExt); - ext.pIndex:=idx; - ext.stride:=orig^.key.ext.stride; - new:=lc.info.grp^.Fetch(orig^.key.offset,csize,@ext); + lvl_0.offset:=orig^.offset; + lvl_0.size :=csize; + + lvl_1.pIndex:=idx; + lvl_1.stride:=orig^.stride; + + new:=lc.info.grp^.Fetch(@lvl_0,@lvl_1); end else begin - new:=lc.info.grp^.Fetch(orig^.key.offset,csize,nil); + lvl_0.offset:=orig^.offset; + lvl_0.size :=csize; + + new:=lc.info.grp^.Fetch(@lvl_0,nil); end; orig:=new; end; @@ -139,15 +142,16 @@ begin FetchStore(orig,rsl); end; -procedure TEmit_vbuf_store._make_store_ce(var lc:Tstore_cache); +procedure TEmit_vbuf_store.make_store_ce(var lc:Tstore_cache); var orig,elm:PsrChain; sum_d:PsrRegNode; - ext:TsrChainExt; + lvl_0:TsrChainLvl_0; + lvl_1:TsrChainLvl_1; i:Byte; begin orig:=lc.v.data[0]; - sum_d:=orig^.key.ext.pIndex; + sum_d:=orig^.pIndex; For i:=0 to lc.elem_count-1 do if (lc.elm[i]<>nil) then @@ -158,14 +162,15 @@ begin elm:=orig; end else begin - sum_d:=TEmit_vbuf_chain(Self).OpAddTo(sum_d,i); + sum_d:=OpIAddTo(sum_d,i); - sum_d^.mark_read; - ext:=Default(TsrChainExt); - ext.pIndex:=sum_d; - ext.stride:=orig^.key.ext.stride; + lvl_0.offset:=0; + lvl_0.size :=orig^.size; - elm:=lc.info.grp^.Fetch(0,orig^.key.size,@ext); + lvl_1.pIndex:=sum_d; + lvl_1.stride:=orig^.stride; + + elm:=lc.info.grp^.Fetch(@lvl_0,@lvl_1); end; Assert(lc.elem_resl=lc.elem_orig,'TODO CONVERT'); @@ -176,7 +181,7 @@ begin end; -procedure TEmit_vbuf_store._make_store_uv(var lc:Tstore_cache); +procedure TEmit_vbuf_store.make_store_uv(var lc:Tstore_cache); var rsl,idx:PsrRegNode; i:Byte; @@ -186,9 +191,9 @@ begin if (lc.elm[i]=nil) then begin Case lc.info.dsel[i] of - 1:lc.elm[i]:=_fetch_one(lc); + 1:lc.elm[i]:=fetch_one(lc); else - lc.elm[i]:=_fetch_zero(lc); + lc.elm[i]:=fetch_zero(lc); end; end; @@ -196,18 +201,16 @@ begin 1:rsl:=lc.elm[0]; else begin - rsl:=emit_OpMakeVec(line,GetVecType(lc.elem_resl,lc.elem_count),lc.elem_count,@lc.elm); - rsl^.mark_read; + rsl:=OpMakeVec(line,lc.elem_resl.AsVector(lc.elem_count),@lc.elm); end; end; idx:=lc.v.data[1]; - idx^.mark_read; - rsl^.mark_read; - emit_OpImageWrite(line,lc.v.data[0],idx,rsl); + + OpImageWrite(line,lc.v.data[0],idx,rsl); end; -procedure TEmit_vbuf_store._make_store_ue(var lc:Tstore_cache); +procedure TEmit_vbuf_store.make_store_ue(var lc:Tstore_cache); var sum_d,idx,rsl:PsrRegNode; i:Byte; @@ -224,12 +227,10 @@ begin sum_d:=idx; end else begin - sum_d:=TEmit_vbuf_chain(Self).OpAddTo(idx,i); + sum_d:=OpIAddTo(idx,i); end; - sum_d^.mark_read; - rsl^.mark_read; - emit_OpImageWrite(line,lc.v.data[0],sum_d,rsl); + OpImageWrite(line,lc.v.data[0],sum_d,rsl); end; end; @@ -261,7 +262,7 @@ begin Case lc.info.dsel[i] of 4..7: begin //RGBA - lc.elm[i]:=_fetch_id(lc,lc.info.dsel[i]-4); + lc.elm[i]:=fetch_id(lc,lc.info.dsel[i]-4); end; else; end; @@ -277,10 +278,10 @@ begin if (lc.elem_count=0) then Exit; Case v.vType of - vcChainVector :_make_store_cv(lc); - vcChainElement :_make_store_ce(lc); - vcUniformVector :_make_store_uv(lc); - vcUniformElement:_make_store_ue(lc) + vcChainVector :make_store_cv(lc); + vcChainElement :make_store_ce(lc); + vcUniformVector :make_store_uv(lc); + vcUniformElement:make_store_ue(lc) else; end; diff --git a/spirv/emit_vintrp.pas b/spirv/emit_vintrp.pas index a57f3b7a..b964f848 100644 --- a/spirv/emit_vintrp.pas +++ b/spirv/emit_vintrp.pas @@ -6,22 +6,21 @@ interface uses sysutils, + spirv, ps4_pssl, - srTypes, + srType, srInput, srReg, - spirv, - SprvEmit, - emit_op; + emit_fetch; type - TEmit_VINTRP=object(TEmitOp) - procedure _emit_VINTRP; + TEmit_VINTRP=class(TEmitFetch) + procedure emit_VINTRP; end; implementation -procedure TEmit_VINTRP._emit_VINTRP; +procedure TEmit_VINTRP.emit_VINTRP; var inp_M0:PsrInput; @@ -35,23 +34,23 @@ var begin Assert(FExecutionModel=ExecutionModel.Fragment); //only pixel shader - dst:=FRegsStory.get_vdst8(FSPI.VINTRP.VDST); + dst:=get_vdst8(FSPI.VINTRP.VDST); - inp_M0:=GetInputRegNode(FRegsStory.M0.current); + inp_M0:=GetInputRegNode(get_m0^.current); Assert(inp_M0<>nil); - Assert(inp_M0^.key.itype=itPsState); + Assert(inp_M0^.itype=itPsState); Case FSPI.VINTRP.OP of V_INTERP_P1_F32: begin - src:=FRegsStory.get_vsrc8(FSPI.VINTRP.VSRC); + src:=get_vsrc8(FSPI.VINTRP.VSRC); inp_SRC:=GetInputRegNode(src^.current); Assert(inp_SRC<>nil); - Case inp_SRC^.key.itype of + Case inp_SRC^.itype of itPerspSample, itPerspCenter, //barycentrics with perspective interpolation itPerspCentroid, @@ -62,24 +61,23 @@ begin Assert(false); end; - Assert(inp_SRC^.key.typeid=0); //I + Assert(inp_SRC^.typeid=0); //I - rsl:=AddFragLayout(inp_SRC^.key.itype,dtVec4f,FSPI.VINTRP.ATTR); - rsl^.mark_read; + rsl:=AddFragLayout(inp_SRC^.itype,dtVec4f,FSPI.VINTRP.ATTR); dst^.New(line,dtFloat32); - emit_OpCompExtract(line,dst^.current,rsl,FSPI.VINTRP.ATTRCHAN); + OpExtract(line,dst^.current,rsl,FSPI.VINTRP.ATTRCHAN); end; V_INTERP_P2_F32: begin - src:=FRegsStory.get_vsrc8(FSPI.VINTRP.VSRC); + src:=get_vsrc8(FSPI.VINTRP.VSRC); inp_SRC:=GetInputRegNode(src^.current); Assert(inp_SRC<>nil); - Case inp_SRC^.key.itype of + Case inp_SRC^.itype of itPerspSample, itPerspCenter, //barycentrics with perspective interpolation itPerspCentroid, @@ -90,13 +88,12 @@ begin Assert(false); end; - Assert(inp_SRC^.key.typeid=1); //J + Assert(inp_SRC^.typeid=1); //J - rsl:=AddFragLayout(inp_SRC^.key.itype,dtVec4f,FSPI.VINTRP.ATTR); - rsl^.mark_read; + rsl:=AddFragLayout(inp_SRC^.itype,dtVec4f,FSPI.VINTRP.ATTR); dst^.New(line,dtFloat32); - emit_OpCompExtract(line,dst^.current,rsl,FSPI.VINTRP.ATTRCHAN); + OpExtract(line,dst^.current,rsl,FSPI.VINTRP.ATTRCHAN); end; diff --git a/spirv/emit_vop1.pas b/spirv/emit_vop1.pas index 4b82077f..3cc4fd65 100644 --- a/spirv/emit_vop1.pas +++ b/spirv/emit_vop1.pas @@ -7,188 +7,153 @@ interface uses sysutils, ps4_pssl, - srTypes, - srReg, spirv, - SprvEmit, - emit_op; + srType, + srReg, + emit_fetch; type - TEmit_VOP1=object(TEmitOp) - procedure _emit_VOP1; - procedure _emit_V_MOV_B32; - procedure _emit_V_CVT(OpId:DWORD;dst_type,src_type:TsrDataType); - procedure _emit_V_CVT_OFF_F32_I4; - procedure _emit_V_CVT_F32_UBYTE0; - procedure _emit_V_EXT_F32(OpId:DWORD); - procedure _emit_V_RCP_F32; - procedure _emit_V_FFBL_B32; + TEmit_VOP1=class(TEmitFetch) + procedure emit_VOP1; + procedure emit_V_MOV_B32; + procedure emit_V_CVT(OpId:DWORD;dst_type,src_type:TsrDataType); + procedure emit_V_CVT_OFF_F32_I4; + procedure emit_V_CVT_F32_UBYTE0; + procedure emit_V_EXT_F32(OpId:DWORD); + procedure emit_V_RCP_F32; + procedure emit_V_FFBL_B32; end; implementation -procedure TEmit_VOP1._emit_V_MOV_B32; +procedure TEmit_VOP1.emit_V_MOV_B32; Var dst:PsrRegSlot; src:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + dst:=get_vdst8(FSPI.VOP1.VDST); src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUnknow); - _MakeCopy(dst,src); + MakeCopy(dst,src); end; -procedure TEmit_VOP1._emit_V_CVT(OpId:DWORD;dst_type,src_type:TsrDataType); +procedure TEmit_VOP1.emit_V_CVT(OpId:DWORD;dst_type,src_type:TsrDataType); Var dst:PsrRegSlot; src:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + dst:=get_vdst8(FSPI.VOP1.VDST); src:=fetch_ssrc9(FSPI.VOP1.SRC0,src_type); - emit_Op1(OpId,dst_type,dst,src); + Op1(OpId,dst_type,dst,src); end; //V_CVT_OFF_F32_I4 //([0..3]-8)/16 -procedure TEmit_VOP1._emit_V_CVT_OFF_F32_I4; +procedure TEmit_VOP1.emit_V_CVT_OFF_F32_I4; Var - dst,tmp:PsrRegSlot; + dst:PsrRegSlot; src:PsrRegNode; - num_8:PsrRegNode; - num_15:PsrRegNode; num_16:PsrRegNode; - subi,subf:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + dst:=get_vdst8(FSPI.VOP1.VDST); src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUInt32); - tmp:=@FRegsStory.FUnattach; - num_15:=FetchReg(FConsts.Fetch(dtUInt32,15)); + src:=OpBitwiseAndTo(src,15); + src^.PrepType(ord(dtInt32)); - emit_OpBitwiseAnd(tmp,src,num_15); - src:=MakeRead(tmp,dtUInt32); + src:=OpISubTo(src,8); - num_8:=FetchReg(FConsts.Fetch(dtInt32,8)); - subi:=dst^.New(line,dtInt32); + src:=OpSToF(src,dtFloat32); - _emit_OpISub(line,subi,src,num_8); - - subi^.mark_read; - subf:=dst^.New(line,dtFloat32); - - _emit_Op1(line,Op.OpConvertSToF,subf,subi); - - subf^.mark_read; - num_16:=FetchReg(FConsts.Fetchf(dtFloat32,16)); - - emit_OpFDiv(dst,subf,num_16); + num_16:=NewReg_s(dtFloat32,16); + Op2(Op.OpFDiv,dtFloat32,dst,src,num_16); end; -procedure TEmit_VOP1._emit_V_CVT_F32_UBYTE0; -Var - dst,tmp:PsrRegSlot; - src:PsrRegNode; - num_FF:PsrRegNode; - -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); - src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUInt32); - - tmp:=@FRegsStory.FUnattach; - num_FF:=FetchReg(FConsts.Fetch(dtUInt32,$FF)); - - emit_OpBitwiseAnd(tmp,src,num_FF); - src:=MakeRead(tmp,dtUInt32); - - emit_Op1(Op.OpConvertUToF,dtFloat32,dst,src); -end; - -procedure TEmit_VOP1._emit_V_EXT_F32(OpId:DWORD); +procedure TEmit_VOP1.emit_V_CVT_F32_UBYTE0; Var dst:PsrRegSlot; src:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); - src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32); - emit_OpExt1(OpId,dtFloat32,dst,src); + dst:=get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUInt32); + + src:=OpBitwiseAndTo(src,$FF); + src^.PrepType(ord(dtUInt32)); + + Op1(Op.OpConvertUToF,dtFloat32,dst,src); end; -procedure TEmit_VOP1._emit_V_RCP_F32; +procedure TEmit_VOP1.emit_V_EXT_F32(OpId:DWORD); +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32); + OpGlsl1(OpId,dtFloat32,dst,src); +end; + +procedure TEmit_VOP1.emit_V_RCP_F32; Var dst:PsrRegSlot; src:PsrRegNode; one:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + dst:=get_vdst8(FSPI.VOP1.VDST); src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32); - one:=FetchReg(FConsts.Fetchf(dtFloat32,1)); + one:=NewReg_s(dtFloat32,1); - emit_OpFDiv(dst,one,src); + Op2(Op.OpFDiv,dtFloat32,dst,one,src); end; -procedure TEmit_VOP1._emit_V_FFBL_B32; +procedure TEmit_VOP1.emit_V_FFBL_B32; Var dst:PsrRegSlot; src:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + dst:=get_vdst8(FSPI.VOP1.VDST); src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtInt32); - emit_OpExt1(GlslOp.FindILsb,dtInt32,dst,src); + OpGlsl1(GlslOp.FindILsb,dtInt32,dst,src); end; -procedure TEmit_VOP1._emit_VOP1; +procedure TEmit_VOP1.emit_VOP1; begin Case FSPI.VOP1.OP of V_NOP:; - V_MOV_B32: - begin - _emit_V_MOV_B32; - end; + V_MOV_B32: emit_V_MOV_B32; - V_CVT_F32_I32: _emit_V_CVT(Op.OpConvertSToF,dtFloat32,dtInt32); - V_CVT_F32_U32: _emit_V_CVT(Op.OpConvertUToF,dtFloat32,dtUInt32); - V_CVT_U32_F32: _emit_V_CVT(Op.OpConvertFToU,dtUInt32 ,dtFloat32); - V_CVT_I32_F32: _emit_V_CVT(Op.OpConvertFToS,dtInt32 ,dtFloat32); + V_CVT_F32_I32: emit_V_CVT(Op.OpConvertSToF,dtFloat32,dtInt32); + V_CVT_F32_U32: emit_V_CVT(Op.OpConvertUToF,dtFloat32,dtUInt32); + V_CVT_U32_F32: emit_V_CVT(Op.OpConvertFToU,dtUInt32 ,dtFloat32); + V_CVT_I32_F32: emit_V_CVT(Op.OpConvertFToS,dtInt32 ,dtFloat32); - V_CVT_OFF_F32_I4: - begin - _emit_V_CVT_OFF_F32_I4; - end; + V_CVT_OFF_F32_I4: emit_V_CVT_OFF_F32_I4; - V_CVT_F32_UBYTE0: - begin - _emit_V_CVT_F32_UBYTE0; - end; + V_CVT_F32_UBYTE0: emit_V_CVT_F32_UBYTE0; - V_FRACT_F32: _emit_V_EXT_F32(GlslOp.Fract); - V_TRUNC_F32: _emit_V_EXT_F32(GlslOp.Trunc); - V_CEIL_F32 : _emit_V_EXT_F32(GlslOp.Ceil); + V_FRACT_F32: emit_V_EXT_F32(GlslOp.Fract); + V_TRUNC_F32: emit_V_EXT_F32(GlslOp.Trunc); + V_CEIL_F32 : emit_V_EXT_F32(GlslOp.Ceil); - V_FLOOR_F32: _emit_V_EXT_F32(GlslOp.Floor); - V_EXP_F32 : _emit_V_EXT_F32(GlslOp.Exp2); - V_LOG_F32 : _emit_V_EXT_F32(GlslOp.Log2); + V_FLOOR_F32: emit_V_EXT_F32(GlslOp.Floor); + V_EXP_F32 : emit_V_EXT_F32(GlslOp.Exp2); + V_LOG_F32 : emit_V_EXT_F32(GlslOp.Log2); - V_RSQ_F32 : _emit_V_EXT_F32(GlslOp.InverseSqrt); + V_RSQ_F32 : emit_V_EXT_F32(GlslOp.InverseSqrt); - V_SQRT_F32 : _emit_V_EXT_F32(GlslOp.Sqrt); + V_SQRT_F32 : emit_V_EXT_F32(GlslOp.Sqrt); - V_SIN_F32 : _emit_V_EXT_F32(GlslOp.Sin); - V_COS_F32 : _emit_V_EXT_F32(GlslOp.Cos); + V_SIN_F32 : emit_V_EXT_F32(GlslOp.Sin); + V_COS_F32 : emit_V_EXT_F32(GlslOp.Cos); - V_RCP_F32: - begin - _emit_V_RCP_F32; - end; + V_RCP_F32 : emit_V_RCP_F32; - V_FFBL_B32: - begin - _emit_V_FFBL_B32; - end; + V_FFBL_B32 : emit_V_FFBL_B32; else Assert(false,'VOP1?'+IntToStr(FSPI.VOP1.OP)); diff --git a/spirv/emit_vop2.pas b/spirv/emit_vop2.pas index 838b7d97..6435ea65 100644 --- a/spirv/emit_vop2.pas +++ b/spirv/emit_vop2.pas @@ -8,506 +8,360 @@ uses sysutils, ps4_pssl, spirv, - srTypes, - srConst, + srType, srReg, - SprvEmit, - emit_op; + emit_fetch; type - TEmit_VOP2=object(TEmitOp) - procedure _emit_VOP2; - procedure _emit_V_CNDMASK_B32; - procedure _emit_V_AND_B32; - procedure _emit_V_OR_B32; - procedure _emit_V_XOR_B32; - procedure _emit_V_LSHL_B32; - procedure _emit_V_LSHLREV_B32; - procedure _emit_V_LSHR_B32; - procedure _emit_V_LSHRREV_B32; - procedure _emit_V_ASHR_I32; - procedure _emit_V_ASHRREV_I32; - procedure _emit_V_ADD_I32; - procedure _emit_V_SUB_I32; - procedure _emit_V_SUBREV_I32; - procedure _emit_V_ADD_F32; - procedure _emit_V_SUB_F32; - procedure _emit_V_SUBREV_F32; - procedure _emit_V_MUL_F32; - procedure _emit_V_CVT_PKRTZ_F16_F32; - procedure _emit_V_MAC_F32; - procedure _emit_V_MADAK_F32; - procedure _emit_V_MADMK_F32; - procedure _emit_V_MIN_MAX(OpId:DWORD;rtype:TsrDataType); + TEmit_VOP2=class(TEmitFetch) + procedure emit_VOP2; + procedure emit_V_CNDMASK_B32; + procedure emit_V_AND_B32; + procedure emit_V_OR_B32; + procedure emit_V_XOR_B32; + procedure emit_V_SH(OpId:DWORD;rtype:TsrDataType); + procedure emit_V_SHREV(OpId:DWORD;rtype:TsrDataType); + procedure emit_V_ADD_I32; + procedure emit_V_SUB_I32; + procedure emit_V_SUBREV_I32; + procedure emit_V2_F32(OpId:DWORD); + procedure emit_V_SUBREV_F32; + procedure emit_V_CVT_PKRTZ_F16_F32; + procedure emit_V_MUL_I32_I24; + procedure emit_V_MUL_U32_U24; + procedure emit_V_MAC_F32; + procedure emit_V_MADAK_F32; + procedure emit_V_MADMK_F32; + procedure emit_V_MMX(OpId:DWORD;rtype:TsrDataType); end; implementation -procedure TEmit_VOP2._emit_V_CNDMASK_B32; +procedure TEmit_VOP2.emit_V_CNDMASK_B32; Var dst:PsrRegSlot; src:array[0..2] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); + dst:=get_vdst8(FSPI.VOP2.VDST); src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUnknow); src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUnknow); - src[2]:=MakeRead(@FRegsStory.VCC[0],dtBool); + src[2]:=MakeRead(get_vcc0,dtBool); - emit_OpSelect(dst,src[0],src[1],src[2]); + OpSelect(dst,src[0],src[1],src[2]); end; -procedure TEmit_VOP2._emit_V_AND_B32; +procedure TEmit_VOP2.emit_V_AND_B32; Var dst:PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); + dst:=get_vdst8(FSPI.VOP2.VDST); src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUnknow); src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUnknow); - emit_OpBitwiseAnd(dst,src[0],src[1]); + OpBitwiseAnd(dst,src[0],src[1]); end; -procedure TEmit_VOP2._emit_V_OR_B32; +procedure TEmit_VOP2.emit_V_OR_B32; Var dst:PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); + dst:=get_vdst8(FSPI.VOP2.VDST); src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUnknow); src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUnknow); - emit_OpBitwiseOr(dst,src[0],src[1]); + OpBitwiseOr(dst,src[0],src[1]); end; -procedure TEmit_VOP2._emit_V_XOR_B32; +procedure TEmit_VOP2.emit_V_XOR_B32; Var dst:PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); + dst:=get_vdst8(FSPI.VOP2.VDST); - src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,{dtUnknow}dtUInt32); - src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,{dtUnknow}dtUInt32); + src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUInt32); + src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUInt32); - emit_OpBitwiseXor(dst,src[0],src[1]); + OpBitwiseXor(dst,src[0],src[1]); end; -procedure TEmit_VOP2._emit_V_LSHL_B32; +procedure TEmit_VOP2.emit_V_SH(OpId:DWORD;rtype:TsrDataType); Var - dst,tmp:PsrRegSlot; - src:array[0..2] of PsrRegNode; + dst:PsrRegSlot; + src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); - tmp:=@FRegsStory.FUnattach; + dst:=get_vdst8(FSPI.VOP2.VDST); + + src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,rtype); + src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32); + + src[1]:=OpBitwiseAndTo(src[1],31); + src[1]^.PrepType(ord(dtUInt32)); + + Op2(OpId,src[0]^.dtype,dst,src[0],src[1]); +end; + +procedure TEmit_VOP2.emit_V_SHREV(OpId:DWORD;rtype:TsrDataType); +Var + dst:PsrRegSlot; + src:array[0..1] of PsrRegNode; +begin + dst:=get_vdst8(FSPI.VOP2.VDST); + + src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32); + src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,rtype); + + src[0]:=OpBitwiseAndTo(src[0],31); + src[0]^.PrepType(ord(dtUInt32)); + + Op2(OpId,src[1]^.dtype,dst,src[1],src[0]); +end; + +procedure TEmit_VOP2.emit_V_ADD_I32; //vdst = vsrc0.s + vsrc1.s; sdst[thread_id:] = carry_out & EXEC +Var + dst,car:PsrRegSlot; + src:array[0..1] of PsrRegNode; + exc:PsrRegNode; +begin + dst:=get_vdst8(FSPI.VOP2.VDST); + car:=get_vcc0; src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32); src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32); - src[2]:=FetchReg(FConsts.Fetch(dtUInt32,31)); - emit_OpBitwiseAnd(tmp,src[1],src[2]); - src[1]:=MakeRead(tmp,dtUInt32); + OpIAddExt(dst,car,src[0],src[1]); - emit_OpShl(dst,src[0],src[1]); + exc:=MakeRead(get_exec0,dtUnknow); + OpBitwiseAnd(car,car^.current,exc); //carry_out & EXEC end; -procedure TEmit_VOP2._emit_V_LSHLREV_B32; +procedure TEmit_VOP2.emit_V_SUB_I32; //vdst = vsrc0.u - vsub.u; sdst[thread_id:] = borrow_out & EXEC Var - dst,tmp:PsrRegSlot; - src:array[0..2] of PsrRegNode; + dst,bor:PsrRegSlot; + src:array[0..1] of PsrRegNode; + exc:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); - tmp:=@FRegsStory.FUnattach; + dst:=get_vdst8(FSPI.VOP2.VDST); + bor:=get_vcc0; src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32); src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32); - src[2]:=FetchReg(FConsts.Fetch(dtUInt32,31)); - emit_OpBitwiseAnd(tmp,src[0],src[2]); - src[0]:=MakeRead(tmp,dtUInt32); + OpISubExt(dst,bor,src[0],src[1]); - emit_OpShl(dst,src[1],src[0]); + exc:=MakeRead(get_exec0,dtUnknow); + OpBitwiseAnd(bor,bor^.current,exc); //borrow_out & EXEC end; -procedure TEmit_VOP2._emit_V_LSHR_B32; +procedure TEmit_VOP2.emit_V_SUBREV_I32; //vdst = vsrc1.u - vsub.u; sdst[thread_id:] = borrow_out & EXEC Var - dst,tmp:PsrRegSlot; - src:array[0..2] of PsrRegNode; + dst,bor:PsrRegSlot; + src:array[0..1] of PsrRegNode; + exc:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); - tmp:=@FRegsStory.FUnattach; + dst:=get_vdst8(FSPI.VOP2.VDST); + bor:=get_vcc0; src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32); src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32); - src[2]:=FetchReg(FConsts.Fetch(dtUInt32,31)); - emit_OpBitwiseAnd(tmp,src[1],src[2]); - src[1]:=MakeRead(tmp,dtUInt32); + OpISubExt(dst,bor,src[1],src[0]); - emit_OpShr(dst,src[0],src[1]); + exc:=MakeRead(get_exec0,dtUnknow); + OpBitwiseAnd(bor,bor^.current,exc); //borrow_out & EXEC end; -procedure TEmit_VOP2._emit_V_LSHRREV_B32; +procedure TEmit_VOP2.emit_V2_F32(OpId:DWORD); Var - dst,tmp:PsrRegSlot; - src:array[0..2] of PsrRegNode; + dst:PsrRegSlot; + src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); - tmp:=@FRegsStory.FUnattach; + dst:=get_vdst8(FSPI.VOP2.VDST); - src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32); - src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32); + src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32); + src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32); - src[2]:=FetchReg(FConsts.Fetch(dtUInt32,31)); - emit_OpBitwiseAnd(tmp,src[0],src[2]); - src[0]:=MakeRead(tmp,dtUInt32); - - emit_OpShr(dst,src[1],src[0]); + Op2(OpId,dtFloat32,dst,src[0],src[1]); end; -procedure TEmit_VOP2._emit_V_ASHR_I32; +procedure TEmit_VOP2.emit_V_SUBREV_F32; Var - dst,tmp:PsrRegSlot; - src:array[0..2] of PsrRegNode; + dst:PsrRegSlot; + src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); - tmp:=@FRegsStory.FUnattach; + dst:=get_vdst8(FSPI.VOP2.VDST); + + src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32); + src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32); + + Op2(Op.OpFSub,dtFloat32,dst,src[1],src[0]); +end; + +procedure TEmit_VOP2.emit_V_CVT_PKRTZ_F16_F32; +Var + dst:PsrRegSlot; + src:array[0..1] of PsrRegNode; +begin + dst:=get_vdst8(FSPI.VOP2.VDST); + + src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32); + src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32); + + OpConvFloatToHalf2(dst,src[0],src[1]); +end; + +procedure TEmit_VOP2.emit_V_MUL_I32_I24; +Var + dst:PsrRegSlot; + src:array[0..1] of PsrRegNode; + bit24:PsrRegNode; +begin + dst:=get_vdst8(FSPI.VOP2.VDST); src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtInt32); - src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32); - - src[2]:=FetchReg(FConsts.Fetch(dtInt32,31)); - emit_OpBitwiseAnd(tmp,src[1],src[2]); - src[1]:=MakeRead(tmp,dtInt32); - - emit_OpShrA(dst,src[0],src[1]); -end; - -procedure TEmit_VOP2._emit_V_ASHRREV_I32; -Var - dst,tmp:PsrRegSlot; - src:array[0..2] of PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); - tmp:=@FRegsStory.FUnattach; - - src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32); src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtInt32); - src[2]:=FetchReg(FConsts.Fetch(dtInt32,31)); - emit_OpBitwiseAnd(tmp,src[0],src[2]); - src[0]:=MakeRead(tmp,dtInt32); + bit24:=NewReg_q(dtUInt32,$FFFFFF); - emit_OpShrA(dst,src[1],src[0]); + src[0]:=OpBitwiseAndTo(src[0],bit24); + src[0]^.PrepType(ord(dtInt32)); + + src[1]:=OpBitwiseAndTo(src[1],bit24); + src[1]^.PrepType(ord(dtInt32)); + + OpIMul(dst,src[0],src[1]); end; -procedure TEmit_VOP2._emit_V_ADD_I32; //vdst = vsrc0.s + vsrc1.s; sdst[thread_id:] = carry_out & EXEC -Var - dst,car:PsrRegSlot; - src:array[0..1] of PsrRegNode; - exc,tmp:PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); - car:=@FRegsStory.VCC[0]; - - src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32); - src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32); - - emit_OpIAddExt(dst,@FRegsStory.FUnattach,src[0],src[1]); - - tmp:=FRegsStory.FUnattach.current; - tmp^.mark_read; - exc:=MakeRead(@FRegsStory.EXEC[0],dtUnknow); - emit_OpBitwiseAnd(car,tmp,exc); -end; - -procedure TEmit_VOP2._emit_V_SUB_I32; //vdst = vsrc0.u - vsub.u; sdst[thread_id:] = borrow_out & EXEC -Var - dst,car:PsrRegSlot; - src:array[0..1] of PsrRegNode; - exc,tmp:PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); - car:=@FRegsStory.VCC[0]; - - src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32); - src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32); - - emit_OpISubExt(dst,@FRegsStory.FUnattach,src[0],src[1]); - - tmp:=FRegsStory.FUnattach.current; - tmp^.mark_read; - exc:=MakeRead(@FRegsStory.EXEC[0],dtUnknow); - emit_OpBitwiseAnd(car,tmp,exc); -end; - -procedure TEmit_VOP2._emit_V_SUBREV_I32; //vdst = vsrc1.u - vsub.u; sdst[thread_id:] = borrow_out & EXEC -Var - dst,car:PsrRegSlot; - src:array[0..1] of PsrRegNode; - exc,tmp:PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); - car:=@FRegsStory.VCC[0]; - - src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32); - src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32); - - emit_OpISubExt(dst,@FRegsStory.FUnattach,src[1],src[0]); - - tmp:=FRegsStory.FUnattach.current; - tmp^.mark_read; - exc:=MakeRead(@FRegsStory.EXEC[0],dtUnknow); - emit_OpBitwiseAnd(car,tmp,exc); -end; - -procedure TEmit_VOP2._emit_V_ADD_F32; +procedure TEmit_VOP2.emit_V_MUL_U32_U24; Var dst:PsrRegSlot; src:array[0..1] of PsrRegNode; + bit24:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); + dst:=get_vdst8(FSPI.VOP2.VDST); - src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32); - src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32); + src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUInt32); + src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUInt32); - emit_OpFAdd(dst,src[0],src[1]); + bit24:=NewReg_q(dtUInt32,$FFFFFF); + + src[0]:=OpBitwiseAndTo(src[0],bit24); + src[0]^.PrepType(ord(dtUInt32)); + + src[1]:=OpBitwiseAndTo(src[1],bit24); + src[1]^.PrepType(ord(dtUInt32)); + + OpIMul(dst,src[0],src[1]); end; -procedure TEmit_VOP2._emit_V_SUB_F32; -Var - dst:PsrRegSlot; - src:array[0..1] of PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); - - src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32); - src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32); - - emit_OpFSub(dst,src[0],src[1]); -end; - -procedure TEmit_VOP2._emit_V_SUBREV_F32; -Var - dst:PsrRegSlot; - src:array[0..1] of PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); - - src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32); - src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32); - - emit_OpFSub(dst,src[1],src[0]); -end; - -procedure TEmit_VOP2._emit_V_MUL_F32; -Var - dst:PsrRegSlot; - src:array[0..1] of PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); - - src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32); - src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32); - - emit_OpFMul(dst,src[0],src[1]); -end; - -procedure TEmit_VOP2._emit_V_CVT_PKRTZ_F16_F32; -Var - dst:PsrRegSlot; - src:array[0..1] of PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); - - src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32); - src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32); - _emit_ConvFloatToHalf(dst,src[0],src[1]); -end; - -procedure TEmit_VOP2._emit_V_MAC_F32; //vdst = vsrc0.f * vsrc1.f + vdst.f -> fma +procedure TEmit_VOP2.emit_V_MAC_F32; //vdst = vsrc0.f * vsrc1.f + vdst.f -> fma Var dst:PsrRegSlot; src:array[0..2] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); + dst:=get_vdst8(FSPI.VOP2.VDST); src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32); src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32); src[2]:=MakeRead(dst,dtFloat32); - emit_OpFmaF32(dst,src[0],src[1],src[2]); + OpFmaF32(dst,src[0],src[1],src[2]); end; -procedure TEmit_VOP2._emit_V_MADAK_F32; //vdst = vsrc0.f * vsrc1.f + kadd.f +procedure TEmit_VOP2.emit_V_MADAK_F32; //vdst = vsrc0.f * vsrc1.f + kadd.f Var dst:PsrRegSlot; src:array[0..2] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); + dst:=get_vdst8(FSPI.VOP2.VDST); src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32); src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32); - src[2]:=FetchReg(FConsts.Fetch(dtFloat32,FSPI.INLINE32)); + src[2]:=NewReg_q(dtFloat32,FSPI.INLINE32); - emit_OpFmaF32(dst,src[0],src[1],src[2]); + OpFmaF32(dst,src[0],src[1],src[2]); end; -procedure TEmit_VOP2._emit_V_MADMK_F32; //vdst = vsrc0.f * kmul.f + vadd.f +procedure TEmit_VOP2.emit_V_MADMK_F32; //vdst = vsrc0.f * kmul.f + vadd.f Var dst:PsrRegSlot; src:array[0..2] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); + dst:=get_vdst8(FSPI.VOP2.VDST); src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32); - src[1]:=FetchReg(FConsts.Fetch(dtFloat32,FSPI.INLINE32)); + src[1]:=NewReg_q(dtFloat32,FSPI.INLINE32); src[2]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32); - emit_OpFmaF32(dst,src[0],src[1],src[2]); + OpFmaF32(dst,src[0],src[1],src[2]); end; -procedure TEmit_VOP2._emit_V_MIN_MAX(OpId:DWORD;rtype:TsrDataType); +procedure TEmit_VOP2.emit_V_MMX(OpId:DWORD;rtype:TsrDataType); Var dst:PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST); + dst:=get_vdst8(FSPI.VOP2.VDST); src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,rtype); src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,rtype); - emit_OpExt2(OpId,rtype,dst,src[0],src[1]); + OpGlsl2(OpId,rtype,dst,src[0],src[1]); end; -procedure TEmit_VOP2._emit_VOP2; +procedure TEmit_VOP2.emit_VOP2; begin Case FSPI.VOP2.OP of - V_CNDMASK_B32: - begin - _emit_V_CNDMASK_B32; - end; + V_CNDMASK_B32: emit_V_CNDMASK_B32; - V_AND_B32: - begin - _emit_V_AND_B32; - end; + V_AND_B32 : emit_V_AND_B32; + V_OR_B32 : emit_V_OR_B32; + V_XOR_B32 : emit_V_XOR_B32; - V_OR_B32: - begin - _emit_V_OR_B32; - end; + V_LSHL_B32 : emit_V_SH(Op.OpShiftLeftLogical,dtUint32); + V_LSHLREV_B32: emit_V_SHREV(Op.OpShiftLeftLogical,dtUint32); + V_LSHR_B32 : emit_V_SH(Op.OpShiftRightLogical,dtUint32); + V_LSHRREV_B32: emit_V_SHREV(Op.OpShiftRightLogical,dtUint32); + V_ASHR_I32 : emit_V_SH(Op.OpShiftRightLogical,dtInt32); + V_ASHRREV_I32: emit_V_SHREV(Op.OpShiftRightLogical,dtInt32); - V_XOR_B32: - begin - _emit_V_XOR_B32; - end; + V_ADD_I32 : emit_V_ADD_I32; + V_SUB_I32 : emit_V_SUB_I32; + V_SUBREV_I32 : emit_V_SUBREV_I32; - V_LSHL_B32: - begin - _emit_V_LSHL_B32; - end; + V_ADD_F32 : emit_V2_F32(Op.OpFAdd); + V_SUB_F32 : emit_V2_F32(Op.OpFSub); + V_SUBREV_F32 : emit_V_SUBREV_F32; - V_LSHLREV_B32: - begin - _emit_V_LSHLREV_B32; - end; + V_MUL_F32 :emit_V2_F32(Op.OpFMul); - V_LSHR_B32: - begin - _emit_V_LSHR_B32; - end; + V_CVT_PKRTZ_F16_F32: emit_V_CVT_PKRTZ_F16_F32; - V_LSHRREV_B32: - begin - _emit_V_LSHRREV_B32 - end; + V_MUL_I32_I24: emit_V_MUL_I32_I24; + V_MUL_U32_U24: emit_V_MUL_U32_U24; - V_ASHR_I32: - begin - _emit_V_ASHR_I32; - end; + V_MAC_F32 : emit_V_MAC_F32; + V_MADAK_F32: emit_V_MADAK_F32; + V_MADMK_F32: emit_V_MADMK_F32; - V_ASHRREV_I32: - begin - _emit_V_ASHRREV_I32 - end; + V_MIN_LEGACY_F32: emit_V_MMX(GlslOp.NMin,dtFloat32); + V_MAX_LEGACY_F32: emit_V_MMX(GlslOp.NMax,dtFloat32); - V_ADD_I32: //vdst = vsrc0.s + vsrc1.s; sdst[thread_id:] = carry_out & EXEC - begin - // Vector ALU (except v_readlane, v_readfirstlane, v_writelane), - // Vector Memory, - // Local and Global Data Share - // and Export. - _emit_V_ADD_I32; - end; + V_MIN_F32: emit_V_MMX(GlslOp.FMin,dtFloat32); + V_MAX_F32: emit_V_MMX(GlslOp.FMax,dtFloat32); - V_SUB_I32: - begin - _emit_V_SUB_I32; - end; + V_MIN_I32: emit_V_MMX(GlslOp.SMin,dtInt32); + V_MAX_I32: emit_V_MMX(GlslOp.SMax,dtInt32); - V_SUBREV_I32: - begin - _emit_V_SUBREV_I32; - end; - - V_ADD_F32: - begin - _emit_V_ADD_F32; - end; - - V_SUB_F32: - begin - _emit_V_SUB_F32; - end; - - V_SUBREV_F32: - begin - _emit_V_SUBREV_F32; - end; - - V_MUL_F32: - begin - _emit_V_MUL_F32; - end; - - V_CVT_PKRTZ_F16_F32: - begin - _emit_V_CVT_PKRTZ_F16_F32; - end; - - V_MAC_F32: //vdst = vsrc0.f * vsrc1.f + vdst.f -> fma - begin - _emit_V_MAC_F32; - end; - - V_MADAK_F32: - begin - _emit_V_MADAK_F32; - end; - - V_MADMK_F32: - begin - _emit_V_MADMK_F32; - end; - - V_MIN_LEGACY_F32:_emit_V_MIN_MAX(GlslOp.NMin,dtFloat32); - V_MAX_LEGACY_F32:_emit_V_MIN_MAX(GlslOp.NMax,dtFloat32); - - V_MIN_F32:_emit_V_MIN_MAX(GlslOp.FMin,dtFloat32); - V_MAX_F32:_emit_V_MIN_MAX(GlslOp.FMax,dtFloat32); - - V_MIN_I32:_emit_V_MIN_MAX(GlslOp.SMin,dtInt32); - V_MAX_I32:_emit_V_MIN_MAX(GlslOp.SMax,dtInt32); - - V_MIN_U32:_emit_V_MIN_MAX(GlslOp.UMin,dtUint32); - V_MAX_U32:_emit_V_MIN_MAX(GlslOp.UMax,dtUint32); + V_MIN_U32: emit_V_MMX(GlslOp.UMin,dtUint32); + V_MAX_U32: emit_V_MMX(GlslOp.UMax,dtUint32); else Assert(false,'VOP2?'+IntToStr(FSPI.VOP2.OP)); diff --git a/spirv/emit_vop3.pas b/spirv/emit_vop3.pas index b8f3f467..d1404125 100644 --- a/spirv/emit_vop3.pas +++ b/spirv/emit_vop3.pas @@ -8,66 +8,59 @@ uses sysutils, ps4_pssl, spirv, - srTypes, + srType, srReg, srOpUtils, - SprvEmit, - emit_op; + emit_fetch; type - TEmit_VOP3=object(TEmitOp) - procedure _emit_VOP3c; - procedure _emit_VOP3b; - procedure _emit_VOP3a; - procedure _emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean); - procedure _emit_V_CMP_C(r,x:Boolean); + TEmit_VOP3=class(TEmitFetch) + procedure emit_VOP3c; + procedure emit_VOP3b; + procedure emit_VOP3a; + procedure emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean); + procedure emit_V_CMP_C(r,x:Boolean); - procedure _emit_src_neg_bit(src:PPsrRegNode;count:Byte); - procedure _emit_src_abs(src:PPsrRegNode); - procedure _emit_src_abs_bit(src:PPsrRegNode;count:Byte); - procedure _emit_dst_omod_f(dst:PsrRegSlot); - procedure _emit_dst_clamp_f(dst:PsrRegSlot); + procedure emit_src_neg_bit(src:PPsrRegNode;count:Byte); + procedure emit_src_abs(src:PPsrRegNode); + procedure emit_src_abs_bit(src:PPsrRegNode;count:Byte); + procedure emit_dst_omod_f(dst:PsrRegSlot); + procedure emit_dst_clamp_f(dst:PsrRegSlot); - procedure _emit_V_CNDMASK_B32; - procedure _emit_V_ADD_F32; - procedure _emit_V_SUB_F32; - procedure _emit_V_CVT_PKRTZ_F16_F32; - procedure _emit_V_MIN_MAX_F32(OpId:DWORD); - procedure _emit_V_MUL_LO_I32; - procedure _emit_V_MUL_F32; - procedure _emit_V_MUL_I32_I24; - procedure _emit_V_MUL_U32_U24; - procedure _emit_V_MUL_HI_U32; - procedure _emit_V_MAC_F32; + procedure emit_V_CNDMASK_B32; + procedure emit_V2_F32(OpId:DWORD); + procedure emit_V_CVT_PKRTZ_F16_F32; + procedure emit_V_MMX_F32(OpId:DWORD); + procedure emit_V_MUL_LO_I32; + procedure emit_V_MUL_I32_I24; + procedure emit_V_MUL_U32_U24; + procedure emit_V_MUL_HI_U32; + procedure emit_V_MAC_F32; - procedure _emit_V_BFE_U32; - procedure _emit_V_BFI_B32; - procedure _emit_V_MAD_F32; - procedure _emit_V_MAD_I32_I24; - procedure _emit_V_MAD_U32_U24; - procedure _emit_V_SAD_U32; - procedure _emit_V_MAX3_F32; - procedure _emit_V_MIN3_F32; - procedure _emit_V_MED3_F32; - procedure _emit_V_FMA_F32; - procedure _emit_V_CUBE(OpId:DWORD); - procedure _emit_V_MOV_B32; - procedure _emit_V_EXT_F32(OpId:DWORD); - procedure _emit_V_RCP_F32; + procedure emit_V_BFE_U32; + procedure emit_V_BFI_B32; + procedure emit_V_MAD_F32; + procedure emit_V_MAD_I32_I24; + procedure emit_V_MAD_U32_U24; + procedure emit_V_SAD_U32; + procedure emit_V_MAX3_F32; + procedure emit_V_MIN3_F32; + procedure emit_V_MED3_F32; + procedure emit_V_FMA_F32; + procedure emit_V_CUBE(OpId:DWORD); + procedure emit_V_MOV_B32; + procedure emit_V2_EXT_F32(OpId:DWORD); + procedure emit_V_RCP_F32; end; implementation -procedure TEmit_VOP3._emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean); +procedure TEmit_VOP3.emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean); Var dst:array[0..1] of PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst[0]:=FRegsStory.get_sdst7(FSPI.VOP3a.VDST+0); - dst[1]:=FRegsStory.get_sdst7(FSPI.VOP3a.VDST+1); - - Assert(dst[0]<>nil); - Assert(dst[1]<>nil); + if not get_sdst7_pair(FSPI.VOP3a.VDST,@dst) then Exit; Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP'); @@ -75,44 +68,40 @@ begin src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,rtype); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,rtype); - _emit_src_abs_bit(@src,2); - _emit_src_neg_bit(@src,2); + emit_src_abs_bit(@src,2); + emit_src_neg_bit(@src,2); - emit_OpCmpV(OpId,dst[0],src[0],src[1]); + OpCmpV(OpId,dst[0],src[0],src[1]); - SetConst(dst[1],dtUnknow,0); //set zero + SetConst_q(dst[1],dtUnknow,0); //set zero if x then begin - MakeCopy(@FRegsStory.EXEC[0],dst[0]^.current); - SetConst(@FRegsStory.EXEC[1],dtUnknow,0); //set zero + MakeCopy(get_exec0,dst[0]^.current); + SetConst_q(get_exec1,dtUnknow,0); //set zero end; end; -procedure TEmit_VOP3._emit_V_CMP_C(r,x:Boolean); +procedure TEmit_VOP3.emit_V_CMP_C(r,x:Boolean); Var dst:array[0..1] of PsrRegSlot; begin - dst[0]:=FRegsStory.get_sdst7(FSPI.VOP3a.VDST+0); - dst[1]:=FRegsStory.get_sdst7(FSPI.VOP3a.VDST+1); - - Assert(dst[0]<>nil); - Assert(dst[1]<>nil); + if not get_sdst7_pair(FSPI.VOP3a.VDST,@dst) then Exit; Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP'); - SetConst(dst[0],dtBool,QWORD(r)); - SetConst(dst[1],dtUnknow,0); //set zero + SetConst_b(dst[0],r); + SetConst_q(dst[1],dtUnknow,0); //set zero if x then begin - MakeCopy(@FRegsStory.EXEC[0],dst[0]^.current); - SetConst(@FRegsStory.EXEC[1],dtUnknow,0); //set zero + MakeCopy(get_exec0,dst[0]^.current); + SetConst_q(get_exec1,dtUnknow,0); //set zero end; end; -procedure TEmit_VOP3._emit_src_neg_bit(src:PPsrRegNode;count:Byte); +procedure TEmit_VOP3.emit_src_neg_bit(src:PPsrRegNode;count:Byte); var i:Byte; dst:PsrRegNode; @@ -123,23 +112,21 @@ begin if Byte(FSPI.VOP3a.NEG).TestBit(i) then begin dst:=NewReg(dtFloat32); - dst^.mark_read; - _emit_OpFNegate(line,dst,src[i]); + _Op1(line,Op.OpFNegate,dst,src[i]); src[i]:=dst; end; end; -procedure TEmit_VOP3._emit_src_abs(src:PPsrRegNode); +procedure TEmit_VOP3.emit_src_abs(src:PPsrRegNode); var dst:PsrRegNode; begin dst:=NewReg(dtFloat32); - dst^.mark_read; - _emit_OpFAbs(line,dst,src^); + _OpGlsl1(line,GlslOp.FAbs,dst,src^); src^:=dst; end; -procedure TEmit_VOP3._emit_src_abs_bit(src:PPsrRegNode;count:Byte); +procedure TEmit_VOP3.emit_src_abs_bit(src:PPsrRegNode;count:Byte); var i:Byte; begin @@ -148,62 +135,56 @@ begin For i:=0 to count-1 do if Byte(FSPI.VOP3a.ABS).TestBit(i) then begin - _emit_src_abs(@src[i]); + emit_src_abs(@src[i]); end; end; -procedure TEmit_VOP3._emit_dst_omod_f(dst:PsrRegSlot); +procedure TEmit_VOP3.emit_dst_omod_f(dst:PsrRegSlot); var src,tmp:PsrRegNode; begin + src:=dst^.current; Case FSPI.VOP3a.OMOD of 0:; 1: // *2 begin - src:=dst^.current; - src^.mark_read; - tmp:=FetchReg(FConsts.Fetchf(dtFloat32,2)); - emit_OpFMul(dst,src,tmp); + tmp:=NewReg_s(dtFloat32,2); + Op2(Op.OpFMul,dtFloat32,dst,src,tmp); end; 2: // *4 begin - src:=dst^.current; - src^.mark_read; - tmp:=FetchReg(FConsts.Fetchf(dtFloat32,4)); - emit_OpFMul(dst,src,tmp); + tmp:=NewReg_s(dtFloat32,4); + Op2(Op.OpFMul,dtFloat32,dst,src,tmp); end; 3: // /2 begin - src:=dst^.current; - src^.mark_read; - tmp:=FetchReg(FConsts.Fetchf(dtFloat32,2)); - emit_OpFDiv(dst,src,tmp); + tmp:=NewReg_s(dtFloat32,2); + Op2(Op.OpFDiv,dtFloat32,dst,src,tmp); end; end; end; -procedure TEmit_VOP3._emit_dst_clamp_f(dst:PsrRegSlot); +procedure TEmit_VOP3.emit_dst_clamp_f(dst:PsrRegSlot); var src,min,max:PsrRegNode; begin if (FSPI.VOP3a.CLAMP=0) then Exit; src:=dst^.current; - src^.mark_read; - min:=FetchReg(FConsts.Fetchf(dtFloat32,0)); - max:=FetchReg(FConsts.Fetchf(dtFloat32,1)); + min:=NewReg_s(dtFloat32,0); + max:=NewReg_s(dtFloat32,1); - emit_OpFClamp(dst,src,min,max); + OpGlsl3(GlslOp.FClamp,dtFloat32,dst,src,min,max); end; -procedure TEmit_VOP3._emit_V_CNDMASK_B32; +procedure TEmit_VOP3.emit_V_CNDMASK_B32; Var dst:PsrRegSlot; src:array[0..2] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + dst:=get_vdst8(FSPI.VOP3a.VDST); Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP'); @@ -212,56 +193,37 @@ begin src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtUnknow); src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtBool); - _emit_src_abs_bit(@src,2); - _emit_src_neg_bit(@src,2); + emit_src_abs_bit(@src,2); + emit_src_neg_bit(@src,2); - emit_OpSelect(dst,src[0],src[1],src[2]); + OpSelect(dst,src[0],src[1],src[2]); end; -procedure TEmit_VOP3._emit_V_ADD_F32; +procedure TEmit_VOP3.emit_V2_F32(OpId:DWORD); Var dst:PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + dst:=get_vdst8(FSPI.VOP3a.VDST); src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); - _emit_src_abs_bit(@src,2); - _emit_src_neg_bit(@src,2); + emit_src_abs_bit(@src,2); + emit_src_neg_bit(@src,2); - emit_OpFAdd(dst,src[0],src[1]); + Op2(OpId,dtFloat32,dst,src[0],src[1]); - _emit_dst_omod_f(dst); - _emit_dst_clamp_f(dst); + emit_dst_omod_f(dst); + emit_dst_clamp_f(dst); end; -procedure TEmit_VOP3._emit_V_SUB_F32; +procedure TEmit_VOP3.emit_V_CVT_PKRTZ_F16_F32; Var dst:PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); - - src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); - src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); - - _emit_src_abs_bit(@src,2); - _emit_src_neg_bit(@src,2); - - emit_OpFSub(dst,src[0],src[1]); - - _emit_dst_omod_f(dst); - _emit_dst_clamp_f(dst); -end; - -procedure TEmit_VOP3._emit_V_CVT_PKRTZ_F16_F32; -Var - dst:PsrRegSlot; - src:array[0..1] of PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + dst:=get_vdst8(FSPI.VOP3a.VDST); Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP'); @@ -269,37 +231,37 @@ begin src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); - _emit_src_abs_bit(@src,2); - _emit_src_neg_bit(@src,2); + emit_src_abs_bit(@src,2); + emit_src_neg_bit(@src,2); - _emit_ConvFloatToHalf(dst,src[0],src[1]); + OpConvFloatToHalf2(dst,src[0],src[1]); end; -procedure TEmit_VOP3._emit_V_MIN_MAX_F32(OpId:DWORD); +procedure TEmit_VOP3.emit_V_MMX_F32(OpId:DWORD); Var dst:PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + dst:=get_vdst8(FSPI.VOP3a.VDST); src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); - _emit_src_abs_bit(@src,2); - _emit_src_neg_bit(@src,2); + emit_src_abs_bit(@src,2); + emit_src_neg_bit(@src,2); - emit_OpExt2(OpId,dtFloat32,dst,src[0],src[1]); + OpGlsl2(OpId,dtFloat32,dst,src[0],src[1]); - _emit_dst_omod_f(dst); - _emit_dst_clamp_f(dst); + emit_dst_omod_f(dst); + emit_dst_clamp_f(dst); end; -procedure TEmit_VOP3._emit_V_MUL_LO_I32; +procedure TEmit_VOP3.emit_V_MUL_LO_I32; Var dst:PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + dst:=get_vdst8(FSPI.VOP3a.VDST); Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS'); @@ -309,36 +271,16 @@ begin src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtInt32); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtInt32); - emit_OpIMul(dst,src[0],src[1]); + OpIMul(dst,src[0],src[1]); end; -procedure TEmit_VOP3._emit_V_MUL_F32; +procedure TEmit_VOP3.emit_V_MUL_I32_I24; Var dst:PsrRegSlot; src:array[0..1] of PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); - - src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); - src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); - - _emit_src_abs_bit(@src,2); - _emit_src_neg_bit(@src,2); - - emit_OpFMul(dst,src[0],src[1]); - - _emit_dst_omod_f(dst); - _emit_dst_clamp_f(dst); -end; - -procedure TEmit_VOP3._emit_V_MUL_I32_I24; -Var - dst,tmp:PsrRegSlot; - src:array[0..1] of PsrRegNode; bit24:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); - tmp:=@FRegsStory.FUnattach; + dst:=get_vdst8(FSPI.VOP3a.VDST); Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS'); @@ -348,27 +290,24 @@ begin src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtInt32); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtInt32); - bit24:=FetchReg(FConsts.Fetch(dtUInt32,$FFFFFF)); + bit24:=NewReg_q(dtUInt32,$FFFFFF); - emit_OpBitwiseAnd(tmp,src[0],bit24); - src[0]:=MakeRead(tmp,dtInt32); + src[0]:=OpBitwiseAndTo(src[0],bit24); + src[0]^.PrepType(ord(dtInt32)); - bit24^.mark_read; + src[1]:=OpBitwiseAndTo(src[1],bit24); + src[1]^.PrepType(ord(dtInt32)); - emit_OpBitwiseAnd(tmp,src[1],bit24); - src[1]:=MakeRead(tmp,dtInt32); - - emit_OpIMul(dst,src[0],src[1]); + OpIMul(dst,src[0],src[1]); end; -procedure TEmit_VOP3._emit_V_MUL_U32_U24; +procedure TEmit_VOP3.emit_V_MUL_U32_U24; Var - dst,tmp:PsrRegSlot; + dst:PsrRegSlot; src:array[0..1] of PsrRegNode; bit24:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); - tmp:=@FRegsStory.FUnattach; + dst:=get_vdst8(FSPI.VOP3a.VDST); Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS'); @@ -378,27 +317,24 @@ begin src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtUInt32); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtUInt32); - bit24:=FetchReg(FConsts.Fetch(dtUInt32,$FFFFFF)); + bit24:=NewReg_q(dtUInt32,$FFFFFF); - emit_OpBitwiseAnd(tmp,src[0],bit24); - src[0]:=MakeRead(tmp,dtUInt32); + src[0]:=OpBitwiseAndTo(src[0],bit24); + src[0]^.PrepType(ord(dtUInt32)); - bit24^.mark_read; + src[1]:=OpBitwiseAndTo(src[1],bit24); + src[1]^.PrepType(ord(dtUInt32)); - emit_OpBitwiseAnd(tmp,src[1],bit24); - src[1]:=MakeRead(tmp,dtUInt32); - - emit_OpIMul(dst,src[0],src[1]); + OpIMul(dst,src[0],src[1]); end; -procedure TEmit_VOP3._emit_V_MUL_HI_U32; +procedure TEmit_VOP3.emit_V_MUL_HI_U32; Var - dst,tmp:PsrRegSlot; + dst:PsrRegSlot; src:array[0..1] of PsrRegNode; tmp_r,dst_r:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); - tmp:=@FRegsStory.FUnattach; + dst:=get_vdst8(FSPI.VOP3a.VDST); Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS'); @@ -408,43 +344,40 @@ begin src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtUInt32); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtUInt32); - emit_Op2(Op.OpUMulExtended,dtStruct2u,tmp,src[0],src[1]); + tmp_r:=NewReg(dtStruct2u); + _Op2(line,Op.OpUMulExtended,tmp_r,src[0],src[1]); - tmp_r:=MakeRead(tmp,dtStruct2u); dst_r:=dst^.New(line,dtUInt32); - emit_OpCompExtract(line,dst_r,tmp_r,1); + OpExtract(line,dst_r,tmp_r,1); end; -procedure TEmit_VOP3._emit_V_MAC_F32; //vdst = vsrc0.f * vsrc1.f + vdst.f -> fma +procedure TEmit_VOP3.emit_V_MAC_F32; //vdst = vsrc0.f * vsrc1.f + vdst.f -> fma Var dst:PsrRegSlot; src:array[0..2] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + dst:=get_vdst8(FSPI.VOP3a.VDST); src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); src[2]:=MakeRead(dst,dtFloat32); - _emit_src_abs_bit(@src,3); - _emit_src_neg_bit(@src,3); + emit_src_abs_bit(@src,3); + emit_src_neg_bit(@src,3); - emit_OpFmaF32(dst,src[0],src[1],src[2]); + OpFmaF32(dst,src[0],src[1],src[2]); - _emit_dst_omod_f(dst); - _emit_dst_clamp_f(dst); + emit_dst_omod_f(dst); + emit_dst_clamp_f(dst); end; -procedure TEmit_VOP3._emit_V_BFE_U32; +procedure TEmit_VOP3.emit_V_BFE_U32; Var - dst,tmp:PsrRegSlot; + dst:PsrRegSlot; src:array[0..2] of PsrRegNode; - num_31:PsrRegNode; - offset,count:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); - tmp:=@FRegsStory.FUnattach; + dst:=get_vdst8(FSPI.VOP3a.VDST); Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS'); @@ -455,26 +388,16 @@ begin src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtUint32); src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtUint32); - num_31:=FetchReg(FConsts.Fetch(dtUInt32,31)); - - emit_OpBitwiseAnd(tmp,src[1],num_31); - offset:=MakeRead(tmp,dtUInt32); - - num_31^.mark_read; - emit_OpBitwiseAnd(tmp,src[2],num_31); - count:=MakeRead(tmp,dtUInt32); - - emit_OpBfeU(dst,src[0],offset,count); + OpBFEU32(dst,src[0],src[1],src[2]); end; -procedure TEmit_VOP3._emit_V_BFI_B32; +procedure TEmit_VOP3.emit_V_BFI_B32; Var - dst,tmp:PsrRegSlot; + dst:PsrRegSlot; bitmsk:PsrRegNode; src:array[0..1] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); - tmp:=@FRegsStory.FUnattach; + dst:=get_vdst8(FSPI.VOP3a.VDST); Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS'); @@ -485,46 +408,36 @@ begin src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtUint32); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtUint32); - emit_OpBitwiseAnd(tmp,src[0],bitmsk); - src[0]:=MakeRead(tmp,dtUInt32); - - emit_OpNot(tmp,bitmsk); - bitmsk:=MakeRead(tmp,dtUInt32); - - emit_OpBitwiseAnd(tmp,src[1],bitmsk); - src[1]:=MakeRead(tmp,dtUInt32); - - emit_OpBitwiseOr(dst,src[0],src[1]); + OpBFIB32(dst,bitmsk,src[0],src[1]); end; -procedure TEmit_VOP3._emit_V_MAD_F32; //vdst = vsrc0.f * vsrc1.f + vadd.f +procedure TEmit_VOP3.emit_V_MAD_F32; //vdst = vsrc0.f * vsrc1.f + vadd.f Var dst:PsrRegSlot; src:array[0..2] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + dst:=get_vdst8(FSPI.VOP3a.VDST); src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32); - _emit_src_abs_bit(@src,3); - _emit_src_neg_bit(@src,3); + emit_src_abs_bit(@src,3); + emit_src_neg_bit(@src,3); - emit_OpFmaF32(dst,src[0],src[1],src[2]); + OpFmaF32(dst,src[0],src[1],src[2]); - _emit_dst_omod_f(dst); - _emit_dst_clamp_f(dst); + emit_dst_omod_f(dst); + emit_dst_clamp_f(dst); end; -procedure TEmit_VOP3._emit_V_MAD_I32_I24; +procedure TEmit_VOP3.emit_V_MAD_I32_I24; Var - dst,tmp:PsrRegSlot; + dst:PsrRegSlot; src:array[0..2] of PsrRegNode; bit24:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); - tmp:=@FRegsStory.FUnattach; + dst:=get_vdst8(FSPI.VOP3a.VDST); Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS'); @@ -535,27 +448,24 @@ begin src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtInt32); src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtInt32); - bit24:=FetchReg(FConsts.Fetch(dtUInt32,$FFFFFF)); + bit24:=NewReg_q(dtUInt32,$FFFFFF); - emit_OpBitwiseAnd(tmp,src[0],bit24); - src[0]:=MakeRead(tmp,dtInt32); + src[0]:=OpBitwiseAndTo(src[0],bit24); + src[0]^.PrepType(ord(dtInt32)); - bit24^.mark_read; + src[1]:=OpBitwiseAndTo(src[1],bit24); + src[1]^.PrepType(ord(dtInt32)); - emit_OpBitwiseAnd(tmp,src[1],bit24); - src[1]:=MakeRead(tmp,dtInt32); - - emit_OpFmaI32(dst,src[0],src[1],src[2]); + OpFmaI32(dst,src[0],src[1],src[2]); end; -procedure TEmit_VOP3._emit_V_MAD_U32_U24; +procedure TEmit_VOP3.emit_V_MAD_U32_U24; Var - dst,tmp:PsrRegSlot; + dst:PsrRegSlot; src:array[0..2] of PsrRegNode; bit24:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); - tmp:=@FRegsStory.FUnattach; + dst:=get_vdst8(FSPI.VOP3a.VDST); Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS'); @@ -566,27 +476,25 @@ begin src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtUInt32); src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtUInt32); - bit24:=FetchReg(FConsts.Fetch(dtUInt32,$FFFFFF)); + bit24:=NewReg_q(dtUInt32,$FFFFFF); - emit_OpBitwiseAnd(tmp,src[0],bit24); - src[0]:=MakeRead(tmp,dtUInt32); + src[0]:=OpBitwiseAndTo(src[0],bit24); + src[0]^.PrepType(ord(dtUInt32)); - bit24^.mark_read; + src[1]:=OpBitwiseAndTo(src[1],bit24); + src[1]^.PrepType(ord(dtUInt32)); - emit_OpBitwiseAnd(tmp,src[1],bit24); - src[1]:=MakeRead(tmp,dtUInt32); - - emit_OpFmaU32(dst,src[0],src[1],src[2]); + OpFmaU32(dst,src[0],src[1],src[2]); end; -procedure TEmit_VOP3._emit_V_SAD_U32; //dst.u = abs(vsrc0.u - vsrc1.u) + vaccum.u +procedure TEmit_VOP3.emit_V_SAD_U32; //dst.u = abs(vsrc0.u - vsrc1.u) + vaccum.u Var dst:PsrRegSlot; src:array[0..2] of PsrRegNode; rdif,rvac:PsrRegNode; //msk:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + dst:=get_vdst8(FSPI.VOP3a.VDST); Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS'); @@ -597,118 +505,103 @@ begin src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtUInt32); src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtUInt32); - rdif:=NewReg(dtInt32); - _emit_OpAbsDiff(line,rdif,src[0],src[1]); + rdif:=NewReg(dtUInt32); + OpAbsDiff(line,rdif,src[0],src[1]); - //msk:=FetchReg(FConsts.Fetch(dtUInt32,$FFFF)); mask need? - //emit_OpBitwiseAnd(tmp,src[2],msk); + //msk:=NewReg(pConsts^.Fetch(dtUInt32,$FFFF)); mask need? + //OpBitwiseAnd(tmp,src[2],msk); //rvac:=tmp^.current; rvac:=src[2]; - rdif^.mark_read; - rvac^.mark_read; - emit_OpIAdd(dst,rdif,rvac); + OpIAdd(dst,rdif,rvac); end; -procedure TEmit_VOP3._emit_V_MAX3_F32; -Var - dst,tmp:PsrRegSlot; - src:array[0..3] of PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); - tmp:=@FRegsStory.FUnattach; - - src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); - src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); - src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32); - - _emit_src_abs_bit(@src,3); - _emit_src_neg_bit(@src,3); - - emit_OpFMax(tmp,src[0],src[1]); - src[3]:=MakeRead(tmp,dtFloat32); - - emit_OpFMax(dst,src[3],src[2]); - - _emit_dst_omod_f(dst); - _emit_dst_clamp_f(dst); -end; - -procedure TEmit_VOP3._emit_V_MIN3_F32; -Var - dst,tmp:PsrRegSlot; - src:array[0..3] of PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); - tmp:=@FRegsStory.FUnattach; - - src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); - src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); - src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32); - - _emit_src_abs_bit(@src,3); - _emit_src_neg_bit(@src,3); - - emit_OpFMin(tmp,src[0],src[1]); - src[3]:=MakeRead(tmp,dtFloat32); - - emit_OpFMin(dst,src[3],src[2]); - - _emit_dst_omod_f(dst); - _emit_dst_clamp_f(dst); -end; - -procedure TEmit_VOP3._emit_V_MED3_F32; -Var - dst:PsrRegSlot; - src:array[0..3] of PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); - - src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); - src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); - src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32); - - _emit_src_abs_bit(@src,3); - _emit_src_neg_bit(@src,3); - - emit_MED3F(dst,src[0],src[1],src[2]); - - _emit_dst_omod_f(dst); - _emit_dst_clamp_f(dst); -end; - -procedure TEmit_VOP3._emit_V_FMA_F32; +procedure TEmit_VOP3.emit_V_MAX3_F32; Var dst:PsrRegSlot; src:array[0..2] of PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + dst:=get_vdst8(FSPI.VOP3a.VDST); src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32); - _emit_src_abs_bit(@src,3); - _emit_src_neg_bit(@src,3); + emit_src_abs_bit(@src,3); + emit_src_neg_bit(@src,3); - emit_OpFmaF32(dst,src[0],src[1],src[2]); + OpGlsl2(GlslOp.FMax,dtFloat32,dst,OpFMaxTo(src[0],src[1]),src[2]); - _emit_dst_omod_f(dst); - _emit_dst_clamp_f(dst); + emit_dst_omod_f(dst); + emit_dst_clamp_f(dst); end; -{ -procedure TEmit_VOP3._emit_V_CUBEMA_F32; +procedure TEmit_VOP3.emit_V_MIN3_F32; Var dst:PsrRegSlot; src:array[0..2] of PsrRegNode; - max:array[0..1] of PsrRegNode; - num_2:PsrRegNode; begin - //max(max(abs(x),abs(y)),abs(z))*2 + dst:=get_vdst8(FSPI.VOP3a.VDST); - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); + src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); + src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32); + + emit_src_abs_bit(@src,3); + emit_src_neg_bit(@src,3); + + OpGlsl2(GlslOp.FMin,dtFloat32,dst,OpFMinTo(src[0],src[1]),src[2]); + + emit_dst_omod_f(dst); + emit_dst_clamp_f(dst); +end; + +procedure TEmit_VOP3.emit_V_MED3_F32; +Var + dst:PsrRegSlot; + src:array[0..2] of PsrRegNode; +begin + dst:=get_vdst8(FSPI.VOP3a.VDST); + + src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); + src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); + src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32); + + emit_src_abs_bit(@src,3); + emit_src_neg_bit(@src,3); + + OpMED3F(dst,src[0],src[1],src[2]); + + emit_dst_omod_f(dst); + emit_dst_clamp_f(dst); +end; + +procedure TEmit_VOP3.emit_V_FMA_F32; +Var + dst:PsrRegSlot; + src:array[0..2] of PsrRegNode; +begin + dst:=get_vdst8(FSPI.VOP3a.VDST); + + src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); + src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); + src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32); + + emit_src_abs_bit(@src,3); + emit_src_neg_bit(@src,3); + + OpFmaF32(dst,src[0],src[1],src[2]); + + emit_dst_omod_f(dst); + emit_dst_clamp_f(dst); +end; + +procedure TEmit_VOP3.emit_V_CUBE(OpId:DWORD); +Var + dst:PsrRegSlot; + src:array[0..2] of PsrRegNode; +begin + dst:=get_vdst8(FSPI.VOP3a.VDST); Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS'); @@ -719,49 +612,15 @@ begin src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32); - _emit_src_abs(@src[0]); - _emit_src_abs(@src[1]); - _emit_src_abs(@src[2]); - - max[0]:=NewReg(dtFloat32); - max[0]^.mark_read; - _emit_OpFMax(line,max[0],src[0],src[1]); - - max[1]:=NewReg(dtFloat32); - max[1]^.mark_read; - _emit_OpFMax(line,max[1],max[0],src[2]); - - num_2:=FetchReg(FConsts.Fetchf(dtFloat32,2)); - - emit_OpFMul(dst,max[1],num_2); -end; -} - -procedure TEmit_VOP3._emit_V_CUBE(OpId:DWORD); -Var - dst:PsrRegSlot; - src:array[0..2] of PsrRegNode; -begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); - - Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); - Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS'); - Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP'); - Assert(FSPI.VOP3a.NEG =0,'FSPI.VOP3a.NEG'); - - src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); - src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32); - src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32); - - emit_Op3(OpId,dtFloat32,dst,src[0],src[1],src[2]); + Op3(OpId,dtFloat32,dst,src[0],src[1],src[2]); end; -procedure TEmit_VOP3._emit_V_MOV_B32; +procedure TEmit_VOP3.emit_V_MOV_B32; Var dst:PsrRegSlot; src:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + dst:=get_vdst8(FSPI.VOP3a.VDST); Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP'); @@ -771,59 +630,59 @@ begin begin src:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); - _emit_src_abs_bit(@src,1); - _emit_src_neg_bit(@src,1); + emit_src_abs_bit(@src,1); + emit_src_neg_bit(@src,1); - _MakeCopy(dst,src); + MakeCopy(dst,src); end else begin src:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtUnknow); - _MakeCopy(dst,src); + MakeCopy(dst,src); end; end; -procedure TEmit_VOP3._emit_V_EXT_F32(OpId:DWORD); +procedure TEmit_VOP3.emit_V2_EXT_F32(OpId:DWORD); Var dst:PsrRegSlot; src:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + dst:=get_vdst8(FSPI.VOP3a.VDST); src:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); - _emit_src_abs_bit(@src,1); - _emit_src_neg_bit(@src,1); + emit_src_abs_bit(@src,1); + emit_src_neg_bit(@src,1); - emit_OpExt1(OpId,dtFloat32,dst,src); + OpGlsl1(OpId,dtFloat32,dst,src); - _emit_dst_omod_f(dst); - _emit_dst_clamp_f(dst); + emit_dst_omod_f(dst); + emit_dst_clamp_f(dst); end; -procedure TEmit_VOP3._emit_V_RCP_F32; +procedure TEmit_VOP3.emit_V_RCP_F32; Var dst:PsrRegSlot; src:PsrRegNode; one:PsrRegNode; begin - dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + dst:=get_vdst8(FSPI.VOP3a.VDST); src:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); - _emit_src_abs_bit(@src,1); - _emit_src_neg_bit(@src,1); + emit_src_abs_bit(@src,1); + emit_src_neg_bit(@src,1); - one:=FetchReg(FConsts.Fetchf(dtFloat32,1)); + one:=NewReg_s(dtFloat32,1); - emit_OpFDiv(dst,one,src); + Op2(Op.OpFDiv,dtFloat32,dst,one,src); - _emit_dst_omod_f(dst); - _emit_dst_clamp_f(dst); + emit_dst_omod_f(dst); + emit_dst_clamp_f(dst); end; -procedure TEmit_VOP3._emit_VOP3c; +procedure TEmit_VOP3.emit_VOP3c; begin Case FSPI.VOP3a.OP of @@ -834,7 +693,7 @@ begin V_CMP_F_U32, V_CMP_F_U64, V_CMPS_F_F32, - V_CMPS_F_F64:_emit_V_CMP_C(false,false); + V_CMPS_F_F64:emit_V_CMP_C(false,false); V_CMP_T_F32, V_CMP_T_F64, @@ -843,7 +702,7 @@ begin V_CMP_T_U32, V_CMP_T_U64, V_CMPS_T_F32, - V_CMPS_T_F64:_emit_V_CMP_C(true,false); + V_CMPS_T_F64:emit_V_CMP_C(true,false); V_CMPX_F_F32, V_CMPX_F_F64, @@ -852,7 +711,7 @@ begin V_CMPX_F_U32, V_CMPX_F_U64, V_CMPSX_F_F32, - V_CMPSX_F_F64:_emit_V_CMP_C(false,true); + V_CMPSX_F_F64:emit_V_CMP_C(false,true); V_CMPX_T_F32, V_CMPX_T_F64, @@ -861,101 +720,101 @@ begin V_CMPX_T_U32, V_CMPX_T_U64, V_CMPSX_T_F32, - V_CMPSX_T_F64:_emit_V_CMP_C(true,true); + V_CMPSX_T_F64:emit_V_CMP_C(true,true); // - V_CMP_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,false); - V_CMP_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,false); - V_CMP_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,false); - V_CMP_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,false); - V_CMP_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,false); - V_CMP_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,false); - V_CMP_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,false); - V_CMP_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,false); - V_CMP_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,false); - V_CMP_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,false); - V_CMP_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,false); - V_CMP_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,false); - V_CMP_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,false); - V_CMP_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,false); + V_CMP_LT_F32 :emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,false); + V_CMP_EQ_F32 :emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,false); + V_CMP_LE_F32 :emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,false); + V_CMP_GT_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,false); + V_CMP_LG_F32 :emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,false); + V_CMP_GE_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,false); + V_CMP_O_F32 :emit_V_CMP_32(Op.OpOrdered ,dtFloat32,false); + V_CMP_U_F32 :emit_V_CMP_32(Op.OpUnordered ,dtFloat32,false); + V_CMP_NGE_F32 :emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,false); + V_CMP_NLG_F32 :emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,false); + V_CMP_NGT_F32 :emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,false); + V_CMP_NLE_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,false); + V_CMP_NEQ_F32 :emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,false); + V_CMP_NLT_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,false); - V_CMPX_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,true); - V_CMPX_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,true); - V_CMPX_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,true); - V_CMPX_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,true); - V_CMPX_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,true); - V_CMPX_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,true); - V_CMPX_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,true); - V_CMPX_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,true); - V_CMPX_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,true); - V_CMPX_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,true); - V_CMPX_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,true); - V_CMPX_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,true); - V_CMPX_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,true); - V_CMPX_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,true); + V_CMPX_LT_F32 :emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,true); + V_CMPX_EQ_F32 :emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,true); + V_CMPX_LE_F32 :emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,true); + V_CMPX_GT_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,true); + V_CMPX_LG_F32 :emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,true); + V_CMPX_GE_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,true); + V_CMPX_O_F32 :emit_V_CMP_32(Op.OpOrdered ,dtFloat32,true); + V_CMPX_U_F32 :emit_V_CMP_32(Op.OpUnordered ,dtFloat32,true); + V_CMPX_NGE_F32 :emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,true); + V_CMPX_NLG_F32 :emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,true); + V_CMPX_NGT_F32 :emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,true); + V_CMPX_NLE_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,true); + V_CMPX_NEQ_F32 :emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,true); + V_CMPX_NLT_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,true); // - V_CMPS_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,false); - V_CMPS_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,false); - V_CMPS_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,false); - V_CMPS_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,false); - V_CMPS_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,false); - V_CMPS_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,false); - V_CMPS_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,false); - V_CMPS_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,false); - V_CMPS_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,false); - V_CMPS_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,false); - V_CMPS_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,false); - V_CMPS_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,false); - V_CMPS_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,false); - V_CMPS_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,false); + V_CMPS_LT_F32 :emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,false); + V_CMPS_EQ_F32 :emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,false); + V_CMPS_LE_F32 :emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,false); + V_CMPS_GT_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,false); + V_CMPS_LG_F32 :emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,false); + V_CMPS_GE_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,false); + V_CMPS_O_F32 :emit_V_CMP_32(Op.OpOrdered ,dtFloat32,false); + V_CMPS_U_F32 :emit_V_CMP_32(Op.OpUnordered ,dtFloat32,false); + V_CMPS_NGE_F32 :emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,false); + V_CMPS_NLG_F32 :emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,false); + V_CMPS_NGT_F32 :emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,false); + V_CMPS_NLE_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,false); + V_CMPS_NEQ_F32 :emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,false); + V_CMPS_NLT_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,false); - V_CMPSX_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,true); - V_CMPSX_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,true); - V_CMPSX_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,true); - V_CMPSX_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,true); - V_CMPSX_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,true); - V_CMPSX_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,true); - V_CMPSX_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,true); - V_CMPSX_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,true); - V_CMPSX_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,true); - V_CMPSX_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,true); - V_CMPSX_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,true); - V_CMPSX_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,true); - V_CMPSX_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,true); - V_CMPSX_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,true); + V_CMPSX_LT_F32 :emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,true); + V_CMPSX_EQ_F32 :emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,true); + V_CMPSX_LE_F32 :emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,true); + V_CMPSX_GT_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,true); + V_CMPSX_LG_F32 :emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,true); + V_CMPSX_GE_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,true); + V_CMPSX_O_F32 :emit_V_CMP_32(Op.OpOrdered ,dtFloat32,true); + V_CMPSX_U_F32 :emit_V_CMP_32(Op.OpUnordered ,dtFloat32,true); + V_CMPSX_NGE_F32 :emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,true); + V_CMPSX_NLG_F32 :emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,true); + V_CMPSX_NGT_F32 :emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,true); + V_CMPSX_NLE_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,true); + V_CMPSX_NEQ_F32 :emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,true); + V_CMPSX_NLT_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,true); // - V_CMP_LT_I32 :_emit_V_CMP_32(Op.OpSLessThan ,dtInt32,false); - V_CMP_EQ_I32 :_emit_V_CMP_32(Op.OpIEqual ,dtInt32,false); - V_CMP_LE_I32 :_emit_V_CMP_32(Op.OpSLessThanEqual ,dtInt32,false); - V_CMP_GT_I32 :_emit_V_CMP_32(Op.OpSGreaterThan ,dtInt32,false); - V_CMP_LG_I32 :_emit_V_CMP_32(Op.OpINotEqual ,dtInt32,false); - V_CMP_GE_I32 :_emit_V_CMP_32(Op.OpSGreaterThanEqual ,dtInt32,false); + V_CMP_LT_I32 :emit_V_CMP_32(Op.OpSLessThan ,dtInt32,false); + V_CMP_EQ_I32 :emit_V_CMP_32(Op.OpIEqual ,dtInt32,false); + V_CMP_LE_I32 :emit_V_CMP_32(Op.OpSLessThanEqual ,dtInt32,false); + V_CMP_GT_I32 :emit_V_CMP_32(Op.OpSGreaterThan ,dtInt32,false); + V_CMP_LG_I32 :emit_V_CMP_32(Op.OpINotEqual ,dtInt32,false); + V_CMP_GE_I32 :emit_V_CMP_32(Op.OpSGreaterThanEqual ,dtInt32,false); - V_CMPX_LT_I32 :_emit_V_CMP_32(Op.OpSLessThan ,dtInt32,true); - V_CMPX_EQ_I32 :_emit_V_CMP_32(Op.OpIEqual ,dtInt32,true); - V_CMPX_LE_I32 :_emit_V_CMP_32(Op.OpSLessThanEqual ,dtInt32,true); - V_CMPX_GT_I32 :_emit_V_CMP_32(Op.OpSGreaterThan ,dtInt32,true); - V_CMPX_LG_I32 :_emit_V_CMP_32(Op.OpINotEqual ,dtInt32,true); - V_CMPX_GE_I32 :_emit_V_CMP_32(Op.OpSGreaterThanEqual ,dtInt32,true); + V_CMPX_LT_I32 :emit_V_CMP_32(Op.OpSLessThan ,dtInt32,true); + V_CMPX_EQ_I32 :emit_V_CMP_32(Op.OpIEqual ,dtInt32,true); + V_CMPX_LE_I32 :emit_V_CMP_32(Op.OpSLessThanEqual ,dtInt32,true); + V_CMPX_GT_I32 :emit_V_CMP_32(Op.OpSGreaterThan ,dtInt32,true); + V_CMPX_LG_I32 :emit_V_CMP_32(Op.OpINotEqual ,dtInt32,true); + V_CMPX_GE_I32 :emit_V_CMP_32(Op.OpSGreaterThanEqual ,dtInt32,true); - V_CMP_LT_U32 :_emit_V_CMP_32(Op.OpULessThan ,dtUint32,false); - V_CMP_EQ_U32 :_emit_V_CMP_32(Op.OpIEqual ,dtUint32,false); - V_CMP_LE_U32 :_emit_V_CMP_32(Op.OpULessThanEqual ,dtUint32,false); - V_CMP_GT_U32 :_emit_V_CMP_32(Op.OpUGreaterThan ,dtUint32,false); - V_CMP_LG_U32 :_emit_V_CMP_32(Op.OpINotEqual ,dtUint32,false); - V_CMP_GE_U32 :_emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,false); + V_CMP_LT_U32 :emit_V_CMP_32(Op.OpULessThan ,dtUint32,false); + V_CMP_EQ_U32 :emit_V_CMP_32(Op.OpIEqual ,dtUint32,false); + V_CMP_LE_U32 :emit_V_CMP_32(Op.OpULessThanEqual ,dtUint32,false); + V_CMP_GT_U32 :emit_V_CMP_32(Op.OpUGreaterThan ,dtUint32,false); + V_CMP_LG_U32 :emit_V_CMP_32(Op.OpINotEqual ,dtUint32,false); + V_CMP_GE_U32 :emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,false); - V_CMPX_LT_U32 :_emit_V_CMP_32(Op.OpULessThan ,dtUint32,true); - V_CMPX_EQ_U32 :_emit_V_CMP_32(Op.OpIEqual ,dtUint32,true); - V_CMPX_LE_U32 :_emit_V_CMP_32(Op.OpULessThanEqual ,dtUint32,true); - V_CMPX_GT_U32 :_emit_V_CMP_32(Op.OpUGreaterThan ,dtUint32,true); - V_CMPX_LG_U32 :_emit_V_CMP_32(Op.OpINotEqual ,dtUint32,true); - V_CMPX_GE_U32 :_emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,true); + V_CMPX_LT_U32 :emit_V_CMP_32(Op.OpULessThan ,dtUint32,true); + V_CMPX_EQ_U32 :emit_V_CMP_32(Op.OpIEqual ,dtUint32,true); + V_CMPX_LE_U32 :emit_V_CMP_32(Op.OpULessThanEqual ,dtUint32,true); + V_CMPX_GT_U32 :emit_V_CMP_32(Op.OpUGreaterThan ,dtUint32,true); + V_CMPX_LG_U32 :emit_V_CMP_32(Op.OpINotEqual ,dtUint32,true); + V_CMPX_GE_U32 :emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,true); else Assert(false,'VOP3c?'+IntToStr(FSPI.VOP3a.OP)); @@ -963,159 +822,82 @@ begin end; -procedure TEmit_VOP3._emit_VOP3b; +procedure TEmit_VOP3.emit_VOP3b; begin Assert(false,'VOP3b?'+IntToStr(FSPI.VOP3b.OP)); end; -procedure TEmit_VOP3._emit_VOP3a; +procedure TEmit_VOP3.emit_VOP3a; begin - - //VOP2 analog - Case FSPI.VOP3a.OP of - 256+V_CNDMASK_B32: - begin - _emit_V_CNDMASK_B32; - end; + //VOP2 analog - 256+V_ADD_F32: - begin - _emit_V_ADD_F32; - end; + 256+V_CNDMASK_B32: emit_V_CNDMASK_B32; - 256+V_SUB_F32: - begin - _emit_V_SUB_F32; - end; + 256+V_ADD_F32: emit_V2_F32(Op.OpFAdd); + 256+V_SUB_F32: emit_V2_F32(Op.OpFSub); - 256+V_CVT_PKRTZ_F16_F32: - begin - _emit_V_CVT_PKRTZ_F16_F32; - end; + 256+V_CVT_PKRTZ_F16_F32: emit_V_CVT_PKRTZ_F16_F32; - 256+V_MIN_LEGACY_F32:_emit_V_MIN_MAX_F32(GlslOp.NMin); - 256+V_MAX_LEGACY_F32:_emit_V_MIN_MAX_F32(GlslOp.NMax); + 256+V_MIN_LEGACY_F32:emit_V_MMX_F32(GlslOp.NMin); + 256+V_MAX_LEGACY_F32:emit_V_MMX_F32(GlslOp.NMax); - 256+V_MIN_F32:_emit_V_MIN_MAX_F32(GlslOp.FMin); - 256+V_MAX_F32:_emit_V_MIN_MAX_F32(GlslOp.FMax); + 256+V_MIN_F32:emit_V_MMX_F32(GlslOp.FMin); + 256+V_MAX_F32:emit_V_MMX_F32(GlslOp.FMax); - 256+V_MUL_F32: - begin - _emit_V_MUL_F32; - end; + 256+V_MUL_F32: emit_V2_F32(Op.OpFMul); - 256+V_MUL_I32_I24: - begin - _emit_V_MUL_I32_I24; - end; + 256+V_MUL_I32_I24: emit_V_MUL_I32_I24; + 256+V_MUL_U32_U24: emit_V_MUL_U32_U24; - 256+V_MUL_U32_U24: - begin - _emit_V_MUL_U32_U24; - end; - - 256+V_MAC_F32: - begin - _emit_V_MAC_F32; - end; + 256+V_MAC_F32: emit_V_MAC_F32; //VOP3 only - V_MUL_LO_I32: - begin - _emit_V_MUL_LO_I32; - end; + V_MUL_LO_I32: emit_V_MUL_LO_I32; + V_MUL_HI_U32: emit_V_MUL_HI_U32; - V_MUL_HI_U32: - begin - _emit_V_MUL_HI_U32; - end; + V_BFE_U32: emit_V_BFE_U32; + V_BFI_B32: emit_V_BFI_B32; + V_MAD_F32: emit_V_MAD_F32; - V_BFE_U32: - begin - _emit_V_BFE_U32; - end; + V_MAD_I32_I24: emit_V_MAD_I32_I24; + V_MAD_U32_U24: emit_V_MAD_U32_U24; - V_BFI_B32: - begin - _emit_V_BFI_B32; - end; + V_SAD_U32 : emit_V_SAD_U32; + V_MAX3_F32: emit_V_MAX3_F32; + V_MIN3_F32: emit_V_MIN3_F32; + V_MED3_F32: emit_V_MED3_F32; + V_FMA_F32 : emit_V_FMA_F32; - V_MAD_F32: - begin - _emit_V_MAD_F32; - end; - - V_MAD_I32_I24: - begin - _emit_V_MAD_I32_I24; - end; - - V_MAD_U32_U24: - begin - _emit_V_MAD_U32_U24; - end; - - V_SAD_U32: - begin - _emit_V_SAD_U32; - end; - - V_MAX3_F32: - begin - _emit_V_MAX3_F32; - end; - - V_MIN3_F32: - begin - _emit_V_MIN3_F32; - end; - - V_MED3_F32: - begin - _emit_V_MED3_F32; - end; - - V_FMA_F32: - begin - _emit_V_FMA_F32; - end; - - V_CUBEID_F32:_emit_V_CUBE(OpCUBEID); - V_CUBESC_F32:_emit_V_CUBE(OpCUBESC); - V_CUBETC_F32:_emit_V_CUBE(OpCUBETC); - V_CUBEMA_F32:_emit_V_CUBE(OpCUBEMA); + V_CUBEID_F32:emit_V_CUBE(OpCUBEID); + V_CUBESC_F32:emit_V_CUBE(OpCUBESC); + V_CUBETC_F32:emit_V_CUBE(OpCUBETC); + V_CUBEMA_F32:emit_V_CUBE(OpCUBEMA); //VOP1 analog 384+V_NOP:; - 384+V_MOV_B32: - begin - _emit_V_MOV_B32; - end; + 384+V_MOV_B32 : emit_V_MOV_B32; - 384+V_FRACT_F32: _emit_V_EXT_F32(GlslOp.Fract); - 384+V_TRUNC_F32: _emit_V_EXT_F32(GlslOp.Trunc); - 384+V_CEIL_F32 : _emit_V_EXT_F32(GlslOp.Ceil); + 384+V_FRACT_F32: emit_V2_EXT_F32(GlslOp.Fract); + 384+V_TRUNC_F32: emit_V2_EXT_F32(GlslOp.Trunc); + 384+V_CEIL_F32 : emit_V2_EXT_F32(GlslOp.Ceil); - 384+V_FLOOR_F32: _emit_V_EXT_F32(GlslOp.Floor); - 384+V_EXP_F32 : _emit_V_EXT_F32(GlslOp.Exp2); - 384+V_LOG_F32 : _emit_V_EXT_F32(GlslOp.Log2); + 384+V_FLOOR_F32: emit_V2_EXT_F32(GlslOp.Floor); + 384+V_EXP_F32 : emit_V2_EXT_F32(GlslOp.Exp2); + 384+V_LOG_F32 : emit_V2_EXT_F32(GlslOp.Log2); - 384+V_RSQ_F32 : _emit_V_EXT_F32(GlslOp.InverseSqrt); + 384+V_RSQ_F32 : emit_V2_EXT_F32(GlslOp.InverseSqrt); - 384+V_SQRT_F32 : _emit_V_EXT_F32(GlslOp.Sqrt); + 384+V_SQRT_F32 : emit_V2_EXT_F32(GlslOp.Sqrt); - 384+V_SIN_F32 : _emit_V_EXT_F32(GlslOp.Sin); - 384+V_COS_F32 : _emit_V_EXT_F32(GlslOp.Cos); + 384+V_SIN_F32 : emit_V2_EXT_F32(GlslOp.Sin); + 384+V_COS_F32 : emit_V2_EXT_F32(GlslOp.Cos); - 384+V_RCP_F32: - begin - _emit_V_RCP_F32; - end; + 384+V_RCP_F32 : emit_V_RCP_F32; else Assert(false,'VOP3a?'+IntToStr(FSPI.VOP3a.OP)); diff --git a/spirv/emit_vopc.pas b/spirv/emit_vopc.pas index dc6c8b51..c415441e 100644 --- a/spirv/emit_vopc.pas +++ b/spirv/emit_vopc.pas @@ -7,60 +7,59 @@ interface uses sysutils, ps4_pssl, - srTypes, + srType, srReg, spirv, - SprvEmit, - emit_op; + emit_fetch; type - TEmit_VOPC=object(TEmitOp) - procedure _emit_VOPC; - procedure _emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean); - procedure _emit_V_CMP_C(r,x:Boolean); + TEmit_VOPC=class(TEmitFetch) + procedure emit_VOPC; + procedure emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean); + procedure emit_V_CMP_C(r,x:Boolean); end; implementation -procedure TEmit_VOPC._emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean); +procedure TEmit_VOPC.emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean); Var dst:array[0..1] of PsrRegSlot; src:array[0..1] of PsrRegNode; begin - dst[0]:=@FRegsStory.VCC[0]; - dst[1]:=@FRegsStory.VCC[1]; + dst[0]:=get_vcc0; + dst[1]:=get_vcc1; src[0]:=fetch_ssrc9(FSPI.VOPC.SRC0 ,rtype); src[1]:=fetch_vsrc8(FSPI.VOPC.VSRC1,rtype); - emit_OpCmpV(OpId,dst[0],src[0],src[1]); + OpCmpV(OpId,dst[0],src[0],src[1]); - SetConst(dst[1],dtUnknow,0); //set zero + SetConst_q(dst[1],dtUnknow,0); //set zero if x then begin - MakeCopy(@FRegsStory.EXEC[0],dst[0]^.current); - SetConst(@FRegsStory.EXEC[1],dtUnknow,0); //set zero + MakeCopy(get_exec0,dst[0]^.current); + SetConst_q(get_exec1,dtUnknow,0); //set zero end; end; -procedure TEmit_VOPC._emit_V_CMP_C(r,x:Boolean); +procedure TEmit_VOPC.emit_V_CMP_C(r,x:Boolean); Var dst:array[0..1] of PsrRegSlot; begin - dst[0]:=@FRegsStory.VCC[0]; - dst[1]:=@FRegsStory.VCC[1]; + dst[0]:=get_vcc0; + dst[1]:=get_vcc1; - SetConst(dst[0],dtBool,QWORD(r)); - SetConst(dst[1],dtUnknow,0); //set zero + SetConst_b(dst[0],r); + SetConst_q(dst[1],dtUnknow,0); //set zero if x then begin - MakeCopy(@FRegsStory.EXEC[0],dst[0]^.current); - SetConst(@FRegsStory.EXEC[1],dtUnknow,0); //set zero + MakeCopy(get_exec0,dst[0]^.current); + SetConst_q(get_exec1,dtUnknow,0); //set zero end; end; -procedure TEmit_VOPC._emit_VOPC; +procedure TEmit_VOPC.emit_VOPC; begin Case FSPI.VOPC.OP of @@ -72,7 +71,7 @@ begin V_CMP_F_U32, V_CMP_F_U64, V_CMPS_F_F32, - V_CMPS_F_F64:_emit_V_CMP_C(false,false); + V_CMPS_F_F64:emit_V_CMP_C(false,false); V_CMP_T_F32, V_CMP_T_F64, @@ -81,7 +80,7 @@ begin V_CMP_T_U32, V_CMP_T_U64, V_CMPS_T_F32, - V_CMPS_T_F64:_emit_V_CMP_C(true,false); + V_CMPS_T_F64:emit_V_CMP_C(true,false); V_CMPX_F_F32, V_CMPX_F_F64, @@ -90,7 +89,7 @@ begin V_CMPX_F_U32, V_CMPX_F_U64, V_CMPSX_F_F32, - V_CMPSX_F_F64:_emit_V_CMP_C(false,true); + V_CMPSX_F_F64:emit_V_CMP_C(false,true); V_CMPX_T_F32, V_CMPX_T_F64, @@ -99,101 +98,101 @@ begin V_CMPX_T_U32, V_CMPX_T_U64, V_CMPSX_T_F32, - V_CMPSX_T_F64:_emit_V_CMP_C(true,true); + V_CMPSX_T_F64:emit_V_CMP_C(true,true); // - V_CMP_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,false); - V_CMP_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,false); - V_CMP_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,false); - V_CMP_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,false); - V_CMP_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,false); - V_CMP_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,false); - V_CMP_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,false); - V_CMP_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,false); - V_CMP_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,false); - V_CMP_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,false); - V_CMP_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,false); - V_CMP_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,false); - V_CMP_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,false); - V_CMP_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,false); + V_CMP_LT_F32 :emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,false); + V_CMP_EQ_F32 :emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,false); + V_CMP_LE_F32 :emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,false); + V_CMP_GT_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,false); + V_CMP_LG_F32 :emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,false); + V_CMP_GE_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,false); + V_CMP_O_F32 :emit_V_CMP_32(Op.OpOrdered ,dtFloat32,false); + V_CMP_U_F32 :emit_V_CMP_32(Op.OpUnordered ,dtFloat32,false); + V_CMP_NGE_F32 :emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,false); + V_CMP_NLG_F32 :emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,false); + V_CMP_NGT_F32 :emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,false); + V_CMP_NLE_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,false); + V_CMP_NEQ_F32 :emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,false); + V_CMP_NLT_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,false); - V_CMPX_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,true); - V_CMPX_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,true); - V_CMPX_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,true); - V_CMPX_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,true); - V_CMPX_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,true); - V_CMPX_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,true); - V_CMPX_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,true); - V_CMPX_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,true); - V_CMPX_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,true); - V_CMPX_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,true); - V_CMPX_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,true); - V_CMPX_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,true); - V_CMPX_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,true); - V_CMPX_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,true); + V_CMPX_LT_F32 :emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,true); + V_CMPX_EQ_F32 :emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,true); + V_CMPX_LE_F32 :emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,true); + V_CMPX_GT_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,true); + V_CMPX_LG_F32 :emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,true); + V_CMPX_GE_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,true); + V_CMPX_O_F32 :emit_V_CMP_32(Op.OpOrdered ,dtFloat32,true); + V_CMPX_U_F32 :emit_V_CMP_32(Op.OpUnordered ,dtFloat32,true); + V_CMPX_NGE_F32 :emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,true); + V_CMPX_NLG_F32 :emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,true); + V_CMPX_NGT_F32 :emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,true); + V_CMPX_NLE_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,true); + V_CMPX_NEQ_F32 :emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,true); + V_CMPX_NLT_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,true); // - V_CMPS_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,false); - V_CMPS_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,false); - V_CMPS_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,false); - V_CMPS_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,false); - V_CMPS_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,false); - V_CMPS_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,false); - V_CMPS_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,false); - V_CMPS_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,false); - V_CMPS_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,false); - V_CMPS_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,false); - V_CMPS_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,false); - V_CMPS_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,false); - V_CMPS_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,false); - V_CMPS_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,false); + V_CMPS_LT_F32 :emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,false); + V_CMPS_EQ_F32 :emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,false); + V_CMPS_LE_F32 :emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,false); + V_CMPS_GT_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,false); + V_CMPS_LG_F32 :emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,false); + V_CMPS_GE_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,false); + V_CMPS_O_F32 :emit_V_CMP_32(Op.OpOrdered ,dtFloat32,false); + V_CMPS_U_F32 :emit_V_CMP_32(Op.OpUnordered ,dtFloat32,false); + V_CMPS_NGE_F32 :emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,false); + V_CMPS_NLG_F32 :emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,false); + V_CMPS_NGT_F32 :emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,false); + V_CMPS_NLE_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,false); + V_CMPS_NEQ_F32 :emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,false); + V_CMPS_NLT_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,false); - V_CMPSX_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,true); - V_CMPSX_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,true); - V_CMPSX_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,true); - V_CMPSX_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,true); - V_CMPSX_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,true); - V_CMPSX_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,true); - V_CMPSX_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,true); - V_CMPSX_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,true); - V_CMPSX_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,true); - V_CMPSX_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,true); - V_CMPSX_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,true); - V_CMPSX_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,true); - V_CMPSX_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,true); - V_CMPSX_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,true); + V_CMPSX_LT_F32 :emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,true); + V_CMPSX_EQ_F32 :emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,true); + V_CMPSX_LE_F32 :emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,true); + V_CMPSX_GT_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,true); + V_CMPSX_LG_F32 :emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,true); + V_CMPSX_GE_F32 :emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,true); + V_CMPSX_O_F32 :emit_V_CMP_32(Op.OpOrdered ,dtFloat32,true); + V_CMPSX_U_F32 :emit_V_CMP_32(Op.OpUnordered ,dtFloat32,true); + V_CMPSX_NGE_F32 :emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,true); + V_CMPSX_NLG_F32 :emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,true); + V_CMPSX_NGT_F32 :emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,true); + V_CMPSX_NLE_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,true); + V_CMPSX_NEQ_F32 :emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,true); + V_CMPSX_NLT_F32 :emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,true); // - V_CMP_LT_I32 :_emit_V_CMP_32(Op.OpSLessThan ,dtInt32,false); - V_CMP_EQ_I32 :_emit_V_CMP_32(Op.OpIEqual ,dtInt32,false); - V_CMP_LE_I32 :_emit_V_CMP_32(Op.OpSLessThanEqual ,dtInt32,false); - V_CMP_GT_I32 :_emit_V_CMP_32(Op.OpSGreaterThan ,dtInt32,false); - V_CMP_LG_I32 :_emit_V_CMP_32(Op.OpINotEqual ,dtInt32,false); - V_CMP_GE_I32 :_emit_V_CMP_32(Op.OpSGreaterThanEqual ,dtInt32,false); + V_CMP_LT_I32 :emit_V_CMP_32(Op.OpSLessThan ,dtInt32,false); + V_CMP_EQ_I32 :emit_V_CMP_32(Op.OpIEqual ,dtInt32,false); + V_CMP_LE_I32 :emit_V_CMP_32(Op.OpSLessThanEqual ,dtInt32,false); + V_CMP_GT_I32 :emit_V_CMP_32(Op.OpSGreaterThan ,dtInt32,false); + V_CMP_LG_I32 :emit_V_CMP_32(Op.OpINotEqual ,dtInt32,false); + V_CMP_GE_I32 :emit_V_CMP_32(Op.OpSGreaterThanEqual ,dtInt32,false); - V_CMPX_LT_I32 :_emit_V_CMP_32(Op.OpSLessThan ,dtInt32,true); - V_CMPX_EQ_I32 :_emit_V_CMP_32(Op.OpIEqual ,dtInt32,true); - V_CMPX_LE_I32 :_emit_V_CMP_32(Op.OpSLessThanEqual ,dtInt32,true); - V_CMPX_GT_I32 :_emit_V_CMP_32(Op.OpSGreaterThan ,dtInt32,true); - V_CMPX_LG_I32 :_emit_V_CMP_32(Op.OpINotEqual ,dtInt32,true); - V_CMPX_GE_I32 :_emit_V_CMP_32(Op.OpSGreaterThanEqual ,dtInt32,true); + V_CMPX_LT_I32 :emit_V_CMP_32(Op.OpSLessThan ,dtInt32,true); + V_CMPX_EQ_I32 :emit_V_CMP_32(Op.OpIEqual ,dtInt32,true); + V_CMPX_LE_I32 :emit_V_CMP_32(Op.OpSLessThanEqual ,dtInt32,true); + V_CMPX_GT_I32 :emit_V_CMP_32(Op.OpSGreaterThan ,dtInt32,true); + V_CMPX_LG_I32 :emit_V_CMP_32(Op.OpINotEqual ,dtInt32,true); + V_CMPX_GE_I32 :emit_V_CMP_32(Op.OpSGreaterThanEqual ,dtInt32,true); - V_CMP_LT_U32 :_emit_V_CMP_32(Op.OpULessThan ,dtUint32,false); - V_CMP_EQ_U32 :_emit_V_CMP_32(Op.OpIEqual ,dtUint32,false); - V_CMP_LE_U32 :_emit_V_CMP_32(Op.OpULessThanEqual ,dtUint32,false); - V_CMP_GT_U32 :_emit_V_CMP_32(Op.OpUGreaterThan ,dtUint32,false); - V_CMP_LG_U32 :_emit_V_CMP_32(Op.OpINotEqual ,dtUint32,false); - V_CMP_GE_U32 :_emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,false); + V_CMP_LT_U32 :emit_V_CMP_32(Op.OpULessThan ,dtUint32,false); + V_CMP_EQ_U32 :emit_V_CMP_32(Op.OpIEqual ,dtUint32,false); + V_CMP_LE_U32 :emit_V_CMP_32(Op.OpULessThanEqual ,dtUint32,false); + V_CMP_GT_U32 :emit_V_CMP_32(Op.OpUGreaterThan ,dtUint32,false); + V_CMP_LG_U32 :emit_V_CMP_32(Op.OpINotEqual ,dtUint32,false); + V_CMP_GE_U32 :emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,false); - V_CMPX_LT_U32 :_emit_V_CMP_32(Op.OpULessThan ,dtUint32,true); - V_CMPX_EQ_U32 :_emit_V_CMP_32(Op.OpIEqual ,dtUint32,true); - V_CMPX_LE_U32 :_emit_V_CMP_32(Op.OpULessThanEqual ,dtUint32,true); - V_CMPX_GT_U32 :_emit_V_CMP_32(Op.OpUGreaterThan ,dtUint32,true); - V_CMPX_LG_U32 :_emit_V_CMP_32(Op.OpINotEqual ,dtUint32,true); - V_CMPX_GE_U32 :_emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,true); + V_CMPX_LT_U32 :emit_V_CMP_32(Op.OpULessThan ,dtUint32,true); + V_CMPX_EQ_U32 :emit_V_CMP_32(Op.OpIEqual ,dtUint32,true); + V_CMPX_LE_U32 :emit_V_CMP_32(Op.OpULessThanEqual ,dtUint32,true); + V_CMPX_GT_U32 :emit_V_CMP_32(Op.OpUGreaterThan ,dtUint32,true); + V_CMPX_LG_U32 :emit_V_CMP_32(Op.OpINotEqual ,dtUint32,true); + V_CMPX_GE_U32 :emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,true); else Assert(false,'VOPC?'); diff --git a/spirv/srNodes.pas b/spirv/ginodes.pas similarity index 78% rename from spirv/srNodes.pas rename to spirv/ginodes.pas index ee37f359..b907cafe 100644 --- a/spirv/srNodes.pas +++ b/spirv/ginodes.pas @@ -1,4 +1,4 @@ -unit srNodes; +unit ginodes; {$mode objfpc}{$H+} @@ -45,45 +45,7 @@ type procedure Insert(new:PNode); end; - TsrNodeType=( - ntUnknow, - ntLiteral, - ntString, - ntConst, - ntType, - ntLabel, - ntBlock, - ntFunc, - ntVar, - ntRefId, - ntOp, - ntReg, - ntVolatile, - ntInput, - ntVertLayout, - ntFragLayout, - ntOutput, - ntChain, - ntUniform, - ntBuffer - ); - - TOpParamSingle=packed object - ntype:TsrNodeType; - pData:Pointer; - procedure SetParam(_ntype:TsrNodeType;_Data:Pointer); - function AsConst:Pointer; - function AsOp:Pointer; - function AsReg:Pointer; - function AsVar:Pointer; - function AsBlock:Pointer; - function AsInput:Pointer; - function AsRefId:Pointer; - function AsUniform:Pointer; - end; - - TfnAlloc=Function(Size:ptruint):Pointer of object; - +function ComparePChar(buf1,buf2:PChar):Integer; function ComparePtruint(buf1,buf2:PPtruint;count:PtrUint):Integer; implementation @@ -169,10 +131,7 @@ function TNodeFetch.Next(node:PNode):PNode; begin Result:=nil; if (pRoot=nil) or (node=nil) then Exit; - if (node^.pRight=nil) then - begin - _Splay(node); - end; + _Splay(node); node:=node^.pRight; While (node<>nil) do begin @@ -185,10 +144,7 @@ function TNodeFetch.Prev(node:PNode):PNode; begin Result:=nil; if (pRoot=nil) or (node=nil) then Exit; - if (node^.pLeft=nil) then - begin - _Splay(node); - end; + _Splay(node); node:=node^.pLeft; While (node<>nil) do begin @@ -483,74 +439,32 @@ begin end; end; -procedure TOpParamSingle.SetParam(_ntype:TsrNodeType;_Data:Pointer); -begin - ntype:=_ntype; - pData:=_Data; -end; +// -function TOpParamSingle.AsConst:Pointer; +function ComparePChar(buf1,buf2:PChar):Integer; begin - Result:=nil; - if (@Self=nil) then Exit; - if (ntype<>ntConst) then Exit; - Result:=pData; -end; - -function TOpParamSingle.AsOp:Pointer; -begin - Result:=nil; - if (@Self=nil) then Exit; - if (ntype<>ntOp) then Exit; - Result:=pData; -end; - -function TOpParamSingle.AsReg:Pointer; -begin - Result:=nil; - if (@Self=nil) then Exit; - if (ntype<>ntReg) then Exit; - Result:=pData; -end; - -function TOpParamSingle.AsVar:Pointer; -begin - Result:=nil; - if (@Self=nil) then Exit; - if (ntype<>ntVar) then Exit; - Result:=pData; -end; - -function TOpParamSingle.AsBlock:Pointer; -begin - Result:=nil; - if (@Self=nil) then Exit; - if (ntype<>ntBlock) then Exit; - Result:=pData; -end; - -function TOpParamSingle.AsInput:Pointer; -begin - Result:=nil; - if (@Self=nil) then Exit; - if (ntype<>ntInput) then Exit; - Result:=pData; -end; - -function TOpParamSingle.AsRefId:Pointer; -begin - Result:=nil; - if (@Self=nil) then Exit; - if (ntype<>ntRefId) then Exit; - Result:=pData; -end; - -function TOpParamSingle.AsUniform:Pointer; -begin - Result:=nil; - if (@Self=nil) then Exit; - if (ntype<>ntUniform) then Exit; - Result:=pData; + Result:=0; + if (buf1=nil) and (buf2=nil) then + begin + Exit; + end else + if (buf1=nil) then + begin + Result:=-Integer(buf2^); + end else + if (buf2=nil) then + begin + Result:=Integer(buf1^); + end else + begin + While true do + begin + Result:=Integer(buf1^)-Integer(buf2^); + if (Result<>0) or (buf1^=#0) or (buf2^=#0) then Exit; + Inc(buf1); + Inc(buf2); + end; + end; end; function ComparePtruint(buf1,buf2:PPtruint;count:PtrUint):Integer; diff --git a/spirv/pssl-spirv.lpi b/spirv/pssl-spirv.lpi index 62cd8ffd..cc55b4d4 100644 --- a/spirv/pssl-spirv.lpi +++ b/spirv/pssl-spirv.lpi @@ -25,7 +25,7 @@ - + @@ -239,6 +239,10 @@ + + + + @@ -263,7 +267,7 @@ - + diff --git a/spirv/pssl-spirv.lpr b/spirv/pssl-spirv.lpr index c1ab71d7..e137777b 100644 --- a/spirv/pssl-spirv.lpr +++ b/spirv/pssl-spirv.lpr @@ -7,8 +7,8 @@ Uses si_ci_vi_merged_registers, ps4_pssl, ps4_shader, - //spirv, - srBuffer, + + srConfig, SprvEmit, emit_post, @@ -21,13 +21,9 @@ var FName:RawByteString; FSave:RawByteString; FPrintInfo:Boolean; - FPrintAsm:Boolean; FPrintSpv:Boolean; - FUseVertexInput:Boolean; - FUseTexelBuffer:Boolean; - FUseOutput16:Boolean; - - BufferCfg:TsrBufferCfg; + // + cfg:TsrConfig; end; type @@ -35,67 +31,12 @@ type REG,COUNT:WORD; end; -{ -procedure load_spv(const fname:RawByteString); -var - M:TMemoryStream; - Header:TSPIRVHeader; - - DW:TSPIRVInstruction; - -label - _exit; -begin - M:=TMemoryStream.Create; - M.LoadFromFile(fname); - M.Position:=0; - - Header:=Default(TSPIRVHeader); - M.Read(Header,SizeOf(TSPIRVHeader)); - if (Header.MAGIC<>spirv.MagicNumber) then Goto _exit; - Writeln(HexStr(Header.TOOL_ID,8)); - - DW:=Default(TSPIRVInstruction); - repeat - if M.Read(DW,SizeOf(TSPIRVInstruction))<>SizeOf(TSPIRVInstruction) then Break; - Writeln(spirv.Op.GetStr(DW.OP)); - if (DW.COUNT>1) then - begin - M.Seek(SizeOf(DWORD)*(DW.COUNT-1),soCurrent); - end; - until false; - - _exit: - M.Free; -end; -} - -procedure post_SprvEmit(var SprvEmit:TSprvEmit); -begin - TSprvEmit_post(SprvEmit).Post; -end; - -procedure alloc_SprvEmit(var SprvEmit:TSprvEmit); -begin - TSprvEmit_alloc(SprvEmit).Alloc; -end; - -procedure print_SprvEmit(var SprvEmit:TSprvEmit); -begin - TSprvEmit_print(SprvEmit).Print; -end; - -procedure SaveToStream_SprvEmit(Stream:TStream;var SprvEmit:TSprvEmit); -begin - TSprvEmit_bin(SprvEmit).SaveToStream(Stream); -end; - -procedure SaveToFile_SprvEmit(const FName:RawByteString;var SprvEmit:TSprvEmit); +procedure SaveToFile_Spv(const FName:RawByteString;var SprvEmit:TSprvEmit); var F:TFileStream; begin F:=TFileStream.Create(FName,fmCreate); - SaveToStream_SprvEmit(F,SprvEmit); + SprvEmit.SaveToStream(F); F.Free; end; @@ -325,9 +266,6 @@ var SprvEmit:TSprvEmit; - //LParser:TsrLParser; - //FCode:TsrCodeBlock; - i:Byte; begin @@ -410,6 +348,8 @@ begin Assert(info<>nil); + SprvEmit:=TSprvEmit.Create; + case info^.m_type of kShaderTypePs : begin @@ -444,39 +384,34 @@ begin end; end; - SprvEmit.FPrintAsm :=cfg.FPrintAsm; - SprvEmit.FUseVertexInput:=cfg.FUseVertexInput; - SprvEmit.FUseTexelBuffer:=cfg.FUseTexelBuffer; - SprvEmit.FUseOutput16 :=cfg.FUseOutput16; + SprvEmit.Config:=cfg.cfg; - SprvEmit.FBuffers.cfg:=cfg.BufferCfg; - - if (SprvEmit.Parse(base)>1) then + if (SprvEmit.ParseStage(base)>1) then begin Writeln(StdErr,'Shader Parse Err'); end; - if cfg.FPrintAsm or cfg.FPrintSpv or (cfg.FSave<>'') then + if cfg.cfg.PrintAsm or cfg.FPrintSpv or (cfg.FSave<>'') then begin - post_SprvEmit(SprvEmit); - alloc_SprvEmit(SprvEmit); + SprvEmit.PostStage; + SprvEmit.AllocStage; end; if cfg.FPrintSpv then begin - print_SprvEmit(SprvEmit); + SprvEmit.Print; Writeln; end; if (cfg.FSave<>'') then begin - SaveToFile_SprvEmit(cfg.FSave,SprvEmit); + SaveToFile_Spv(cfg.FSave,SprvEmit); end; if cfg.FPrintInfo then - Writeln('used_size=',SprvEmit.FAllocator.used_size); + Writeln('used_size=',SprvEmit.Allocator.used_size); - SprvEmit.FAllocator.Free; + SprvEmit.Free; end; function ParseCmd:Boolean; @@ -492,25 +427,28 @@ begin Exit(False); end; - cfg.FUseVertexInput:=True; - cfg.BufferCfg.Init; + cfg.FName:=''; + cfg.FSave:=''; + cfg.FPrintInfo:=False; + cfg.FPrintSpv :=False; + cfg.cfg.Init; n:=-1; For i:=1 to ParamCount do begin case LowerCase(ParamStr(i)) of '-i':cfg.FPrintInfo:=True; - '-a':cfg.FPrintAsm:=True; + '-a':cfg.cfg.PrintAsm:=True; '-p':cfg.FPrintSpv:=True; - '-eva':cfg.FUseVertexInput:=True; - '-dva':cfg.FUseVertexInput:=False; + '-eva':cfg.cfg.UseVertexInput:=True; + '-dva':cfg.cfg.UseVertexInput:=False; - '-etb':cfg.FUseTexelBuffer:=True; - '-dtb':cfg.FUseTexelBuffer:=False; + '-etb':cfg.cfg.UseTexelBuffer:=True; + '-dtb':cfg.cfg.UseTexelBuffer:=False; - '-eoh':cfg.FUseOutput16:=True; - '-doh':cfg.FUseOutput16:=False; + '-eoh':cfg.cfg.UseOutput16:=True; + '-doh':cfg.cfg.UseOutput16:=False; '-b':n:=0; @@ -525,11 +463,11 @@ begin Case n of -1:cfg.FName:=ParamStr(i); 0:cfg.FSave:=ParamStr(i); - 1:cfg.BufferCfg.maxUniformBufferRange :=StrToInt64Def(ParamStr(i),0); - 2:cfg.BufferCfg.PushConstantsOffset :=StrToInt64Def(ParamStr(i),0); - 3:cfg.BufferCfg.maxPushConstantsSize :=StrToInt64Def(ParamStr(i),0); - 4:cfg.BufferCfg.minStorageBufferOffsetAlignment:=StrToInt64Def(ParamStr(i),0); - 5:cfg.BufferCfg.minUniformBufferOffsetAlignment:=StrToInt64Def(ParamStr(i),0); + 1:cfg.cfg.maxUniformBufferRange :=StrToInt64Def(ParamStr(i),0); + 2:cfg.cfg.PushConstantsOffset :=StrToInt64Def(ParamStr(i),0); + 3:cfg.cfg.maxPushConstantsSize :=StrToInt64Def(ParamStr(i),0); + 4:cfg.cfg.minStorageBufferOffsetAlignment:=StrToInt64Def(ParamStr(i),0); + 5:cfg.cfg.minUniformBufferOffsetAlignment:=StrToInt64Def(ParamStr(i),0); end; n:=-1; end; @@ -552,81 +490,47 @@ begin if (cfg.FName='') then begin - //loadspv('vert.spv'); - - //branch adr - //load_dump('shader_dump\MomodoraRUtM\MomodoraRUtM_ps_595F5E5D.dump'); - //load_dump('shader_dump\MomodoraRUtM\MomodoraRUtM_vs_B9E80F51.dump'); - - //load_dump('shader_dump\MomodoraRUtM\MomodoraRUtM_vs_72685B15.dump'); - - //branch - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_cs_3685EFC7.dump'); - - //branch - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_8D309F69.dump'); - - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_30AC6582.dump'); - - //V_MED3_F32 - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_46F7D0CB.dump'); - - //branch - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_897BFEFF.dump'); - - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_A9A43387.dump'); - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_BD5B57D5.dump'); - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_C342C7CD.dump'); - - //V_MED3_F32 - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_E125C5F7.dump'); - - //branch cycle - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_E820FFDE.dump'); - - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_vs_1CE5C47E.dump'); - - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_vs_22E9CA76.dump'); - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_vs_48FA7A4C.dump'); - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_vs_243D8C75.dump'); - - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_vs_B4E470AF.dump'); - //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_vs_E1C90BE3.dump'); - - //branch - ////load_dump('shader_dump\WeAreDoomed\WeAreDoomed_ps4_cs_FEA061C5.dump'); + //load_dump('shader_dump\simplet-single-triangle_debug\simplet-single-triangle_debug_vs_78EF9008.dump'); + //load_dump('shader_dump\simplet-single-triangle_debug\simplet-single-triangle_debug_ps_FBCA196D.dump'); //load_dump('shader_dump\simplet-simple-fs_debug\simplet-simple-fs_debug_vs_398C5BF6.dump'); //load_dump('shader_dump\simplet-simple-fs_debug\simplet-simple-fs_debug_ps_F327ABD1.dump'); - //load_dump('shader_dump\simplet-single-triangle_debug\simplet-single-triangle_debug_vs_78EF9008.dump'); - load_dump('shader_dump\simplet-single-triangle_debug\simplet-single-triangle_debug_ps_FBCA196D.dump'); + //load_dump('shader_dump\WeAreDoomed\WeAreDoomed_ps4_cs_FEA061C5.dump'); + //load_dump('shader_dump\WeAreDoomed\WeAreDoomed_ps4_ps_B9680888.dump'); + //load_dump('shader_dump\WeAreDoomed\WeAreDoomed_ps4_ps_BA60EAD7.dump'); + //load_dump('shader_dump\WeAreDoomed\WeAreDoomed_ps4_vs_0C420DE0.dump'); - //load_dump('shader_dump\basic_quad_debug\basic_quad_debug_ps_C342C7CD.dump'); - //load_dump('shader_dump\basic_quad_debug\basic_quad_debug_vs_D216FEB8.dump'); - - //load_dump('shader_dump\basic_quad_debug\basic_quad_debug_cs_3685EFC7.dump'); + load_dump('shader_dump\basic-sample\basic-sample_debug_ps_E125C5F7.dump'); //load_dump('shader_dump\basic_quad_debug\basic_quad_debug_ps_A9F64695.dump'); - //load_dump('shader_dump\basic_quad_debug\basic_quad_debug_vs_B4E470AF.dump'); - - //load_dump('shader_dump\basic_quad_debug\basic_quad_debug_vs_1CE5C47E.dump'); - - //load_dump('shader_dump\basic-compute_debug\basic-compute_debug_ps_4BD7E17E.dump'); - //load_dump('shader_dump\basic-compute_debug\basic-compute_debug_vs_0C30DA0F.dump'); - - //load_dump('shader_dump\SonicMania\SonicMania_ps_0C48E8B2.dump'); - - - //load_dump('shader_dump\SonicMania\SonicMania_ps_B4281DBF.dump'); + //load_dump('shader_dump\basic_quad_debug\basic_quad_debug_cs_3685EFC7.dump'); //load_dump('shader_dump\SonicMania\SonicMania_ps_11DF2A32.dump'); + //load_dump('shader_dump\SonicMania\SonicMania_ps_3CC22A00.dump'); - //load_dump('shader_dump\SonicMania\SonicMania_ps_3CC22A00.dump'); //cfg + //load_dump('shader_dump\MomodoraRUtM\MomodoraRUtM_ps_595F5E5D.dump'); + load_dump('shader_dump\MomodoraRUtM\MomodoraRUtM_ps_B42E92C3.dump'); + //load_dump('shader_dump\MomodoraRUtM\MomodoraRUtM_vs_B9E80F51.dump'); + + //load_dump('shader_dump\basic-sample\basic-sample_debug_cs_4303E70D.dump'); + //load_dump('shader_dump\basic-sample\basic-sample_debug_cs_C4EA2D91.dump'); + + //load_dump('shader_dump\Cladun_Returns\ClassicDungeon3ORBIS_ps_B2ED8D0C.dump'); + //load_dump('shader_dump\Cladun_Returns\ClassicDungeon3ORBIS_ps_B39D802A.dump'); + + //load_dump('shader_dump\depth-mode-sample\depth-mode-sample_debug_ps_E125C5F7.dump'); + + //load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_E820FFDE.dump'); + + //load_dump('shader_dump\JETPACKJOYRIDE\mgjp_cs_2D246406.dump'); end; + if (cfg.FName<>'') then + begin load_dump(cfg.FName); + end; load_pssl(GPU_REGS.CS.Addr); @@ -634,7 +538,9 @@ begin load_pssl(GPU_REGS.PS.Addr); if cfg.FPrintInfo then + begin readln; + end; end. { diff --git a/spirv/srAllocator.pas b/spirv/srAllocator.pas index 0c685498..2a900f97 100644 --- a/spirv/srAllocator.pas +++ b/spirv/srAllocator.pas @@ -5,7 +5,7 @@ unit srAllocator; interface uses - srNodes; + ginodes; type PsrAllocNode=^TsrAllocNode; diff --git a/spirv/srBitcast.pas b/spirv/srBitcast.pas index 55601f3e..54511a16 100644 --- a/spirv/srBitcast.pas +++ b/spirv/srBitcast.pas @@ -5,11 +5,11 @@ unit srBitcast; interface uses - sysutils, - srNodes, - srTypes, - srConst, - srReg; + ginodes, + srNode, + srType, + srConst, + srReg; type PsrBitcast=^TsrBitcast; @@ -24,27 +24,34 @@ type function c(n1,n2:PsrBitcast):Integer; static; end; + PsrBitcastList=^TsrBitcastList; TsrBitcastList=object type TNodeFetch=specialize TNodeFetch; var - pRoot:Pointer; FNTree:TNodeFetch; - function Find(dtype:TsrDataType;src:PsrRegNode):PsrBitcast; - function FetchRead(dtype:TsrDataType;src:PsrRegNode):PsrRegNode; - function FetchDst(dtype:TsrDataType;src:PsrRegNode):PsrRegNode; - function FetchCast(dtype:TsrDataType;src:PsrRegNode):PsrRegNode; + rSlot:TsrRegSlot; + procedure Init(Emit:TCustomEmit); inline; + function Find(dtype:TsrDataType;src:PsrRegNode):PsrBitcast; + function FetchRead(dtype:TsrDataType;src:PsrRegNode):PsrRegNode; + function FetchDstr(dtype:TsrDataType;src:PsrRegNode):PsrRegNode; + function FetchCast(dtype:TsrDataType;src:PsrRegNode):PsrRegNode; end; implementation -uses - SprvEmit, - emit_op; - function TsrBitcast.c(n1,n2:PsrBitcast):Integer; begin - Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrBitcast.key)); + //first dtype + Result:=Integer(n1^.key.dtype>n2^.key.dtype)-Integer(n1^.key.dtype0) then Exit; + //second src + Result:=Integer(n1^.key.src>n2^.key.src)-Integer(n1^.key.srcnil) then begin - dst:=node^.dst; - dst^.mark_read; - Result:=dst; + Result:=node^.dst; Exit; end; if src^.is_const then begin pConst:=src^.AsConst; - pConst^.mark_unread; - dst:=PSprvEmit(pRoot)^.NewReg(dtype); - dst^.pLine:=src^.pLine; - dst^.SetConst(PSprvEmit(pRoot)^.FConsts.Bitcast(dtype,pConst)) + + pConstList:=rSlot.FEmit.GetConstList; + pConst:=pConstList^.Bitcast(dtype,pConst); + + dst:=rSlot.New(src^.pLine,dtype); + dst^.pWriter:=pConst; end else begin if TryBitcastType(src^.dtype,dtype) then begin - src^.mark_read; - dst:=PSprvEmit(pRoot)^.NewReg(dtype); - dst^.pLine:=src^.pLine; - PEmitOp(pRoot)^.emit_OpCastExt(src^.pLine,dst,src); + dst:=rSlot.New(src^.pLine,dtype); + + rSlot.FEmit.OpCast(src^.pLine,dst,src) end else begin Assert(false,'bitcast'); end; end; - node:=PSprvEmit(pRoot)^.Alloc(SizeOf(TsrBitcast)); + node:=rSlot.FEmit.Alloc(SizeOf(TsrBitcast)); node^:=Default(TsrBitcast); node^.key.dtype:=dtype; node^.key.src:=src; node^.dst:=dst; FNTree.Insert(node); - dst^.mark_read; Result:=dst; end; diff --git a/spirv/srBuffer.pas b/spirv/srBuffer.pas index 6f0bd0d4..3c9e4272 100644 --- a/spirv/srBuffer.pas +++ b/spirv/srBuffer.pas @@ -5,14 +5,23 @@ unit srBuffer; interface uses - spirv, - srNodes, - srTypes, - srVariable, - srLayout, - srDecorate; + sysutils, + spirv, + ginodes, + srNode, + srType, + srTypes, + srVariable, + srLayout, + srDecorate, + srConfig; type + ntBuffer=class(ntDescriptor) + class Function pwrite_count (node:PsrNode):PDWORD; override; + class function GetStorageName(node:PsrNode):RawByteString; override; + end; + PsrBuffer=^TsrBuffer; PsrField=^TsrField; @@ -33,7 +42,7 @@ type //---- pBuffer:PsrBuffer; - parent:PsrField; + pParent:PsrField; offset:PtrUint; size:PtrUint; stride:PtrUint; @@ -45,7 +54,6 @@ type // - Alloc:TfnAlloc; FList:TFieldFetch; function c(n1,n2:PsrField):Integer; static; @@ -60,80 +68,90 @@ type function FetchValue(_offset,_size:PtrUint;_dtype:TsrDataType):TFieldFetchValue; function FetchRuntimeArray(_offset,_stride:PtrUint):TFieldFetchValue; function IsStructUsedRuntimeArray:Boolean; - function IsStructNotUsed:Boolean; + function IsStructNotUsed:Boolean; inline; + function IsTop:Boolean; inline; function GetStructDecorate:DWORD; + procedure UpdateSize; + function GetSize:PtrUint; procedure FillNode(o,s:PtrUint); function FillSpace:Integer; - procedure AllocID; - procedure AllocBinding(aType:PsrType;Decorates:PsrDecorateList); end; TsrBufferType=(btStorageBuffer,btUniformBuffer,btPushConstant); - TsrBuffer=object(TsrDescriptor) + TsrBuffer=packed object(TsrDescriptor) pLeft,pRight:PsrBuffer; //---- + fwrite_count:DWORD; + fchain_read :DWORD; + fchain_write:DWORD; + // + align_offset:DWORD; - key:packed record - pLayout:PsrDataLayout; - CastNum:PtrInt; - end; + FEmit:TCustomEmit; bType:TsrBufferType; - write_count:DWORD; - align_offset:DWORD; + key:packed record + pLayout:PsrDataLayout; + AliasId:PtrInt; + end; FTop:TsrField; + function c(n1,n2:PsrBuffer):Integer; static; + Procedure Init(Emit:TCustomEmit); inline; + function GetStorageName:RawByteString; function GetTypeChar:Char; function GetString:RawByteString; function GetStructName:RawByteString; - procedure UpdateSize; function GetSize:PtrUint; + procedure TakeChain(node:PsrChain); procedure EnumAllField(cb:TFieldEnumCb); procedure ShiftOffset(Offset:PtrUint); end; - TsrBufferCfg=object - SpvVersion:PtrUint; - maxUniformBufferRange:PtrUint; // $FFFF - PushConstantsOffset:PtrUint; // 0 - maxPushConstantsSize:PtrUint; // 128 - minStorageBufferOffsetAlignment:PtrUint; // $10 - minUniformBufferOffsetAlignment:PtrUint; // $100 - Procedure Init; - Function CanUseStorageBufferClass:Boolean; - end; - + PsrBufferList=^TsrBufferList; TsrBufferList=object type TNodeFetch=specialize TNodeFetch; var - Alloc:TfnAlloc; - cfg:TsrBufferCfg; + FEmit:TCustomEmit; FNTree:TNodeFetch; FPushConstant:PsrBuffer; - procedure Init(cb:TfnAlloc); + procedure Init(Emit:TCustomEmit); inline; function Fetch(s:PsrDataLayout;n:PtrInt):PsrBuffer; - function NextCast(buf:PsrBuffer):PsrBuffer; + function NextAlias(buf:PsrBuffer):PsrBuffer; Function First:PsrBuffer; Function Next(node:PsrBuffer):PsrBuffer; procedure EnumAllField(cb:TFieldEnumCb); procedure OnFillSpace(node:PsrField); procedure FillSpace; - procedure OnAllocID(node:PsrField); + procedure OnAllocID(pField:PsrField); procedure AllocID; - procedure AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList); - procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList); - procedure UpdateStorage(node:PsrChain;pBuffer:PsrBuffer); + procedure AllocBinding(Var FBinding:Integer); + procedure AllocSourceExtension; + function FindUserDataBuf:PsrBuffer; procedure ApplyBufferType; procedure AlignOffset(node:PsrBuffer;offset:PtrUint); procedure AlignOffset; + procedure OnAllocTypeBinding(pField:PsrField); + procedure AllocTypeBinding; + procedure AllocName; end; implementation +class Function ntBuffer.pwrite_count(node:PsrNode):PDWORD; +begin + Result:=@PsrBuffer(node)^.fwrite_count; +end; + +class function ntBuffer.GetStorageName(node:PsrNode):RawByteString; +begin + Result:=PsrBuffer(node)^.GetStorageName; +end; + //--- function TsrField.c(n1,n2:PsrField):Integer; @@ -194,12 +212,12 @@ begin Result:=FList.Find(@node); if (Result=nil) then begin - Result:=Alloc(SizeOf(TsrField)); - Result^.Alloc:=Alloc; + Assert(pBuffer^.FEmit<>nil); + Result:=pBuffer^.FEmit.Alloc(SizeOf(TsrField)); Result^.pBuffer:=pBuffer; - Result^.parent:=@Self; - Result^.offset:=o; - Result^.FID:=-1; + Result^.pParent:=@Self; + Result^.offset :=o; + Result^.FID :=-1; FList.Insert(Result); Inc(FCount); end; @@ -213,9 +231,9 @@ begin Result:=Default(TFieldFetchValue); _stride:=0; - if isVector(_dtype) then + if _dtype.isVector then begin - _stride:=BitSizeType(GetVecChild(_dtype)) div 8; + _stride:=_dtype.Child.BitSize div 8; end; node:=Find_le(_offset); @@ -262,9 +280,9 @@ begin end; else begin - if isVector(node^.dtype) then + if node^.dtype.isVector then begin //ftVector - if isVector(_dtype) then + if _dtype.isVector then begin if (node^.offset=_offset) and (node^.size =_size) and @@ -287,7 +305,7 @@ begin end; end else begin //ftValue - if isVector(_dtype) then + if _dtype.isVector then begin if (node^.offset=_offset) and (node^.size =_size) then @@ -350,15 +368,20 @@ begin end; end; -function TsrField.IsStructNotUsed:Boolean; +function TsrField.IsStructNotUsed:Boolean; inline; begin - Result:=(FCount<=1) and (parent<>nil); + Result:=(FCount<=1) and (pParent<>nil); +end; + +function TsrField.IsTop:Boolean; inline; +begin + Result:=(pParent=nil); end; function TsrField.GetStructDecorate:DWORD; begin Result:=DWORD(-1); //dont use - if (parent=nil) then //is top + if IsTop then if (dtype=dtTypeStruct) then //is struct begin @@ -374,6 +397,23 @@ begin end; end; +procedure TsrField.UpdateSize; +var + node:PsrField; +begin + node:=FList.Max; + if (node<>nil) then + begin + size:=node^.offset+node^.size; + end; +end; + +function TsrField.GetSize:PtrUint; +begin + UpdateSize; + Result:=size; +end; + procedure TsrField.FillNode(o,s:PtrUint); procedure _Pad(p,v:PtrUint;_dtype:TsrDataType); //inline; @@ -477,43 +517,6 @@ begin end; end; -procedure TsrField.AllocID; -var - node:PsrField; - ID:Integer; -begin - ID:=0; - node:=First; - While (node<>nil) do - begin - if IsVector(dtype) then - begin - ID:=node^.offset div stride; - node^.FID:=ID; - end else - begin - node^.FID:=ID; - Inc(ID); - end; - node:=Next(node); - end; -end; - -procedure TsrField.AllocBinding(aType:PsrType;Decorates:PsrDecorateList); -var - node:PsrField; -begin - if (aType=nil) then Exit; - if (Decorates=nil) then Exit; - if isVector(dtype) then Exit; - node:=First; - While (node<>nil) do - begin - Decorates^.emit_member_decorate(ntType,aType,node^.FID,node^.offset); - node:=Next(node); - end; -end; - //-- function TsrBuffer.c(n1,n2:PsrBuffer):Integer; @@ -522,7 +525,30 @@ begin Result:=Integer(n1^.key.pLayout>n2^.key.pLayout)-Integer(n1^.key.pLayout0) then Exit; //second CastNum - Result:=Integer(n1^.key.CastNum>n2^.key.CastNum)-Integer(n1^.key.CastNumn2^.key.AliasId)-Integer(n1^.key.AliasIdnil) then - begin - FTop.size:=node^.offset+node^.size; - end; -end; - function TsrBuffer.GetSize:PtrUint; begin - UpdateSize; - Result:=FTop.size; + Result:=FTop.GetSize; +end; + +procedure TsrBuffer.TakeChain(node:PsrChain); +begin + if (@Self=nil) or (node=nil) then Exit; + + mark_read(node); + + fchain_read :=fchain_read +node^.read_count; + fchain_write:=fchain_write+node^.write_count; end; procedure TsrBuffer.EnumAllField(cb:TFieldEnumCb); @@ -583,9 +607,8 @@ begin repeat While (node<>nil) do begin - if (node^.FList.pRoot<>nil) then //child exist + if (node^.First<>nil) then //child exist begin - curr^.FList._Splay(node); //Move to root curr:=node; node:=curr^.First; //down end else @@ -595,9 +618,9 @@ begin end; end; cb(curr); - curr:=curr^.parent; //up + node:=curr; + curr:=curr^.pParent; //up if (curr=nil) then Break; - node:=curr^.FList.pRoot; //last find node:=curr^.Next(node); until false; end; @@ -619,24 +642,9 @@ begin end; end; -Procedure TsrBufferCfg.Init; +procedure TsrBufferList.Init(Emit:TCustomEmit); inline; begin - SpvVersion:=$10100; - maxUniformBufferRange:=$FFFF; - maxPushConstantsSize:=128; - minStorageBufferOffsetAlignment:=0; - minUniformBufferOffsetAlignment:=0; -end; - -Function TsrBufferCfg.CanUseStorageBufferClass:Boolean; -begin - Result:=(SpvVersion>=$10300); -end; - -procedure TsrBufferList.Init(cb:TfnAlloc); -begin - Alloc:=cb; - cfg.Init; + FEmit:=Emit; end; function TsrBufferList.Fetch(s:PsrDataLayout;n:PtrInt):PsrBuffer; @@ -644,30 +652,27 @@ var node:TsrBuffer; begin node:=Default(TsrBuffer); + node.Init(FEmit); node.key.pLayout:=s; - node.key.CastNum:=n; + node.key.AliasId:=n; Result:=FNTree.Find(@node); if (Result=nil) then begin - Result:=Alloc(SizeOf(TsrBuffer)); - Result^.key.pLayout:=s; - Result^.key.CastNum:=n; - Result^.bType :=btStorageBuffer; - Result^.FStorage:=StorageClass.Uniform; - Result^.FBinding:=-1; - Result^.FTop.Alloc:=Alloc; + Result:=FEmit.Alloc(SizeOf(TsrBuffer)); + Move(node,Result^,SizeOf(TsrBuffer)); Result^.FTop.pBuffer:=Result; - Result^.FTop.FID:=-1; - Result^.FTop.dtype:=dtTypeStruct; + // + Result^.InitVar(FEmit); + // FNTree.Insert(Result); end; end; -function TsrBufferList.NextCast(buf:PsrBuffer):PsrBuffer; +function TsrBufferList.NextAlias(buf:PsrBuffer):PsrBuffer; begin Result:=nil; if (buf=nil) then Exit; - Result:=Fetch(buf^.key.pLayout,buf^.key.CastNum+1); + Result:=Fetch(buf^.key.pLayout,buf^.key.AliasId+1); end; Function TsrBufferList.First:PsrBuffer; @@ -688,7 +693,10 @@ begin node:=First; While (node<>nil) do begin - node^.EnumAllField(cb); + if node^.IsUsed then + begin + node^.EnumAllField(cb); + end; node:=Next(node); end; end; @@ -703,9 +711,26 @@ begin EnumAllField(@OnFillSpace); end; -procedure TsrBufferList.OnAllocID(node:PsrField); +procedure TsrBufferList.OnAllocID(pField:PsrField); +var + node:PsrField; + ID:Integer; begin - node^.AllocID; + ID:=0; + node:=pField^.First; + While (node<>nil) do + begin + if pField^.dtype.IsVector then + begin + ID:=node^.offset div pField^.stride; + node^.FID:=ID; + end else + begin + node^.FID:=ID; + Inc(ID); + end; + node:=pField^.Next(node); + end; end; procedure TsrBufferList.AllocID; @@ -713,80 +738,108 @@ begin EnumAllField(@OnAllocID); end; -procedure TsrBufferList.AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList); +procedure TsrBufferList.AllocBinding(Var FBinding:Integer); var + pConfig:PsrConfig; + pDecorateList:PsrDecorateList; node:PsrBuffer; pVar:PsrVariable; begin - if (Decorates=nil) then Exit; + pConfig:=FEmit.GetConfig; + pDecorateList:=FEmit.GetDecorateList; node:=First; While (node<>nil) do begin pVar:=node^.pVar; - if (pVar<>nil) then + if (pVar<>nil) and node^.IsUsed then + if (node^.bType<>btPushConstant) then + if (node^.FBinding=-1) then //alloc begin - if (node^.bType<>btPushConstant) then - if (node^.FBinding=-1) then //alloc + pDecorateList^.OpDecorate(pVar,Decoration.Binding,FBinding); + pDecorateList^.OpDecorate(pVar,Decoration.DescriptorSet,pConfig^.DescriptorSet); + node^.FBinding:=FBinding; + Inc(FBinding); + end; + node:=Next(node); + end; +end; + +procedure TsrBufferList.AllocSourceExtension; +var + pDebugInfoList:PsrDebugInfoList; + node:PsrBuffer; + pVar:PsrVariable; +begin + pDebugInfoList:=FEmit.GetDebugInfoList; + node:=First; + While (node<>nil) do + begin + pVar:=node^.pVar; + if (pVar<>nil) and node^.IsUsed then + begin + pDebugInfoList^.OpSourceExtension(node^.GetString); + end; + node:=Next(node); + end; +end; + +function TsrBufferList.FindUserDataBuf:PsrBuffer; +var + node:PsrBuffer; +begin + Result:=nil; + node:=First; + While (node<>nil) do + begin + if node^.IsUsed then + begin + if node^.key.pLayout^.IsUserData then begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.Binding,FBinding); - Decorates^.emit_decorate(ntVar,pVar,Decoration.DescriptorSet,Decorates^.FDescriptorSet); - node^.FBinding:=FBinding; - Inc(FBinding); + Exit(node); end; end; node:=Next(node); end; end; -procedure TsrBufferList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList); -var - node:PsrBuffer; - pVar:PsrVariable; -begin - if (FDebugInfo=nil) then Exit; - node:=First; - While (node<>nil) do - begin - pVar:=node^.pVar; - if (pVar<>nil) then - begin - FDebugInfo^.emit_source_extension(node^.GetString); - end; - node:=Next(node); - end; -end; - -procedure TsrBufferList.UpdateStorage(node:PsrChain;pBuffer:PsrBuffer); -begin - if (node=nil) or (pBuffer=nil) then Exit; - pBuffer^.write_count:=pBuffer^.write_count+node^.write_count; -end; - procedure TsrBufferList.ApplyBufferType; var + pConfig:PsrConfig; node:PsrBuffer; begin + pConfig:=FEmit.GetConfig; + + node:=FindUserDataBuf; + if (node<>nil) and (FPushConstant=nil) then + if (node^.write_count=0) and + (node^.GetSize<=pConfig^.maxPushConstantsSize) then + begin + node^.bType :=btPushConstant; + node^.FStorage:=StorageClass.PushConstant; + FPushConstant :=node; + end; + node:=First; While (node<>nil) do begin - if (node^.bType=btStorageBuffer) then + if node^.IsUsed and (node^.bType=btStorageBuffer) then begin if (FPushConstant=nil) and - (node^.write_count=0) and - (node^.GetSize<=cfg.maxPushConstantsSize) then + (node^.fchain_write=0) and + (node^.GetSize<=pConfig^.maxPushConstantsSize) then begin node^.bType :=btPushConstant; node^.FStorage:=StorageClass.PushConstant; - FPushConstant:=node; + FPushConstant :=node; end else - if (node^.write_count=0) and - (node^.GetSize<=cfg.maxUniformBufferRange) then + if (node^.fchain_write=0) and + (node^.GetSize<=pConfig^.maxUniformBufferRange) then begin node^.bType :=btUniformBuffer; node^.FStorage:=StorageClass.Uniform; end else - if cfg.CanUseStorageBufferClass then + if pConfig^.CanUseStorageBufferClass then begin node^.FStorage:=StorageClass.StorageBuffer; end else @@ -822,25 +875,97 @@ end; procedure TsrBufferList.AlignOffset; var + pConfig:PsrConfig; node:PsrBuffer; begin + pConfig:=FEmit.GetConfig; node:=First; While (node<>nil) do begin - Case node^.bType of - btStorageBuffer: - begin - AlignOffset(node,cfg.minStorageBufferOffsetAlignment); - end; - btUniformBuffer: - begin - AlignOffset(node,cfg.minUniformBufferOffsetAlignment); - end; - btPushConstant: - begin - node^.align_offset:=cfg.PushConstantsOffset; - node^.ShiftOffset(cfg.PushConstantsOffset); - end; + if node^.IsUsed then + begin + Case node^.bType of + btStorageBuffer: + begin + AlignOffset(node,pConfig^.minStorageBufferOffsetAlignment); + end; + btUniformBuffer: + begin + AlignOffset(node,pConfig^.minUniformBufferOffsetAlignment); + end; + btPushConstant: + begin + node^.align_offset:=pConfig^.PushConstantsOffset; + node^.ShiftOffset(pConfig^.PushConstantsOffset); + end; + end; + end; + node:=Next(node); + end; +end; + +procedure TsrBufferList.OnAllocTypeBinding(pField:PsrField); +var + pDecorateList:PsrDecorateList; + node:PsrField; + SD:DWORD; +begin + if (pField^.dtype<>dtTypeStruct) then Exit; + if (pField^.pType=nil) then Exit; + pDecorateList:=FEmit.GetDecorateList; + SD:=pField^.GetStructDecorate; + if (SD<>DWORD(-1)) then + begin + pDecorateList^.OpDecorate(pField^.pType,SD,0); + end; + node:=pField^.First; + While (node<>nil) do + begin + pDecorateList^.OpMemberDecorate(pField^.pType,node^.FID,node^.offset); + node:=pField^.Next(node); + end; +end; + +procedure TsrBufferList.AllocTypeBinding; +var + pDecorateList:PsrDecorateList; + node:PsrBuffer; +begin + EnumAllField(@OnAllocTypeBinding); + // + pDecorateList:=FEmit.GetDecorateList; + // + node:=First; + While (node<>nil) do + begin + if node^.IsUsed and (node^.pVar<>nil) then + if (node^.bType=btStorageBuffer) then + begin + if (node^.fchain_read=0) then + begin + pDecorateList^.OpDecorate(node^.pVar,Decoration.NonReadable,0); + end; + if (node^.fchain_write=0) then + begin + pDecorateList^.OpDecorate(node^.pVar,Decoration.NonWritable,0); + end; + end; + node:=Next(node); + end; +end; + +procedure TsrBufferList.AllocName; +var + FDebugInfo:PsrDebugInfoList; + node:PsrBuffer; +begin + FDebugInfo:=FEmit.GetDebugInfoList; + node:=First; + While (node<>nil) do + begin + if node^.IsUsed and (node^.FTop.pType<>nil) then + begin + FDebugInfo^.OpName(node^.FTop.pType,node^.GetStructName); end; node:=Next(node); end; diff --git a/spirv/srParser.pas b/spirv/srCFGCursor.pas similarity index 81% rename from spirv/srParser.pas rename to spirv/srCFGCursor.pas index 3b30305d..415da7a8 100644 --- a/spirv/srParser.pas +++ b/spirv/srCFGCursor.pas @@ -1,16 +1,17 @@ -unit srParser; +unit srCFGCursor; {$mode ObjFPC}{$H+} interface uses - sysutils, - srLabel, - srCFG, - srNodes; + srCFGLabel, + srCFGParser, + ginodes, + srNode; type + PsrCursor=^TsrCursor; TsrCursor=object(TsrLCursor) pCode:PsrCodeBlock; pBlock:PsrCFGBlock; @@ -18,8 +19,11 @@ type end; TsrCodeList=specialize TNodeQueue; + + PsrCodeHeap=^TsrCodeHeap; TsrCodeHeap=object(TsrCodeList) - Alloc:TfnAlloc; + FEmit:TCustomEmit; + Procedure Init(Emit:TCustomEmit); function FindByPtr(base:Pointer):PsrCodeBlock; function FetchByPtr(base:Pointer;bType:TsrBlockType):TsrCursor; end; @@ -28,6 +32,11 @@ implementation // +Procedure TsrCodeHeap.Init(Emit:TCustomEmit); +begin + FEmit:=Emit; +end; + function TsrCodeHeap.FindByPtr(base:Pointer):PsrCodeBlock; var node:PsrCodeBlock; @@ -52,8 +61,8 @@ begin node:=FindByPtr(base); if (node=nil) then begin - node:=Alloc(SizeOf(TsrCodeBlock)); - node^.Alloc:=Alloc; + node:=FEmit.Alloc(SizeOf(TsrCodeBlock)); + node^.FEmit:=FEmit; if parse_code_cfg(bType,base,node)>1 then Assert(False); Push_tail(node); end; diff --git a/spirv/srLabel.pas b/spirv/srCFGLabel.pas similarity index 98% rename from spirv/srLabel.pas rename to spirv/srCFGLabel.pas index 3772f8fb..f3865b12 100644 --- a/spirv/srLabel.pas +++ b/spirv/srCFGLabel.pas @@ -1,13 +1,12 @@ -unit srLabel; +unit srCFGLabel; {$mode ObjFPC}{$H+} interface uses - sysutils, ps4_pssl, - srNodes; + ginodes; type TSrcAdr=object diff --git a/spirv/srCFG.pas b/spirv/srCFGParser.pas similarity index 98% rename from spirv/srCFG.pas rename to spirv/srCFGParser.pas index 44df54e7..1fb2c46c 100644 --- a/spirv/srCFG.pas +++ b/spirv/srCFGParser.pas @@ -1,14 +1,14 @@ -unit srCFG; +unit srCFGParser; {$mode ObjFPC}{$H+} interface uses - sysutils, ps4_pssl, - srNodes, - srLabel; + ginodes, + srNode, + srCFGLabel; type PsrCFGBlock=^TsrCFGBlock; @@ -42,7 +42,7 @@ type TsrCodeBlock=object pNext:PsrCodeBlock; //---- - Alloc:TfnAlloc; + FEmit:TCustomEmit; Body:Pointer; Size:ptruint; FLabels:TsrLabels; @@ -475,10 +475,9 @@ begin Result:=FLabels.FNTree.Find(@node); if (Result=nil) then begin - Result:=Alloc(SizeOf(TsrLabel)); + Result:=FEmit.Alloc(SizeOf(TsrLabel)); Result^.Adr:=Adr; FLabels.FNTree.Insert(Result); - //FLabels.FList.Push_tail(Result); end; end; @@ -489,7 +488,7 @@ end; Function TsrCFGParser.NewBlock:PsrCFGBlock; begin - Result:=pCode^.Alloc(SizeOf(TsrCFGBlock)); + Result:=pCode^.FEmit.Alloc(SizeOf(TsrCFGBlock)); end; Procedure TsrCFGParser.PushBlock(New:PsrCFGBlock); diff --git a/spirv/srCacheOp.pas b/spirv/srCacheOp.pas new file mode 100644 index 00000000..8a5d6df5 --- /dev/null +++ b/spirv/srCacheOp.pas @@ -0,0 +1,114 @@ +unit srCacheOp; + +{$mode objfpc}{$H+} + +interface + +uses + ginodes, + srNode, + srCFGLabel, + srType, + srReg, + srOp; + +type + PsrCacheOp=^TsrCacheOp; + TsrCacheOp=object + private + pLeft,pRight:PsrCacheOp; + //---- + key:packed record + place:PsrOpBlock; + OpId:DWORD; + dtype:TsrDataType; + count:DWORD; + end; + pData:PPsrRegNode; + function c(n1,n2:PsrCacheOp):Integer; static; + public + pDst:PsrNode; + end; + + PsrCacheOpList=^TsrCacheOpList; + TsrCacheOpList=object + type + TNodeFetch=specialize TNodeFetch; + var + FEmit:TCustomEmit; + FNTree:TNodeFetch; + Procedure Init(Emit:TCustomEmit); inline; + function Fetch(place:PsrOpBlock;OpId:DWORD;rtype:TsrDataType;count:Byte;src:PPsrRegNode):PsrCacheOp; + end; + +function _up_to_real(t:PsrOpBlock):PsrOpBlock; + +implementation + +function _up_to_real(t:PsrOpBlock):PsrOpBlock; +begin + repeat + if not t^.IsType(ntOpBlock) then Break; + Case t^.Block.bType of + btMain, + btCond, + btLoop:Break; + else; + end; + t:=t^.Parent; + until false; + Result:=t; +end; + +//-- + +function TsrCacheOp.c(n1,n2:PsrCacheOp):Integer; +var + count:DWORD; +begin + Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrCacheOp.key)); + if (Result=0) then + begin + count:=n1^.key.count; + if (count<>0) then + begin + Result:=CompareByte(n1^.pData^,n2^.pData^,count*SizeOf(Pointer)); + end; + end; +end; + +Procedure TsrCacheOpList.Init(Emit:TCustomEmit); inline; +begin + FEmit:=Emit; +end; + +function TsrCacheOpList.Fetch(place:PsrOpBlock;OpId:DWORD;rtype:TsrDataType;count:Byte;src:PPsrRegNode):PsrCacheOp; +var + size:ptruint; + node:TsrCacheOp; +begin + Assert(place<>nil); + place:=_up_to_real(place); + Result:=nil; + node:=Default(TsrCacheOp); + node.key.place:=place; + node.key.OpId :=OpId; + node.key.dtype:=rtype; + node.key.count:=count; + node.pData:=src; + Result:=FNTree.Find(@node); + if (Result=nil) then + begin + Result:=FEmit.Alloc(SizeOf(TsrCacheOp)); + Move(node,Result^,SizeOf(TsrCacheOp)); + + size:=count*SizeOf(Pointer); + Result^.pData:=FEmit.Alloc(size); + Move(src^,Result^.pData^,size); + + FNTree.Insert(Result); + end; +end; + +end. + diff --git a/spirv/srCap.pas b/spirv/srCap.pas deleted file mode 100644 index 93faf80b..00000000 --- a/spirv/srCap.pas +++ /dev/null @@ -1,62 +0,0 @@ -unit srCap; - -{$mode ObjFPC}{$H+} - -interface - -uses - srNodes; - -type - PSpirvCap=^TSpirvCap; - TSpirvCap=object - pLeft,pRight:PSpirvCap; - //---- - ID:DWORD; - function c(n1,n2:PSpirvCap):Integer; static; - end; - - PsrCapList=^TsrCapList; - TsrCapList=object - type - TNodeFetch=specialize TNodeFetch; - var - Alloc:TfnAlloc; - FNTree:TNodeFetch; - procedure Add(ID:DWORD); - Function First:PSpirvCap; - Function Next(node:PSpirvCap):PSpirvCap; - end; - -implementation - -function TSpirvCap.c(n1,n2:PSpirvCap):Integer; -begin - Result:=Integer(n1^.ID>n2^.ID)-Integer(n1^.IDnil) then Exit; - pnode:=Alloc(SizeOf(TSpirvCap)); - Move(fnode,pnode^,SizeOf(TSpirvCap)); - FNTree.Insert(pnode); -end; - -Function TsrCapList.First:PSpirvCap; -begin - Result:=FNTree.Min; -end; - -Function TsrCapList.Next(node:PSpirvCap):PSpirvCap; -begin - Result:=FNTree.Next(node); -end; - -end. - diff --git a/spirv/srCapability.pas b/spirv/srCapability.pas new file mode 100644 index 00000000..dccb5dfd --- /dev/null +++ b/spirv/srCapability.pas @@ -0,0 +1,69 @@ +unit srCapability; + +{$mode ObjFPC}{$H+} + +interface + +uses + ginodes, + srNode; + +type + PsrCapability=^TsrCapability; + TsrCapability=object + pLeft,pRight:PsrCapability; + //---- + ID:DWORD; + function c(n1,n2:PsrCapability):Integer; static; + end; + + PsrCapabilityList=^TsrCapabilityList; + TsrCapabilityList=object + type + TNodeFetch=specialize TNodeFetch; + var + FEmit:TCustomEmit; + FNTree:TNodeFetch; + Procedure Init(Emit:TCustomEmit); + procedure Add(ID:DWORD); + Function First:PsrCapability; + Function Next(node:PsrCapability):PsrCapability; + end; + +implementation + +function TsrCapability.c(n1,n2:PsrCapability):Integer; +begin + Result:=Integer(n1^.ID>n2^.ID)-Integer(n1^.IDnil) then Exit; + pnode:=FEmit.Alloc(SizeOf(TsrCapability)); + Move(fnode,pnode^,SizeOf(TsrCapability)); + FNTree.Insert(pnode); +end; + +Function TsrCapabilityList.First:PsrCapability; +begin + Result:=FNTree.Min; +end; + +Function TsrCapabilityList.Next(node:PsrCapability):PsrCapability; +begin + Result:=FNTree.Next(node); +end; + +end. + diff --git a/spirv/srConfig.pas b/spirv/srConfig.pas new file mode 100644 index 00000000..2d1efebf --- /dev/null +++ b/spirv/srConfig.pas @@ -0,0 +1,47 @@ +unit srConfig; + +{$mode ObjFPC}{$H+} + +interface + +type + PsrConfig=^TsrConfig; + TsrConfig=packed object + PrintAsm:Boolean; + UseVertexInput:Boolean; //True + UseTexelBuffer:Boolean; + UseOutput16:Boolean; + // + DescriptorSet:DWORD; //0 + // + SpvVersion:PtrUint; // $10100 + maxUniformBufferRange:PtrUint; // $FFFF + PushConstantsOffset:PtrUint; // 0 + maxPushConstantsSize:PtrUint; // 128 + minStorageBufferOffsetAlignment:PtrUint; // $10 + minUniformBufferOffsetAlignment:PtrUint; // $100 + // + Procedure Init; + Function CanUseStorageBufferClass:Boolean; + end; + +implementation + +Procedure TsrConfig.Init; +begin + UseVertexInput:=True; + // + SpvVersion:=$10100; + maxUniformBufferRange:=$FFFF; + maxPushConstantsSize:=128; + minStorageBufferOffsetAlignment:=0; + minUniformBufferOffsetAlignment:=0; +end; + +Function TsrConfig.CanUseStorageBufferClass:Boolean; +begin + Result:=(SpvVersion>=$10300); +end; + +end. + diff --git a/spirv/srConst.pas b/spirv/srConst.pas index f2889ebf..0bb9d183 100644 --- a/spirv/srConst.pas +++ b/spirv/srConst.pas @@ -5,66 +5,91 @@ unit srConst; interface uses - srNodes, - srRefId, - srTypes, - half16; + sysutils, + spirv, + ginodes, + srNode, + srLiteral, + srRefId, + srType, + srTypes, + half16; type - PPsrConst=^PsrConst; - PsrConst=^TsrConst; - TsrConst=object - pPrev,pNext,pLeft,pRight:PsrConst; - //---- - read_count:DWORD; - ID:TsrRefId; //post id - pType:PsrType; - key:packed record - dtype:TsrDataType; - count:DWORD; - end; - Data:QWORD; - function c(n1,n2:PsrConst):Integer; static; - Procedure mark_read; - Procedure mark_unread; - function GetCompItem(i:Byte):PsrConst; inline; - Procedure SetCompItem(i:Byte;p:PsrConst); inline; - function GetData:QWORD; - Function isZeroVal:Boolean; inline; - Function isBoolVal:Boolean; - Function AsBool:Boolean; inline; - Function AsUint:DWORD; - function AsInt:Integer; inline; - Function AsUint64:QWORD; inline; - Function AsInt64:Int64; inline; - function AsFloat32:Single; - function AsHalf16:THalf16; - function AsWord:Word; - function AsByte:Byte; - Procedure _mark_read_child; - Procedure _mark_unread_child; - Procedure Clear; + ntConst=class(TsrNodeVmt) + class Procedure zero_read (node:PsrNode); override; + class Procedure zero_unread (node:PsrNode); override; + class function Next (node:PsrNode):Pointer; override; + class function Prev (node:PsrNode):Pointer; override; + class Function GetPtype (node:PsrNode):PsrNode; override; + class function GetPrintName (node:PsrNode):RawByteString; override; + class function GetRef (node:PsrNode):Pointer; override; end; + PPsrConst=^PsrConst; + PsrConst=^TsrConst; + TsrConst=packed object(TsrNode) + private + pPrev,pNext,pLeft,pRight:PsrConst; + //-- + ID:TsrRefId; //post id + fOpId:WORD; + fCount:WORD; + FType:PsrType; + pData:PPsrNode; + function c(n1,n2:PsrConst):Integer; static; + public + property pType:PsrType read FType; + property OpId:WORD read fOpId; + property ItemCount:WORD read fCount; + Procedure Init; inline; + function dtype:TsrDataType; + function GetItem(i:Word):PsrNode; + function GetLiteral(i:Word):PsrLiteral; + function GetConst(i:Word):PsrConst; + Function AsBool:Boolean; inline; + function AsUint8:Byte; inline; + function AsInt8:Shortint; inline; + function AsUint16:Word; inline; + function AsInt16:Smallint; inline; + Function AsUint32:DWORD; inline; + function AsInt32:Integer; inline; + Function AsUint64:QWORD; inline; + Function AsInt64:Int64; inline; + function AsHalf16:THalf16; inline; + function AsFloat32:Single; inline; + function AsFloat64:Double; inline; + function GetData:QWORD; + Function isZeroVal:Boolean; inline; + Function isBoolVal:Boolean; inline; + function GetPrintName:RawByteString; + end; + + PsrConstList=^TsrConstList; TsrConstList=object type TNodeList=specialize TNodeList; TNodeFetch=specialize TNodeFetch; var - Alloc:TfnAlloc; + FEmit:TCustomEmit; FList:TNodeList; FNTree:TNodeFetch; - function _Fetch(node:PsrConst):PsrConst; - function Fetch(dtype:TsrDataType;value:QWORD):PsrConst; - function Fetchb(value:Boolean):PsrConst; inline; - function Fetchi(dtype:TsrDataType;value:Integer):PsrConst; inline; - Function Fetchf(dtype:TsrDataType;value:Single):PsrConst; inline; - function Fetch_ssrc9_const(SSRC:Word;d2:DWORD):PsrConst; - function Fetch_ssrc9_const(SSRC:Word;d2:DWORD;rtype:TsrDataType):PsrConst; - function Fetch_ssrc8_const(SSRC:Byte;d2:DWORD):PsrConst; inline; - function Fetch_ssrc8_const(SSRC:Byte;d2:DWORD;rtype:TsrDataType):PsrConst; inline; - function Fetch_vec(rtype:TsrDataType;count:Byte;nodes:PPsrConst):PsrConst; - function Bitcast(rtype:TsrDataType;old:PsrConst):PsrConst; + Procedure Init(Emit:TCustomEmit); inline; + function _Fetch(node:PsrConst;copy:Boolean):PsrConst; + function _Fetch1(dtype:TsrDataType;OpId:DWORD;value:QWORD):PsrConst; + function _FetchVector(dtype:TsrDataType;value:QWORD):PsrConst; + function Fetch(dtype:TsrDataType;value:QWORD):PsrConst; + function Fetch_b(value:Boolean):PsrConst; inline; + function Fetch_i(dtype:TsrDataType;value:Integer):PsrConst; inline; + Function Fetch_s(dtype:TsrDataType;value:Single):PsrConst; inline; + function FetchVector(pType:PsrType;count:Word;pData:PPsrConst;copy:Boolean):PsrConst; + function FetchVector(dtype:TsrDataType;pData:PPsrConst;copy:Boolean):PsrConst; + function Bitcast(rtype:TsrDataType;old:PsrConst):PsrConst; + function Fetch_ssrc9_const(SSRC:Word;d2:DWORD):PsrConst; + function Fetch_ssrc9_const(SSRC:Word;d2:DWORD;rtype:TsrDataType):PsrConst; + function Fetch_ssrc8_const(SSRC:Byte;d2:DWORD):PsrConst; inline; + function Fetch_ssrc8_const(SSRC:Byte;d2:DWORD;rtype:TsrDataType):PsrConst; inline; + function First:PsrConst; inline; end; function get_soffset_const_int(SSRC:Word):Integer; @@ -75,291 +100,457 @@ function CompareConst(r1,r2:PsrConst):Boolean; implementation -function TsrConst.c(n1,n2:PsrConst):Integer; +class Procedure ntConst.zero_read(node:PsrNode); var - count:DWORD; + i:WORD; begin - Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrConst.key)); - if (Result<>0) then Exit; - count:=n1^.key.count; - if (count=0) then + With PsrConst(node)^ do begin - Result:=Integer(n1^.Data>n2^.Data)-Integer(n1^.Data0) then + For i:=0 to fCount-1 do + begin + GetItem(i)^.mark_read(node); + end; end; end; -Procedure TsrConst.mark_read; +class Procedure ntConst.zero_unread(node:PsrNode); +var + i:WORD; begin - Inc(read_count); + With PsrConst(node)^ do + begin + FType^.mark_unread(node); + if (fCount<>0) then + For i:=0 to fCount-1 do + begin + GetItem(i)^.mark_unread(node); + end; + end; end; -Procedure TsrConst.mark_unread; +class function ntConst.Next(node:PsrNode):Pointer; begin - Assert(read_count<>0); - if (read_count<>0) then Dec(read_count); + Result:=PsrConst(node)^.pNext; end; -function TsrConst.GetCompItem(i:Byte):PsrConst; inline; +class function ntConst.Prev(node:PsrNode):Pointer; begin - Result:=PPsrConst(@Data)[i]; + Result:=PsrConst(node)^.pPrev; end; -Procedure TsrConst.SetCompItem(i:Byte;p:PsrConst); inline; +class Function ntConst.GetPtype(node:PsrNode):PsrNode; begin - PPsrConst(@Data)[i]:=p; + Result:=PsrConst(node)^.FType; +end; + +class function ntConst.GetPrintName(node:PsrNode):RawByteString; +begin + Result:=PsrConst(node)^.GetPrintName; +end; + +class function ntConst.GetRef(node:PsrNode):Pointer; +begin + Result:=@PsrConst(node)^.ID; +end; + +// + +Procedure TsrConst.Init; inline; +begin + fntype:=ntConst; +end; + +function TsrConst.c(n1,n2:PsrConst):Integer; +begin + //first FType + Result:=Integer(n1^.FType>n2^.FType)-Integer(n1^.FType0) then Exit; + //second fCount + Result:=Integer(n1^.fCount>n2^.fCount)-Integer(n1^.fCount0) then Exit; + //third pData + Result:=ComparePtruint(PPtruint(n1^.pData),PPtruint(n2^.pData),n1^.fCount); +end; + +function TsrConst.dtype:TsrDataType; +begin + Result:=FType^.dtype; +end; + +function TsrConst.GetItem(i:Word):PsrNode; +begin + if (i>fCount) then Exit(nil); + Result:=pData[i]; +end; + +function TsrConst.GetLiteral(i:Word):PsrLiteral; +begin + Result:=GetItem(i)^.AsType(ntLiteral); +end; + +function TsrConst.GetConst(i:Word):PsrConst; +begin + Result:=GetItem(i)^.AsType(ntConst); +end; + +Function TsrConst.AsBool:Boolean; inline; +begin + Result:=GetLiteral(0)^.AsBool; +end; + +function TsrConst.AsUint8:Byte; inline; +begin + Result:=GetLiteral(0)^.AsUint8; +end; + +function TsrConst.AsInt8:Shortint; inline; +begin + Result:=GetLiteral(0)^.AsInt8; +end; + +function TsrConst.AsUint16:Word; inline; +begin + Result:=GetLiteral(0)^.AsUint16; +end; + +function TsrConst.AsInt16:Smallint; inline; +begin + Result:=GetLiteral(0)^.AsInt16; +end; + +Function TsrConst.AsUint32:DWORD; inline; +begin + Result:=GetLiteral(0)^.AsUint32; +end; + +function TsrConst.AsInt32:Integer; inline; +begin + Result:=GetLiteral(0)^.AsInt32; +end; + +Function TsrConst.AsUint64:QWORD; inline; +begin + Result:=GetLiteral(0)^.AsUint64; +end; + +Function TsrConst.AsInt64:Int64; inline; +begin + Result:=GetLiteral(0)^.AsInt64; +end; + +function TsrConst.AsHalf16:THalf16; inline; +begin + Result:=GetLiteral(0)^.AsHalf16; +end; + +function TsrConst.AsFloat32:Single; inline; +begin + Result:=GetLiteral(0)^.AsFloat32; +end; + +function TsrConst.AsFloat64:Double; inline; +begin + Result:=GetLiteral(0)^.AsFloat64; end; function TsrConst.GetData:QWORD; begin Result:=0; - case key.dtype of + case dtype of + dtVec2u8, + dtVec2i8: + begin + PBYTE(@Result)[0]:=GetConst(0)^.AsUint8; + PBYTE(@Result)[1]:=GetConst(1)^.AsUint8; + end; + + dtVec4u8, + dtVec4i8: + begin + PBYTE(@Result)[0]:=GetConst(0)^.AsUint8; + PBYTE(@Result)[1]:=GetConst(1)^.AsUint8; + PBYTE(@Result)[2]:=GetConst(2)^.AsUint8; + PBYTE(@Result)[3]:=GetConst(3)^.AsUint8; + end; + + dtStruct2u, + dtVec2u, + dtVec2i, dtVec2f: begin - PSingle(@Result)[0]:=GetCompItem(0)^.AsFloat32; - PSingle(@Result)[1]:=GetCompItem(1)^.AsFloat32; + PDWORD(@Result)[0]:=GetConst(0)^.AsUint32; + PDWORD(@Result)[1]:=GetConst(1)^.AsUint32; end; - dtVec2h: - begin - PHalf16(@Result)[0]:=GetCompItem(0)^.AsHalf16; - PHalf16(@Result)[1]:=GetCompItem(1)^.AsHalf16; - end; - dtVec4h: - begin - PHalf16(@Result)[0]:=GetCompItem(0)^.AsHalf16; - PHalf16(@Result)[1]:=GetCompItem(1)^.AsHalf16; - PHalf16(@Result)[2]:=GetCompItem(2)^.AsHalf16; - PHalf16(@Result)[3]:=GetCompItem(3)^.AsHalf16; - end; - dtStruct2u: - begin - PDWord(@Result)[0]:=GetCompItem(0)^.AsUint; - PDWord(@Result)[1]:=GetCompItem(1)^.AsUint; - end; + + dtVec2u16, + dtVec2i16, + dtVec2h : + begin + PWORD(@Result)[0]:=GetConst(0)^.AsUint16; + PWORD(@Result)[1]:=GetConst(1)^.AsUint16; + end; + + dtVec4u16, + dtVec4i16, + dtVec4h : + begin + PWORD(@Result)[0]:=GetConst(0)^.AsUint16; + PWORD(@Result)[1]:=GetConst(1)^.AsUint16; + PWORD(@Result)[2]:=GetConst(2)^.AsUint16; + PWORD(@Result)[3]:=GetConst(3)^.AsUint16; + end; + else begin - Assert(key.count=0,'count<>0'); - Result:=data; + Assert(fCount=1,'fCount<>1'); + Result:=AsUint64; end; end; end; Function TsrConst.isZeroVal:Boolean; begin - case key.dtype of - dtInt32 , - dtUint32 , - dtFloat32:Result:=(AsUint=0); + case dtype of + dtInt8, + dtUint8:Result:=(AsUint8=0); + + dtHalf16, + dtInt16, + dtUint16:Result:=(AsUint16=0); + + dtFloat32, + dtInt32, + dtUint32:Result:=(AsUint32=0); + + dtFloat64, + dtInt64, + dtUint64:Result:=(AsUint64=0); else Result:=False; end; end; -Function TsrConst.isBoolVal:Boolean; +Function TsrConst.isBoolVal:Boolean; inline; begin - if (key.count<>0) then Exit(False); - Case Data of + if (fCount<>1) then Exit(False); + Case AsUint64 of 0,1:Result:=True; else Result:=False; end; end; -Function TsrConst.AsBool:Boolean; inline; -begin - Result:=PBoolean(@Data)^; -end; - -Function TsrConst.AsUint:DWORD; -begin - Result:=PDWORD(@Data)^; -end; - -function TsrConst.AsInt:Integer; inline; -begin - Result:=PInteger(@Data)^; -end; - -Function TsrConst.AsUint64:QWORD; inline; -begin - Result:=Data; -end; - -Function TsrConst.AsInt64:Int64; inline; -begin - Result:=Int64(Data); -end; - -function TsrConst.AsFloat32:Single; -begin - Result:=PSingle(@Data)^; -end; - -function TsrConst.AsHalf16:THalf16; -begin - Result:=PHalf16(@Data)^ -end; - -function TsrConst.AsWord:Word; -begin - Result:=PWord(@Data)^; -end; - -function TsrConst.AsByte:Byte; -begin - Result:=PByte(@Data)^; -end; - -Procedure TsrConst._mark_read_child; +function TsrConst.GetPrintName:RawByteString; var - i:DWORD; + s:Single; + i:Int64; + ui:qword; begin - if (key.count<>0) then - For i:=0 to key.count-1 do - begin - GetCompItem(i)^.mark_read; - end; -end; + Result:=''; -Procedure TsrConst._mark_unread_child; -var - i:DWORD; -begin - if (key.count<>0) then - For i:=0 to key.count-1 do - begin - GetCompItem(i)^.mark_unread; - end; -end; + Case dtype of + dtBool: + begin + Case AsBool of + true :Result:='true'; + False:Result:='false'; + end; + end; -Procedure TsrConst.Clear; -var - i:DWORD; -begin - if (key.count<>0) then + dtHalf16: + begin + s:=Single(AsHalf16); + i:=Trunc(s); + if (s=i) then + begin + Case i of + 0..99:Result:='ch'+IntToStr(i); + -9..-1:Result:='chm'+IntToStr(abs(i)); + else; + end; + end; + end; + + dtFloat32: + begin + s:=AsFloat32; + i:=Trunc(s); + if (s=i) then + begin + Case i of + 0..99:Result:='cf'+IntToStr(i); + -9..-1:Result:='cfm'+IntToStr(abs(i)); + else; + end; + end; + end; + + dtInt32 : + begin + i:=AsInt32; + Case i of + 0..99:Result:='ci'+IntToStr(i); + -9..-1:Result:='cim'+IntToStr(abs(i)); + else; + end; + end; + + dtUint32: + begin + ui:=AsUint32; + Case ui of + 0..99:Result:='cu'+IntToStr(ui); + else; + end; + end; + + else; + end; + + if (Result='') then begin - For i:=0 to key.count-1 do - begin - GetCompItem(i)^.mark_unread; - end; - key.count:=0; + Assert(ID.Alloc); + Result:='c'+IntToStr(ID.ID); end; end; -function TsrConstList._Fetch(node:PsrConst):PsrConst; +// + +Procedure TsrConstList.Init(Emit:TCustomEmit); inline; +begin + FEmit:=Emit; +end; + +function TsrConstList._Fetch(node:PsrConst;copy:Boolean):PsrConst; var size:DWORD; begin Result:=FNTree.Find(node); if (Result=nil) then begin - size:=node^.key.count; - if (size=0) then - size:=SizeOf(TsrConst) - else - size:=SizeOf(TsrConst)-SizeOf(TsrConst.Data)+SizeOf(Pointer)*size; - Result:=Alloc(size); - Move(node^,Result^,size); + Result:=FEmit.Alloc(SizeOf(TsrConst)); + Move(node^,Result^,SizeOf(TsrConst)); + + if copy and (node^.fCount<>0) then + begin + size:=SizeOf(Pointer)*node^.fCount; + Result^.pData:=FEmit.Alloc(size); + Move(node^.pData^,Result^.pData^,Size); + end; + FNTree.Insert(Result); FList.Push_tail(Result); - end else - begin - node^._mark_unread_child; end; end; -function TsrConstList.Fetch(dtype:TsrDataType;value:QWORD):PsrConst; +function TsrConstList._Fetch1(dtype:TsrDataType;OpId:DWORD;value:QWORD):PsrConst; var - rec:record - node:TsrConst; - align:array[0..3] of Pointer; - end; - h:array[0..3] of PsrConst; + pLiteralList:PsrLiteralList; + pTypeList:PsrTypeList; + node:TsrConst; + item:array[0..0] of PsrNode; begin Result:=nil; - rec.node:=Default(TsrConst); + pLiteralList:=FEmit.GetLiteralList; + pTypeList :=FEmit.GetTypeList; + // + item[0]:=pLiteralList^.FetchConst(dtype,value); + // + node:=Default(TsrConst); + node.Init; + node.fOpId :=OpId; + node.fCount:=1; + node.FType :=pTypeList^.Fetch(dtype); + node.pData :=@item; + Result:=_Fetch(@node,True); +end; - value:=value and GetTypeHigh(dtype); +function TsrConstList._FetchVector(dtype:TsrDataType;value:QWORD):PsrConst; +var + pTypeList:PsrTypeList; + node:TsrConst; + item:array[0..3] of PsrNode; + Child:TsrDataType; + High:QWORD; + i,BitSize:Byte; +begin + Result:=nil; + pTypeList:=FEmit.GetTypeList; + // + Child :=dtype.Child; + BitSize:=Child.BitSize; + High :=Child.High; + For i:=0 to dtype.Count-1 do + begin + item[i]:=Fetch(Child,value and High); + value:=value shr BitSize; + end; + // + node:=Default(TsrConst); + node.Init; + node.fOpId :=Op.OpConstantComposite; + node.fCount:=dtype.Count; + node.FType :=pTypeList^.Fetch(dtype); + node.pData :=@item; + Result:=_Fetch(@node,True); +end; + +function TsrConstList.Fetch(dtype:TsrDataType;value:QWORD):PsrConst; +begin + Result:=nil; + + value:=value and dtype.High; Case dtype of - dtUnknow, - dtBool, - dtFloat32, + dtUnknow: + begin + Result:=_Fetch1(dtype,Op.OpNop,value); + end; + + dtBool: + begin + if Boolean(value) then + begin + Result:=_Fetch1(dtype,Op.OpConstantTrue ,value); + end else + begin + Result:=_Fetch1(dtype,Op.OpConstantFalse,value); + end; + end; + dtHalf16, + dtFloat32, + dtFloat64, + dtInt8, + dtUint8, + dtInt16, + dtUint16, dtInt32, dtUint32, dtInt64, dtUint64: - begin - rec.node.key.dtype:=dtype; - rec.node.Data:=value; - Result:=_Fetch(@rec.node); - Result^.mark_read; + Result:=_Fetch1(dtype,Op.OpConstant,value); end; dtStruct2u, + dtVec2u8, + dtVec4u8, + dtVec2i8, + dtVec4i8, + dtVec2u16, + dtVec4u16, + dtVec2i16, + dtVec4i16, dtVec2u, dtVec2i, + dtVec2h, + dtVec4h, dtVec2f: begin - rec.node.key.dtype:=GetVecChild(dtype); - rec.node.Data:=PDWORD(@value)[0]; - h[0]:=_Fetch(@rec.node); - h[0]^.mark_read; - rec.node.Data:=PDWORD(@value)[1]; - h[1]:=_Fetch(@rec.node); - h[1]^.mark_read; - rec.node.key.dtype:=dtype; - rec.node.key.count:=2; - rec.node.SetCompItem(0,h[0]); - rec.node.SetCompItem(1,h[1]); - Result:=_Fetch(@rec.node); - Result^.mark_read; - end; - - dtVec2h: - begin - rec.node.key.dtype:=dtHalf16; - rec.node.Data:=PWORD(@value)[0]; - h[0]:=_Fetch(@rec.node); - h[0]^.mark_read; - rec.node.Data:=PWORD(@value)[1]; - h[1]:=_Fetch(@rec.node); - h[1]^.mark_read; - rec.node.key.dtype:=dtVec2h; - rec.node.key.count:=2; - rec.node.SetCompItem(0,h[0]); - rec.node.SetCompItem(1,h[1]); - Result:=_Fetch(@rec.node); - Result^.mark_read; - end; - - dtVec4h: - begin - rec.node.key.dtype:=dtHalf16; - rec.node.Data:=PWORD(@value)[0]; - h[0]:=_Fetch(@rec.node); - h[0]^.mark_read; - rec.node.Data:=PWORD(@value)[1]; - h[1]:=_Fetch(@rec.node); - h[1]^.mark_read; - rec.node.Data:=PWORD(@value)[2]; - h[2]:=_Fetch(@rec.node); - h[2]^.mark_read; - rec.node.Data:=PWORD(@value)[3]; - h[3]:=_Fetch(@rec.node); - h[3]^.mark_read; - rec.node.key.dtype:=dtVec4h; - rec.node.key.count:=4; - rec.node.SetCompItem(0,h[0]); - rec.node.SetCompItem(1,h[1]); - rec.node.SetCompItem(2,h[2]); - rec.node.SetCompItem(3,h[3]); - Result:=_Fetch(@rec.node); - Result^.mark_read; + Result:=_FetchVector(dtype,value); end; else @@ -368,35 +559,88 @@ begin end; -function TsrConstList.Fetchb(value:Boolean):PsrConst; inline; +function TsrConstList.Fetch_b(value:Boolean):PsrConst; inline; begin Result:=Fetch(dtBool,QWORD(value)); end; -function TsrConstList.Fetchi(dtype:TsrDataType;value:Integer):PsrConst; inline; +function TsrConstList.Fetch_i(dtype:TsrDataType;value:Integer):PsrConst; inline; begin Result:=Fetch(dtype,PDWORD(@value)^); end; -Function TsrConstList.Fetchf(dtype:TsrDataType;value:Single):PsrConst; inline; +Function TsrConstList.Fetch_s(dtype:TsrDataType;value:Single):PsrConst; inline; begin Result:=Fetch(dtype,PDWORD(@value)^); end; +function TsrConstList.FetchVector(pType:PsrType;count:Word;pData:PPsrConst;copy:Boolean):PsrConst; +var + node:TsrConst; +begin + Assert(count<>0); + Assert(pData<>nil); + node:=Default(TsrConst); + node.Init; + node.fOpId :=Op.OpConstantComposite; + node.fCount:=count; + node.FType :=pType; + node.pData :=Pointer(pData); + Result:=_Fetch(@node,copy); +end; + +function TsrConstList.FetchVector(dtype:TsrDataType;pData:PPsrConst;copy:Boolean):PsrConst; +var + pTypeList:PsrTypeList; +begin + pTypeList:=FEmit.GetTypeList; + Result:=FetchVector(pTypeList^.Fetch(dtype),dtype.Count,pData,copy); +end; + +function TsrConstList.Bitcast(rtype:TsrDataType;old:PsrConst):PsrConst; +var + data:qword; +begin + Result:=nil; + + if not old^.IsType(ntConst) then Exit(old); + + if (rtype=dtUnknow) or (rtype=old^.dtype) then + begin + Exit(old); + end; + + if (old^.dtype=dtUnknow) then + begin + data:=old^.GetData; + Result:=Fetch(rtype,data); + Exit; + end; + + if TryBitcastType(rtype,old^.dtype) then + begin + data:=old^.GetData; + Result:=Fetch(rtype,data); + end else + begin + Assert(false,'const bitcast'); + end; +end; + function TsrConstList.Fetch_ssrc9_const(SSRC:Word;d2:DWORD):PsrConst; begin Case SSRC of 128:Result:=Fetch(dtUnknow,0); 129..192:Result:=Fetch(dtUint32,SSRC-128); - 193..208:Result:=Fetchi(dtInt32,-(SSRC-192)); - 240:Result:=Fetchf(dtFloat32, 0.5); - 241:Result:=Fetchf(dtFloat32,-0.5); - 242:Result:=Fetchf(dtFloat32, 1.0); - 243:Result:=Fetchf(dtFloat32,-1.0); - 244:Result:=Fetchf(dtFloat32, 2.0); - 245:Result:=Fetchf(dtFloat32,-2.0); - 246:Result:=Fetchf(dtFloat32, 4.0); - 247:Result:=Fetchf(dtFloat32,-4.0); + 193..208:Result:=Fetch_i(dtInt32,-(SSRC-192)); + 240:Result:=Fetch_s(dtFloat32, 0.5); + 241:Result:=Fetch_s(dtFloat32,-0.5); + 242:Result:=Fetch_s(dtFloat32, 1.0); + 243:Result:=Fetch_s(dtFloat32,-1.0); + 244:Result:=Fetch_s(dtFloat32, 2.0); + 245:Result:=Fetch_s(dtFloat32,-2.0); + 246:Result:=Fetch_s(dtFloat32, 4.0); + 247:Result:=Fetch_s(dtFloat32,-4.0); 255:Result:=Fetch(dtUnknow,d2); else Result:=nil; @@ -421,20 +665,20 @@ begin begin if CompareType(dtInt32,rtype) then begin - Result:=Fetchi(dtInt32,-(SSRC-192)); + Result:=Fetch_i(dtInt32,-(SSRC-192)); end else begin - Result:=Fetchi(rtype,-(SSRC-192)); + Result:=Fetch_i(rtype,-(SSRC-192)); end; end; - 240:Result:=Fetchf(rtype, 0.5); - 241:Result:=Fetchf(rtype,-0.5); - 242:Result:=Fetchf(rtype, 1.0); - 243:Result:=Fetchf(rtype,-1.0); - 244:Result:=Fetchf(rtype, 2.0); - 245:Result:=Fetchf(rtype,-2.0); - 246:Result:=Fetchf(rtype, 4.0); - 247:Result:=Fetchf(rtype,-4.0); + 240:Result:=Fetch_s(rtype, 0.5); + 241:Result:=Fetch_s(rtype,-0.5); + 242:Result:=Fetch_s(rtype, 1.0); + 243:Result:=Fetch_s(rtype,-1.0); + 244:Result:=Fetch_s(rtype, 2.0); + 245:Result:=Fetch_s(rtype,-2.0); + 246:Result:=Fetch_s(rtype, 4.0); + 247:Result:=Fetch_s(rtype,-4.0); 255:Result:=Fetch(rtype,d2); else Result:=nil; @@ -451,57 +695,9 @@ begin Result:=Fetch_ssrc9_const(SSRC,d2,rtype); end; -function TsrConstList.Fetch_vec(rtype:TsrDataType;count:Byte;nodes:PPsrConst):PsrConst; -var - rec:record - node:TsrConst; - align:array[0..3] of Pointer; - end; - h:PsrConst; - i:Byte; +function TsrConstList.First:PsrConst; inline; begin - Assert(count<>0); - Assert(count<=4); - rec.node:=Default(TsrConst); - rec.node.key.dtype:=rtype; - rec.node.key.count:=count; - For i:=0 to count-1 do - begin - h:=nodes[i]; - h^.mark_read; - rec.node.SetCompItem(i,h); - end; - Result:=_Fetch(@rec.node); - Result^.mark_read; -end; - -function TsrConstList.Bitcast(rtype:TsrDataType;old:PsrConst):PsrConst; -var - data:qword; -begin - Result:=nil; - if (old=nil) then Exit; - if (rtype=dtUnknow) or (rtype=old^.key.dtype) then - begin - old^.mark_read; - Exit(old); - end; - - if (old^.key.dtype=dtUnknow) then - begin - data:=old^.Data; - Result:=Fetch(rtype,data); - Exit; - end; - - if TryBitcastType(rtype,old^.key.dtype) then - begin - data:=old^.GetData; - Result:=Fetch(rtype,data); - end else - begin - Assert(false,'const bitcast'); - end; + Result:=FList.pHead; end; function get_soffset_const_int(SSRC:Word):Integer; @@ -564,7 +760,7 @@ begin end; end; -function CompareConstCount(buf1,buf2:PPsrConst;count:PtrUint):Boolean; +function CompareConstCount(buf1,buf2:PPsrConst;count:Byte):Boolean; begin Result:=true; While (count<>0) do @@ -584,14 +780,14 @@ begin begin Result:=(r1=r2); if Result then Exit; - if CompareType(r1^.key.dtype,r2^.key.dtype) and (r1^.key.count=r2^.key.count) then + if CompareType(r1^.dtype,r2^.dtype) and (r1^.fCount=r2^.fCount) then begin - if (r1^.key.count=0) then + if (r1^.fCount=1) then begin - Result:=(r1^.Data=r2^.Data); + Result:=(r1^.AsUint64=r2^.AsUint64); end else begin - Result:=CompareConstCount(@r1^.Data,@r2^.Data,r1^.key.count); + Result:=CompareConstCount(Pointer(r1^.pData),Pointer(r2^.pData),r1^.fCount); end; end; end; diff --git a/spirv/srDecorate.pas b/spirv/srDecorate.pas index 9ebc7071..cc936877 100644 --- a/spirv/srDecorate.pas +++ b/spirv/srDecorate.pas @@ -6,31 +6,48 @@ interface uses spirv, - srNodes, + srNode, srOp; type + PsrHeaderList=^TsrHeaderList; + TsrHeaderList=object(TsrOpBlockCustom) + FGLSL_std_450:PSpirvOp; + function emit_glsl_ext:PSpirvOp; + end; + PsrDecorateList=^TsrDecorateList; - TsrDecorateList=object(TsrOpBlockSimple) - FDescriptorSet:DWORD; - procedure emit_decorate(ntype:TsrNodeType;Data:Pointer;dec_id,param:DWORD); - procedure emit_member_decorate(ntype:TsrNodeType;Data:Pointer;index,offset:DWORD); + TsrDecorateList=object(TsrOpBlockCustom) + procedure OpDecorate(Data:PsrNode;dec_id,param:DWORD); + procedure OpMemberDecorate(Data:PsrNode;index,offset:DWORD); end; PsrDebugInfoList=^TsrDebugInfoList; - TsrDebugInfoList=object(TsrOpBlockSimple) - procedure emit_source_extension(const n:RawByteString); - procedure emit_name(ntype:TsrNodeType;Data:Pointer;const n:RawByteString); + TsrDebugInfoList=object(TsrOpBlockCustom) + procedure OpSourceExtension(const n:RawByteString); + procedure OpName(Data:PsrNode;const n:RawByteString); + function OpString(const n:RawByteString):PsrNode; end; implementation -procedure TsrDecorateList.emit_decorate(ntype:TsrNodeType;Data:Pointer;dec_id,param:DWORD); +function TsrHeaderList.emit_glsl_ext:PSpirvOp; +begin + if (FGLSL_std_450=nil) then + begin + FGLSL_std_450:=AddSpirvOp(Op.OpExtInstImport); + FGLSL_std_450^.pDst:=Emit.NewRefNode; + FGLSL_std_450^.AddString('GLSL.std.450'); + end; + Result:=FGLSL_std_450; +end; + +procedure TsrDecorateList.OpDecorate(Data:PsrNode;dec_id,param:DWORD); var node:PSpirvOp; begin node:=AddSpirvOp(Op.OpDecorate); - node^.AddParam(ntype,Data); + node^.AddParam(Data); node^.AddLiteral(dec_id,Decoration.GetStr(dec_id)); Case dec_id of Decoration.BuiltIn: @@ -48,18 +65,18 @@ begin end; end; -procedure TsrDecorateList.emit_member_decorate(ntype:TsrNodeType;Data:Pointer;index,offset:DWORD); +procedure TsrDecorateList.OpMemberDecorate(Data:PsrNode;index,offset:DWORD); var node:PSpirvOp; begin node:=AddSpirvOp(Op.OpMemberDecorate); - node^.AddParam(ntype,Data); + node^.AddParam(Data); node^.AddLiteral(index); node^.AddLiteral(Decoration.Offset,Decoration.GetStr(Decoration.Offset)); node^.AddLiteral(offset); end; -procedure TsrDebugInfoList.emit_source_extension(const n:RawByteString); +procedure TsrDebugInfoList.OpSourceExtension(const n:RawByteString); var node:PSpirvOp; begin @@ -67,14 +84,24 @@ begin node^.AddString(n); end; -procedure TsrDebugInfoList.emit_name(ntype:TsrNodeType;Data:Pointer;const n:RawByteString); +procedure TsrDebugInfoList.OpName(Data:PsrNode;const n:RawByteString); var node:PSpirvOp; begin node:=AddSpirvOp(Op.OpName); - node^.AddParam(ntype,Data); + node^.AddParam(Data); node^.AddString(n); end; +function TsrDebugInfoList.OpString(const n:RawByteString):PsrNode; +var + node:PSpirvOp; +begin + node:=AddSpirvOp(Op.OpString); + node^.pDst:=Emit.NewRefNode; + node^.AddString(n); + Result:=node^.pDst; +end; + end. diff --git a/spirv/srFlow.pas b/spirv/srFlow.pas new file mode 100644 index 00000000..01ed01ce --- /dev/null +++ b/spirv/srFlow.pas @@ -0,0 +1,418 @@ +unit srFlow; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + spirv, + srNode, + srCFGLabel, + srCFGParser, + srCFGCursor, + srReg, + srOp, + srOpUtils, + srConfig, + emit_op; + +type + TEmitFlow=class(TEmitOp) + // + Procedure InitFlow; + Procedure PushBlockOp(pLine:PspirvOp;pChild:PsrOpBlock;pLBlock:PsrCFGBlock); + function PopBlockOp:Boolean; + function CheckBlockBeg:Boolean; + function CheckBlockEnd:Boolean; + // + function GetPtr:Pointer; + procedure SetPtr(base:Pointer;bType:TsrBlockType); + function IsFinalize:Boolean; + function FindLabel(Adr:TSrcAdr):PsrLabel; + // + procedure Finalize; + // + function NextParse:Byte; + function ParseStage(base:Pointer):Byte; + end; + +implementation + +Procedure TEmitFlow.InitFlow; +begin + CodeHeap.Init(Self); + // + InitBlock:=AllocBlockOp; + InitBlock^.SetInfo(btOther,Cursor.Adr,Cursor.Adr); + PushBlockOp(line,InitBlock,nil); + Main^.PopBlock; +end; + +Procedure TEmitFlow.PushBlockOp(pLine:PspirvOp;pChild:PsrOpBlock;pLBlock:PsrCFGBlock); +begin + pChild^.FCursor:=Cursor; //prev + + InsSpirvOp(pLine,PspirvOp(pChild)); + + Main^.PushBlock(pChild); + + if (pLBlock<>nil) then + begin + Cursor.pBlock:=pLBlock; //push + end; +end; + +procedure UpdateVolMark(pBlock:PsrOpBlock); +var + pChild:PsrOpBlock; +begin + if (not pBlock^.IsType(ntOpBlock)) then Exit; + if (pBlock^.Regs.FVolMark<>vmNone) then Exit; + + pChild:=pBlock^.line; //last + if (not pChild^.IsType(ntOpBlock)) then Exit; + + Case pChild^.Block.bType of + btAdr, + btAdrBranch, + btOther:; + else + Exit; + end; + + pBlock^.Regs.FVolMark:=pChild^.Regs.FVolMark; +end; + +function TEmitFlow.PopBlockOp:Boolean; +var + pOpBlock:PsrOpBlock; + pOpChild:PsrOpBlock; + pOpLabel:array[0..2] of PspirvOp; + + branch_up:Boolean; + + procedure pop_cond; + begin + Assert(pOpLabel[1]<>nil); + + Case pOpBlock^.Regs.FVolMark of + vmNone:PrivateList.build_volatile_cur(pOpBlock^.Regs.pSnap); + vmEnd :PrivateList.build_volatile_dis(pOpBlock^.Regs.pSnap); + else; + end; + + if not is_term_op(line) then + begin + OpBranch(line,pOpLabel[1]); + end; + + AddSpirvOp(line,pOpLabel[1]); //end + end; + + procedure pop_loop; + begin + //add OpLoopMerge continue + + Assert(pOpLabel[0]<>nil); + Assert(pOpLabel[1]<>nil); + Assert(pOpLabel[2]<>nil); + + Case pOpBlock^.Regs.FVolMark of + vmNone:PrivateList.build_volatile_old(pOpBlock^.Regs.pSnap); + else; + end; + + if pOpBlock^.Cond.FUseCont then //use continue + begin + + if not is_term_op(line) then + begin + OpBranch(line,pOpLabel[1]); //break + end; + + AddSpirvOp(line,pOpLabel[2]); //OpLoopMerge end + + pOpChild:=AllocBlockOp; + pOpChild^.SetInfo(btOther,Cursor.Adr,Cursor.Adr); + PushBlockOp(line,pOpChild,nil); + OpBranch(line,pOpLabel[0]); //continue + Main^.PopBlock; + + AddSpirvOp(line,pOpLabel[1]); //end + + end else //dont used continue + begin + + if not is_term_op(line) then + begin + AddSpirvOp(line,NewLabelOp(True)); //devide + end; + + AddSpirvOp(line,pOpLabel[2]); //OpLoopMerge end + + pOpChild:=AllocBlockOp; + pOpChild^.SetInfo(btOther,Cursor.Adr,Cursor.Adr); + PushBlockOp(line,pOpChild,nil); + OpBranch(line,pOpLabel[1]); //break + Main^.PopBlock; + + AddSpirvOp(line,pOpLabel[1]); //end + + end; + + end; + + procedure pop_else; + begin + if (pOpLabel[1]<>nil) then + begin + if not is_term_op(line) then + begin + OpBranch(line,pOpLabel[1]); + end; + AddSpirvOp(line,pOpLabel[1]); + end; + end; + +begin + Result:=False; + if (Main=nil) then Exit; + + branch_up:=False; + + repeat + + pOpBlock:=Main^.pBlock; + if (pOpBlock=nil) then Exit; + + UpdateVolMark(pOpBlock); + + pOpLabel[0]:=pOpBlock^.Labels.pBegOp; + pOpLabel[1]:=pOpBlock^.Labels.pEndOp; + pOpLabel[2]:=pOpBlock^.Labels.pMrgOp; + + Case pOpBlock^.Block.bType of + btCond: + begin + pop_cond; + branch_up:=False; + end; + btLoop: + begin + pop_loop; + branch_up:=False; + end; + else + pop_else; + end; + + Case pOpBlock^.Block.bType of + btAdr: + begin + Cursor:=pOpBlock^.FCursor; + end; + btAdrBranch: + begin + Cursor:=pOpBlock^.FCursor; + branch_up:=True; + end; + btOther:; //nop + else + begin + Cursor.PopBlock; + end; + end; + + Result:=Main^.PopBlock; + + until (not branch_up) or (not Result); + +end; + +function TEmitFlow.CheckBlockBeg:Boolean; +var + pLBlock:PsrCFGBlock; + pOpLabel:array[0..3] of PspirvOp; + pOpBlock:PsrOpBlock; + pOpChild:PsrOpBlock; + adr:TSrcAdr; + Info:TsrBlockInfo; +begin + Result:=False; + adr:=Cursor.Adr; + if (FindLabel(adr)=nil) then Exit; + + pLBlock:=Cursor.pBlock^.FindBlock(adr); + if (pLBlock<>nil) then + Case pLBlock^.bType of + btLoop: + begin + PrivateList.make_copy_all; + + Info:=Default(TsrBlockInfo); + Info.b_adr:=pLBlock^.pBLabel^.Adr; + Info.e_adr:=pLBlock^.pELabel^.Adr; + Info.bType:=btLoop; + + pOpLabel[0]:=NewLabelOp(False); //continue + pOpLabel[1]:=NewLabelOp(False); //end + pOpLabel[2]:=NewLabelOp(False); //cond + pOpLabel[3]:=NewLabelOp(False); //start + + pOpLabel[0]^.Adr:=Info.b_adr; + pOpLabel[1]^.Adr:=Info.e_adr; + pOpLabel[2]^.Adr:=Info.e_adr; + pOpLabel[3]^.Adr:=Info.b_adr; + + pOpBlock:=NewBlockOp(RegsStory.get_snapshot); + pOpBlock^.SetLabels(pOpLabel[0],pOpLabel[1],pOpLabel[2]); + pOpBlock^.SetInfo(Info); + + PushBlockOp(line,pOpBlock,pLBlock); + + OpBranch(line,pOpLabel[0]); + AddSpirvOp(line,pOpLabel[0]); //continue loop + + OpLoopMerge(line,pOpLabel[1],pOpLabel[2]); + OpBranch(line,pOpLabel[3]); + AddSpirvOp(line,pOpLabel[3]); + + //down group + Info.bType:=btOther; + pOpChild:=AllocBlockOp; + pOpChild^.SetInfo(Info); + PushBlockOp(line,pOpChild,nil); + end; + btAdr, + btAdrBranch: //skip + begin + adr:=pLBlock^.pELabel^.Adr; + Cursor.Adr:=adr; + end; + else; + end; + +end; + +function TEmitFlow.CheckBlockEnd:Boolean; +begin + Result:=False; + if (Main=nil) then Exit; + if (Main^.pBlock=nil) then Exit; + + if (Main^.pBlock^.Parent<>nil) and + Main^.pBlock^.IsEndOf(Cursor.Adr) then + begin + Result:=PopBlockOp; + end; +end; + +// + +function TEmitFlow.GetPtr:Pointer; +begin + Result:=Cursor.Adr.get_pc; +end; + +procedure TEmitFlow.SetPtr(base:Pointer;bType:TsrBlockType); +begin + if (Cursor.Adr.get_pc=base) then Exit; + Cursor:=CodeHeap.FetchByPtr(base,bType); +end; + +function TEmitFlow.IsFinalize:Boolean; +begin + Result:=False; + if (Main^.pBlock^.Parent=nil) then + if Cursor.pBlock^.IsEndOf(Cursor.Adr) then + begin + Result:=True; + end; +end; + +function TEmitFlow.FindLabel(Adr:TSrcAdr):PsrLabel; +begin + Result:=nil; + if (Cursor.pCode=nil) then Exit; + Result:=Cursor.pCode^.FindLabel(Adr); +end; + +procedure TEmitFlow.Finalize; +begin + if (Main=nil) then Exit; + + if (Main^.pBlock<>nil) then + While (Main^.pBlock^.Parent<>nil) do + begin + PopBlockOp; + end; + + AddSpirvOp(Op.OpFunctionEnd); +end; + +// + +function TEmitFlow.NextParse:Byte; +var + FLevel:DWORD; +begin + if (Cursor.pCode=nil) then Exit(2); + if (Cursor.pBlock=nil) then Exit(3); + if (Main=nil) then Exit(4); + if (Main^.pBlock=nil) then Exit(5); + + if Config.PrintAsm then + begin + Write(HexStr(Cursor.OFFSET_DW*4,4)); + FLevel:=0; + if (Main<>nil) then + if (Main^.pBlock<>nil) then + begin + FLevel:=Main^.pBlock^.Level; + end; + Write(Space(FLevel+1)); + end; + + Result:=Cursor.Next(FSPI); + if (Result>1) then Exit; + + if Config.PrintAsm then + begin + print_spi(FSPI); + end; + + emit_spi; + + While (CheckBlockBeg) do; + While (CheckBlockEnd) do; + + Result:=0; + if IsFinalize then + begin + Finalize; + Result:=1; + end; + +end; + +function TEmitFlow.ParseStage(base:Pointer):Byte; +begin + Result:=0; + SetPtr(base,btMain); + Main^.pTop^.SetCFGBlock(Cursor.pBlock); + While (CheckBlockBeg) do; + repeat + Result:=NextParse; + Case Result of + 0:; + 1:Break; + else + Break; + end; + until false; +end; + +end. + diff --git a/spirv/srFragLayout.pas b/spirv/srFragLayout.pas index e933cbac..f76d6533 100644 --- a/spirv/srFragLayout.pas +++ b/spirv/srFragLayout.pas @@ -5,16 +5,18 @@ unit srFragLayout; interface uses - sysutils, - spirv, - srNodes, - srReg, - srOp, - srLayout, - srVariable, - srInput, - srCap, - srDecorate; + sysutils, + spirv, + ginodes, + srNode, + srType, + srReg, + srOp, + srLayout, + srVariable, + srInput, + srCapability, + srDecorate; type //itPerspSample, //Sample @@ -24,44 +26,63 @@ type //itLinearCenter, //NoPerspective //itLinearCentroid, //NoPerspective Centroid - PsrFragLayout=^TsrFragLayout; - TsrFragLayout=object(TsrDescriptor) - pLeft,pRight:PsrFragLayout; - //---- - itype:TpsslInputType; - - pReg:PsrRegNode; - - function c(n1,n2:PsrFragLayout):Integer; static; - function GetName:RawByteString; + ntFragLayout=class(ntDescriptor) + class function GetStorageName(node:PsrNode):RawByteString; override; end; + PsrFragLayout=^TsrFragLayout; + TsrFragLayout=object(TsrDescriptor) + private + pLeft,pRight:PsrFragLayout; + //---- + itype:TpsslInputType; + function c(n1,n2:PsrFragLayout):Integer; static; + public + pReg:PsrRegNode; + Procedure Init; inline; + function GetStorageName:RawByteString; + end; + + PsrFragLayoutList=^TsrFragLayoutList; TsrFragLayoutList=object type TNodeFetch=specialize TNodeFetch; var - Alloc:TfnAlloc; + FEmit:TCustomEmit; FNTree:TNodeFetch; - procedure Init(cb:TfnAlloc); - function Fetch(itype:TpsslInputType;location:DWORD):PsrFragLayout; + procedure Init(Emit:TCustomEmit); inline; + function Fetch(itype:TpsslInputType;location:DWORD;rtype:TsrDataType):PsrFragLayout; Function First:PsrFragLayout; Function Next(node:PsrFragLayout):PsrFragLayout; - procedure AllocBinding(Decorates:PsrDecorateList;Cap:PsrCapList); + procedure AllocBinding; procedure AllocEntryPoint(EntryPoint:PSpirvOp); end; implementation +class function ntFragLayout.GetStorageName(node:PsrNode):RawByteString; +begin + Result:=PsrFragLayout(node)^.GetStorageName; +end; + +// + function TsrFragLayout.c(n1,n2:PsrFragLayout):Integer; begin //first itype Result:=Integer(n1^.itype>n2^.itype)-Integer(n1^.itype0) then Exit; //second location Result:=Integer(n1^.FBinding>n2^.FBinding)-Integer(n1^.FBindingnil) do begin pVar:=node^.pVar; - if (pVar<>nil) then + if (pVar<>nil) and node^.IsUsed then begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,node^.FBinding); + pDecorateList^.OpDecorate(pVar,Decoration.Location,node^.FBinding); case node^.itype of itPerspSample: //Sample begin - Cap^.Add(Capability.SampleRateShading); - Decorates^.emit_decorate(ntVar,pVar,Decoration.Sample,0); + pCapabilityList^.Add(Capability.SampleRateShading); + pDecorateList^.OpDecorate(pVar,Decoration.Sample,0); end; itPerspCenter:; //default itPerspCentroid: //Centroid begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.Centroid,0); + pDecorateList^.OpDecorate(pVar,Decoration.Centroid,0); end; itLinearSample: //NoPerspective Sample begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.NoPerspective,0); - Decorates^.emit_decorate(ntVar,pVar,Decoration.Sample,0); + pDecorateList^.OpDecorate(pVar,Decoration.NoPerspective,0); + pDecorateList^.OpDecorate(pVar,Decoration.Sample,0); end; itLinearCenter: //NoPerspective begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.NoPerspective,0); + pDecorateList^.OpDecorate(pVar,Decoration.NoPerspective,0); end; itLinearCentroid: //NoPerspective Centroid begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.NoPerspective,0); - Decorates^.emit_decorate(ntVar,pVar,Decoration.Centroid,0); + pDecorateList^.OpDecorate(pVar,Decoration.NoPerspective,0); + pDecorateList^.OpDecorate(pVar,Decoration.Centroid,0); end; else Assert(false,'AllocBinding'); @@ -172,9 +200,9 @@ begin While (node<>nil) do begin pVar:=node^.pVar; - if (pVar<>nil) then + if (pVar<>nil) and node^.IsUsed then begin - EntryPoint^.AddParam(ntVar,pVar); + EntryPoint^.AddParam(pVar); end; node:=Next(node); end; diff --git a/spirv/srInput.pas b/spirv/srInput.pas index a8335d1a..b44e5ef0 100644 --- a/spirv/srInput.pas +++ b/spirv/srInput.pas @@ -5,15 +5,18 @@ unit srInput; interface uses - typinfo, - sysutils, - spirv, - srNodes, - srReg, - srOp, - srLayout, - srVariable, - srDecorate; + typinfo, + sysutils, + spirv, + ginodes, + srNode, + srType, + srReg, + srOp, + srLayout, + srVariable, + srCapability, + srDecorate; type TpsslInputType=( @@ -42,90 +45,123 @@ type itFloatPos, itFrontFace, - itAncillary, itSampleCoverage, itPosFixed, itTgid, itTgSize, - itThreadId + itThreadId, + // + itSampleId, + itLayer, + + itSubgroupLocalInvocationId ); + ntInput=class(ntDescriptor) + class function GetStorageName(node:PsrNode):RawByteString; override; + end; + PsrInput=^TsrInput; TsrInput=object(TsrDescriptor) - pLeft,pRight:PsrInput; - //---- - - key:packed record - itype:TpsslInputType; - typeid:Byte; - end; - - pReg:PsrRegNode; - - function c(n1,n2:PsrInput):Integer; static; - function GetName:RawByteString; + private + pLeft,pRight:PsrInput; + //---- + key:packed record + itype:TpsslInputType; + typeid:Byte; + end; + function c(n1,n2:PsrInput):Integer; static; + public + pReg:PsrRegNode; + property itype:TpsslInputType read key.itype; + property typeid:Byte read key.typeid; + Procedure Init; inline; + function GetStorageName:RawByteString; end; + PsrInputList=^TsrInputList; TsrInputList=object type TNodeFetch=specialize TNodeFetch; var - Alloc:TfnAlloc; + FEmit:TCustomEmit; FNTree:TNodeFetch; - procedure Init(cb:TfnAlloc); - function Search(itype:TpsslInputType;id:Byte=0):PsrInput; - function Fetch(itype:TpsslInputType;id:Byte=0):PsrInput; + Procedure Init(Emit:TCustomEmit); inline; + function Search(itype:TpsslInputType;id:Byte):PsrInput; + function Fetch(rtype:TsrDataType;itype:TpsslInputType;id:Byte):PsrInput; Function First:PsrInput; Function Next(node:PsrInput):PsrInput; - procedure AllocBinding(Decorates:PsrDecorateList); + procedure AllocBinding; procedure AllocEntryPoint(EntryPoint:PSpirvOp); end; implementation -function TsrInput.c(n1,n2:PsrInput):Integer; +class function ntInput.GetStorageName(node:PsrNode):RawByteString; begin - Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrInput.key)); + Result:=PsrInput(node)^.GetStorageName; end; -function TsrInput.GetName:RawByteString; +// + +function TsrInput.c(n1,n2:PsrInput):Integer; +begin + //first itype + Result:=Integer(n1^.key.itype>n2^.key.itype)-Integer(n1^.key.itype0) then Exit; + //second typeid + Result:=Integer(n1^.key.typeid>n2^.key.typeid)-Integer(n1^.key.typeidnil) do begin pVar:=node^.pVar; - if (pVar<>nil) then + if (pVar<>nil) and node^.IsUsed then begin Case node^.key.itype of itFloatPos: begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.FragCoord); + pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.FragCoord); end; itTgid: begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.WorkgroupId); + pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.WorkgroupId); end; itThreadId: begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.LocalInvocationID); + pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.LocalInvocationID); end; itVIndex: begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.VertexIndex); + pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.VertexIndex); end; itFrontFace: begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.FrontFacing); + pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.FrontFacing); end; + + itLayer: + begin + pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.Layer); + pCapabilityList^.Add(Capability.Geometry); + end; + itSampleId: + begin + pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.SampleId); + end; + else {Assert(false,'AllocBinding')}; end; @@ -192,9 +242,9 @@ begin While (node<>nil) do begin pVar:=node^.pVar; - if (pVar<>nil) then + if (pVar<>nil) and node^.IsUsed then begin - EntryPoint^.AddParam(ntVar,pVar); + EntryPoint^.AddParam(pVar); end; node:=Next(node); end; diff --git a/spirv/srInterface.pas b/spirv/srInterface.pas new file mode 100644 index 00000000..0b7fd3dc --- /dev/null +++ b/spirv/srInterface.pas @@ -0,0 +1,518 @@ +unit srInterface; + +{$mode objfpc}{$H+} + +interface + +uses + ps4_pssl, + spirv, + srNode, + srConfig, + srAllocator, + srCFGCursor, + srRefId, + srLiteral, + srCapability, + srDecorate, + srType, + srTypes, + srConst, + srReg, + srVariable, + srInput, + srOutput, + srLayout, + srVertLayout, + srFragLayout, + srBuffer, + srUniform, + srPrivate, + srBitcast, + srOp, + srOpUtils, + srCacheOp; + +type + TLocalSize=packed record + x,y,z:DWORD; + end; + + TEmitInterface=class(TCustomEmit) + FExecutionModel:Word; + FLocalSize:TLocalSize; + Config:TsrConfig; + // + FSPI:TSPI; + // + Allocator:TsrAllocator; + // + LiteralList :TsrLiteralList; + TypeList :TsrTypeList; + ConstList :TsrConstList; + RegsStory :TsrRegsStory; + CapabilityList:TsrCapabilityList; + HeaderList :TsrHeaderList; + DecorateList :TsrDecorateList; + DebugInfoList :TsrDebugInfoList; + VariableList :TsrVariableList; + // + InputList :TsrInputList; + OutputList :TsrOutputList; + // + DataLayoutList:TsrDataLayoutList; + VertLayoutList:TsrVertLayoutList; + FragLayoutList:TsrFragLayoutList; + // + BufferList :TsrBufferList; + UniformList :TsrUniformList; + PrivateList :TsrPrivateList; + // + BitcastList :TsrBitcastList; + CacheOpList :TsrCacheOpList; + // + FuncList :TsrFuncList; + // + CodeHeap :TsrCodeHeap; + Cursor :TsrCursor; + Main :PSpirvFunc; + InitBlock:PsrOpBlock; + // + RefIdAlloc:TsrRefIdAlloc; + // + function Alloc(Size:ptruint):Pointer; override; + Function GetConfig :Pointer; override; + Function GetCodeHeap :Pointer; override; + + Function GetLiteralList :Pointer; override; + Function GetTypeList :Pointer; override; + Function GetConstList :Pointer; override; + Function GetRegsStory :Pointer; override; + Function GetCapabilityList :Pointer; override; + Function GetHeaderList :Pointer; override; + Function GetDecorateList :Pointer; override; + Function GetDebugInfoList :Pointer; override; + Function GetVariableList :Pointer; override; + Function GetInputList :Pointer; override; + Function GetOutputList :Pointer; override; + Function GetDataLayoutList :Pointer; override; + Function GetVertLayoutList :Pointer; override; + Function GetFragLayoutList :Pointer; override; + Function GetBufferList :Pointer; override; + Function GetUniformList :Pointer; override; + Function GetBitcastList :Pointer; override; + Function GetCacheOpList :Pointer; override; + Function GetFuncList :Pointer; override; + + Function GetCursor :Pointer; override; + + function NewRefNode :PsrNode; override; + // + Function line :PspirvOp; + Function curr_line :Pointer; override; + function init_line :Pointer; override; + // + Procedure InitLists; + // + function NewVariable:Pointer; + // + function _get_line(ppLine:PPspirvOp):PspirvOp; + // + Function NewRegPair:PsrRegPair; + Function NewReg(rtype:TsrDataType):PsrRegNode; + Function NewReg(pConst:PsrConst;ppLine:PPspirvOp=nil):PsrRegNode; + // + Function NewReg_q(dtype:TsrDataType;value:QWORD;ppLine:PPspirvOp=nil):PsrRegNode; + Function NewReg_b(value:Boolean;ppLine:PPspirvOp=nil):PsrRegNode; + Function NewReg_i(dtype:TsrDataType;value:Integer;ppLine:PPspirvOp=nil):PsrRegNode; + Function NewReg_s(dtype:TsrDataType;value:Single;ppLine:PPspirvOp=nil):PsrRegNode; + // + function NewSpirvOp(OpId:DWORD):PSpirvOp; + function NewLabelOp(sdep:Boolean):PSpirvOp; + function AddSpirvOp(OpId:DWORD):PSpirvOp; + function AddSpirvOp(pLine:PspirvOp;OpId:DWORD):PSpirvOp; + function AddSpirvOp(pLine,pNew:PspirvOp):PSpirvOp; + function AddSGlslOp(pLine:PspirvOp;OpId:DWORD):PSpirvOp; + // + procedure PostLink(pLine,dst:PsrNode); override; + procedure MakeCopy(dst:PsrRegSlot;src:PsrRegNode); + // + Procedure SetConst(pSlot:PsrRegSlot;pConst:PsrConst); + Procedure SetConst_q(pSlot:PsrRegSlot;dtype:TsrDataType;value:QWORD); + Procedure SetConst_b(pSlot:PsrRegSlot;value:Boolean); + Procedure SetConst_i(pSlot:PsrRegSlot;dtype:TsrDataType;value:Integer); + Procedure SetConst_s(pSlot:PsrRegSlot;dtype:TsrDataType;value:Single); + // + function AllocBlockOp:PsrOpBlock; + function NewBlockOp(Snap:TsrRegsSnapshot):PsrOpBlock; + function InsertBlockOp(pLine:PspirvOp;pChild:PsrOpBlock):PspirvOp; + // + procedure AddCapability(ID:DWORD); + end; + +implementation + +function TEmitInterface.Alloc(Size:ptruint):Pointer; +begin + Result:=Allocator.Alloc(Size); +end; + +Function TEmitInterface.GetConfig:Pointer; +begin + Result:=@Config; +end; + +Function TEmitInterface.GetCodeHeap:Pointer; +begin + Result:=@CodeHeap; +end; + +Function TEmitInterface.GetLiteralList:Pointer; +begin + Result:=@LiteralList; +end; + +Function TEmitInterface.GetTypeList:Pointer; +begin + Result:=@TypeList; +end; + +Function TEmitInterface.GetConstList:Pointer; +begin + Result:=@ConstList; +end; + +Function TEmitInterface.GetRegsStory:Pointer; +begin + Result:=@RegsStory; +end; + +Function TEmitInterface.GetCapabilityList:Pointer; +begin + Result:=@CapabilityList; +end; + +Function TEmitInterface.GetHeaderList:Pointer; +begin + Result:=@HeaderList; +end; + +Function TEmitInterface.GetDecorateList:Pointer; +begin + Result:=@DecorateList; +end; + +Function TEmitInterface.GetDebugInfoList:Pointer; +begin + Result:=@DebugInfoList; +end; + +Function TEmitInterface.GetVariableList:Pointer; +begin + Result:=@VariableList; +end; + +Function TEmitInterface.GetInputList:Pointer; +begin + Result:=@InputList; +end; + +Function TEmitInterface.GetOutputList:Pointer; +begin + Result:=@OutputList; +end; + +Function TEmitInterface.GetDataLayoutList:Pointer; +begin + Result:=@DataLayoutList; +end; + +Function TEmitInterface.GetVertLayoutList:Pointer; +begin + Result:=@VertLayoutList; +end; + +Function TEmitInterface.GetFragLayoutList:Pointer; +begin + Result:=@FragLayoutList; +end; + +Function TEmitInterface.GetBufferList:Pointer; +begin + Result:=@BufferList; +end; + +Function TEmitInterface.GetUniformList:Pointer; +begin + Result:=@UniformList; +end; + +Function TEmitInterface.GetBitcastList:Pointer; +begin + Result:=@BitcastList; +end; + +Function TEmitInterface.GetCacheOpList:Pointer; +begin + Result:=@CacheOpList; +end; + +Function TEmitInterface.GetFuncList:Pointer; +begin + Result:=@FuncList; +end; + +Function TEmitInterface.GetCursor:Pointer; +begin + Result:=@Cursor; +end; + +// + +function TEmitInterface.NewRefNode:PsrNode; +begin + Result:=Alloc(SizeOf(TsrRefNode)); + PsrRefNode(Result)^.Init; +end; + +Function TEmitInterface.line:PspirvOp; +begin + Result:=nil; + if (Main<>nil) then + begin + Result:=Main^.line; + end; +end; + +function TEmitInterface.curr_line:Pointer; +begin + Result:=line; +end; + +function TEmitInterface.init_line:Pointer; +begin + Assert(InitBlock<>nil); + if (InitBlock^.dummy.Parent=nil) then //is not init? + begin + InitBlock^.Init(Self); + end; + Result:=InitBlock^.line; + Assert(Result<>nil); +end; + +Procedure TEmitInterface.InitLists; +begin + Config.Init; + + LiteralList .Init(Self); + TypeList .Init(Self); + ConstList .Init(Self); + RegsStory .Init(Self); + CapabilityList.Init(Self); + HeaderList .Init(Self); + DecorateList .Init(Self); + DebugInfoList .Init(Self); + VariableList .Init(Self); + InputList .Init(Self); + OutputList .Init(Self); + DataLayoutList.Init(Self); + VertLayoutList.Init(Self); + FragLayoutList.Init(Self); + BufferList .Init(Self); + UniformList .Init(Self); + PrivateList .Init(Self); + BitcastList .Init(Self); + CacheOpList .Init(Self); +end; + +function TEmitInterface.NewVariable:Pointer; +begin + Result:=VariableList.Fetch; +end; + +// + +function TEmitInterface._get_line(ppLine:PPspirvOp):PspirvOp; +begin + if (ppLine=nil) then Exit(line); + if (ppLine^=nil) then Exit(line); + Result:=ppLine^; +end; + +// + +Function TEmitInterface.NewRegPair:PsrRegPair; +begin + Result:=Alloc(SizeOf(TsrRegPair)); + Result^.Init; +end; + +Function TEmitInterface.NewReg(rtype:TsrDataType):PsrRegNode; +begin + Result:=RegsStory.FUnattach.New(line,rtype); +end; + +Function TEmitInterface.NewReg(pConst:PsrConst;ppLine:PPspirvOp=nil):PsrRegNode; +begin + if (pConst=nil) then Exit(nil); + Result:=NewReg(pConst^.dtype); + Result^.pWriter:=pConst; + Result^.pLine:=_get_line(ppLine); +end; + +// + +Function TEmitInterface.NewReg_q(dtype:TsrDataType;value:QWORD;ppLine:PPspirvOp=nil):PsrRegNode; +begin + Result:=NewReg(ConstList.Fetch(dtype,value),ppLine); +end; + +Function TEmitInterface.NewReg_b(value:Boolean;ppLine:PPspirvOp=nil):PsrRegNode; +begin + Result:=NewReg(ConstList.Fetch_b(value),ppLine); +end; + +Function TEmitInterface.NewReg_i(dtype:TsrDataType;value:Integer;ppLine:PPspirvOp=nil):PsrRegNode; +begin + Result:=NewReg(ConstList.Fetch_i(dtype,value),ppLine); +end; + +Function TEmitInterface.NewReg_s(dtype:TsrDataType;value:Single;ppLine:PPspirvOp=nil):PsrRegNode; +begin + Result:=NewReg(ConstList.Fetch_s(dtype,value),ppLine); +end; + +function TEmitInterface.NewSpirvOp(OpId:DWORD):PSpirvOp; +begin + Result:=Alloc(SizeOf(TSpirvOp)); + Result^.Init(OpId); + Result^.adr:=Cursor.Adr; +end; + +function TEmitInterface.NewLabelOp(sdep:Boolean):PSpirvOp; +Var + node:PSpirvOp; +begin + node:=NewSpirvOp(Op.OpLabel); + node^.pDst:=NewRefNode; + Result:=node; + if sdep then node^.pDst^.mark_read(nil); +end; + +function TEmitInterface.AddSpirvOp(OpId:DWORD):PSpirvOp; +begin + Result:=AddSpirvOp(line,OpId); +end; + +function TEmitInterface.AddSpirvOp(pLine:PspirvOp;OpId:DWORD):PSpirvOp; +begin + Result:=InsSpirvOp(pLine,NewSpirvOp(OpId)); +end; + +function TEmitInterface.AddSpirvOp(pLine,pNew:PspirvOp):PSpirvOp; +begin + Result:=InsSpirvOp(pLine,pNew); +end; + +function TEmitInterface.AddSGlslOp(pLine:PspirvOp;OpId:DWORD):PSpirvOp; +var + ext,node:PSpirvOp; +begin + ext:=HeaderList.emit_glsl_ext; + node:=AddSpirvOp(pLine,Op.OpExtInst); + node^.AddParam(ext^.pDst); + node^.AddLiteral(OpId,GlslOp.GetStr(OpId)); + Result:=node; +end; + +procedure TEmitInterface.PostLink(pLine,dst:PsrNode); +var + node:PspirvOp; +begin + node:=pLine^.AsType(ntOpCustom); + Assert(node<>nil); + + if node^.IsType(ntOp) then + if (node^.OpId=Op.OpNop) then + begin + node^.AddParam(dst); + Exit; + end; + + node:=AddSpirvOp(node,Op.OpNop); + node^.AddParam(dst); + node^.mark_not_used; +end; + +procedure TEmitInterface.MakeCopy(dst:PsrRegSlot;src:PsrRegNode); +var + node:PsrRegNode; +begin + node:=dst^.New(line,src^.dtype); + node^.pWriter:=src; + + PostLink(line,node); //post processing +end; + +Procedure TEmitInterface.SetConst(pSlot:PsrRegSlot;pConst:PsrConst); +var + dst:PsrRegNode; +begin + dst:=pSlot^.New(line,pConst^.dtype); + dst^.pWriter:=pConst; + + PostLink(line,dst); //post processing +end; + +Procedure TEmitInterface.SetConst_q(pSlot:PsrRegSlot;dtype:TsrDataType;value:QWORD); +begin + SetConst(pSlot,ConstList.Fetch(dtype,value)); +end; + +Procedure TEmitInterface.SetConst_b(pSlot:PsrRegSlot;value:Boolean); +begin + SetConst(pSlot,ConstList.Fetch_b(value)); +end; + +Procedure TEmitInterface.SetConst_i(pSlot:PsrRegSlot;dtype:TsrDataType;value:Integer); +begin + SetConst(pSlot,ConstList.Fetch_i(dtype,value)); +end; + +Procedure TEmitInterface.SetConst_s(pSlot:PsrRegSlot;dtype:TsrDataType;value:Single); +begin + SetConst(pSlot,ConstList.Fetch_s(dtype,value)); +end; + +function TEmitInterface.AllocBlockOp:PsrOpBlock; +begin + Result:=Alloc(SizeOf(TsrOpBlock)); + Result^.Init(Self); +end; + +function TEmitInterface.NewBlockOp(Snap:TsrRegsSnapshot):PsrOpBlock; +begin + Result:=AllocBlockOp; + Result^.Regs.pSnap :=Alloc(SizeOf(TsrRegsSnapshot)); + Result^.Regs.pSnap^:=Snap; + Result^.Regs.FVolMark:=vmNone; + Result^.Cond.FUseCont:=false; +end; + +function TEmitInterface.InsertBlockOp(pLine:PspirvOp;pChild:PsrOpBlock):PspirvOp; +begin + pLine:=InsSpirvOp(pLine,PspirvOp(pChild)); + pChild^.UpdateLevel; + Result:=pLine; +end; + +// + +procedure TEmitInterface.AddCapability(ID:DWORD); +begin + CapabilityList.Add(ID); +end; + +end. + + diff --git a/spirv/srLayout.pas b/spirv/srLayout.pas index 447a7352..e0a8ba0c 100644 --- a/spirv/srLayout.pas +++ b/spirv/srLayout.pas @@ -5,18 +5,25 @@ unit srLayout; interface uses - ps4_shader, - srNodes, - srParser, - srCFG, - srTypes, - srReg, - srVariable, - srRefId, - srDecorate; + sysutils, + ps4_shader, + spirv, + ginodes, + srNode, + srCFGParser, + srCFGCursor, + srType, + srTypes, + srReg, + srOp, + srVariable, + srBitcast, + srRefId, + srDecorate; type TsrResourceType=( + rtRoot, rtBufPtr2, rtFunPtr2, rtVSharp4, @@ -26,41 +33,82 @@ type ); type + ntChain=class(TsrNodeVmt) + class Procedure zero_read (node:PsrNode); override; + class Procedure zero_unread (node:PsrNode); override; + class Function pwrite_count(node:PsrNode):PDWORD; override; + class function Next (node:PsrNode):Pointer; override; + class function Prev (node:PsrNode):Pointer; override; + class function Parent (node:PsrNode):Pointer; override; + class Procedure PrepType (node:PPrepTypeNode); override; + class function GetPrintName(node:PsrNode):RawByteString; override; + class function GetRef (node:PsrNode):Pointer; override; + end; + PsrDataLayout=^TsrDataLayout; - PsrChainExt=^TsrChainExt; - TsrChainExt=object + PsrChainLvl_1=^TsrChainLvl_1; + TsrChainLvl_1=object pIndex:PsrRegNode; stride:PtrUint; - function c(n1,n2:PsrChainExt):Integer; static; + function c(n1,n2:PsrChainLvl_1):Integer; static; + end; + + PsrChainLvl_0=^TsrChainLvl_0; + TsrChainLvl_0=object + size :PtrUint; + offset:PtrUint; + function c(n1,n2:PsrChainLvl_0):Integer; static; end; PsrChain=^TsrChain; - TsrChain=object - pLeft,pRight:PsrChain; - //---- - read_count:DWORD; - write_count:DWORD; - parent:PsrDataLayout; - key:packed record - ext:TsrChainExt; - size,offset:PtrUint; - end; - rSlot:TsrRegSlot; - pField:Pointer; - pLine:Pointer; - ID:TsrRefId; //post id - function c(n1,n2:PsrChain):Integer; static; - Procedure mark_read; - Procedure mark_unread; - Procedure mark_write; - Procedure SetRegType(rtype:TsrDataType); - function GetRegType:TsrDataType; - function IsUsed:Boolean; + TsrChain=object(TsrNode) + type + PVNode=^TVNode; + TVNode=record + pPrev,pNext:PVNode; + pLine:PspirvOp; + end; + TNodeList=specialize TNodeList; + private + pLeft,pRight:PsrChain; + //-- + fwrite_count:DWORD; + //-- + ID:TsrRefId; //post id + FParent:PsrDataLayout; + key:packed record + lvl_1:TsrChainLvl_1; + lvl_0:TsrChainLvl_0; + end; + Fdtype:TsrDataType; + FList:TNodeList; + function c(n1,n2:PsrChain):Integer; static; + Procedure SetRegType(rtype:TsrDataType); + public + pField:Pointer; + //pLine:Pointer; + property Parent:PsrDataLayout read FParent; + property pIndex:PsrRegNode read key.lvl_1.pIndex; + property stride:PtrUint read key.lvl_1.stride; + property size :PtrUint read key.lvl_0.size; + property offset:PtrUint read key.lvl_0.offset; + property dtype:TsrDataType read Fdtype write SetRegType; + Procedure Init(L:PsrDataLayout); + function Emit:TCustomEmit; + Procedure UpdateRegType; + Procedure PrepType(new:TsrDataType); + procedure AddLine(pLine:PspirvOp); + function FirstLine:PspirvOp; + procedure FetchLoad(pLine:PspirvOp;dst:PsrRegNode); + Procedure FetchStore(pLine:PspirvOp;src:PsrRegNode); + function GetPrintName:RawByteString; end; TsrChains=array[0..7] of PsrChain; + TChainCb=function(node:PsrChain):Integer of object; + //---- TsrDataLayout=object @@ -76,45 +124,65 @@ type end; pData:Pointer; FID:Integer; - Alloc:TfnAlloc; + FEmit:TCustomEmit; FList:TChainFetch; function c(n1,n2:PsrDataLayout):Integer; static; - function Fetch(o,s:PtrUint;ext:PsrChainExt):PsrChain; + function Fetch(lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrChain; Function First:PsrChain; Function Last:PsrChain; - Function Next(node:PsrChain):PsrChain; - Function Prev(node:PsrChain):PsrChain; + Function NextChain(node:PsrChain):PsrChain; + Function PrevChain(node:PsrChain):PsrChain; + function EnumChain(cb:TChainCb):Integer; function GetData:Pointer; + function IsUserData:Boolean; inline; function GetStride:PtrUint; function GetTypeChar:Char; function GetString:RawByteString; function GetFuncString(LEN:DWORD):RawByteString; end; + PsrDataLayoutList=^TsrDataLayoutList; TsrDataLayoutList=object type TNodeFetch=specialize TNodeFetch; var FTop:TsrDataLayout; FNTree:TNodeFetch; - procedure Init(cb:TfnAlloc); + procedure Init(Emit:TCustomEmit); procedure SetUserData(pData:Pointer); + function pRoot:PsrDataLayout; function Fetch(p:PsrDataLayout;o:PtrUint;t:TsrResourceType):PsrDataLayout; Function First:PsrDataLayout; Function Next(node:PsrDataLayout):PsrDataLayout; function Grouping(const chain:TsrChains;rtype:TsrResourceType):PsrDataLayout; + function EnumChain(cb:TChainCb):Integer; Procedure AllocID; - procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList); - procedure AllocFuncExt(FDebugInfo:PsrDebugInfoList;var Heap:TsrCodeHeap); + procedure AllocSourceExtension; + procedure AllocFuncExt; end; //---- + ntDescriptor=class(TsrNodeVmt) + class Procedure zero_read (node:PsrNode); override; + class Procedure zero_unread (node:PsrNode); override; + class Function GetPtype (node:PsrNode):PsrNode; override; + class Function GetStorageClass(node:PsrNode):DWORD; override; + end; + PsrDescriptor=^TsrDescriptor; - TsrDescriptor=object - pVar:PsrVariable; - FStorage:DWORD; - FBinding:Integer; + TsrDescriptor=packed object(TsrNode) + protected + FVar:PsrVariable; + FType:PsrType; + FStorage:DWORD; + FBinding:Integer; + procedure InitVar(Emit:TCustomEmit); + procedure InitType(rtype:TsrDataType;Emit:TCustomEmit); + procedure SetType(t:PsrType); + public + property pVar:PsrVariable read FVar; + property pType:PsrType read FType write SetType; end; function is_consistents(const chains:TsrChains;count:Byte):Boolean; @@ -124,6 +192,88 @@ function GetResourceSizeDw(r:TsrResourceType):Byte; implementation +class Procedure ntChain.zero_read(node:PsrNode); +begin + With PsrChain(node)^ do + begin + key.lvl_1.pIndex^.mark_read(node); + end; +end; + +class Procedure ntChain.zero_unread(node:PsrNode); +begin + With PsrChain(node)^ do + begin + key.lvl_1.pIndex^.mark_unread(node); + end; +end; + +class Function ntChain.pwrite_count(node:PsrNode):PDWORD; +begin + Result:=@PsrChain(node)^.fwrite_count; +end; + +class function ntChain.Next(node:PsrNode):Pointer; +begin + Result:=PsrChain(node)^.FParent^.NextChain(PsrChain(node)); +end; + +class function ntChain.Prev(node:PsrNode):Pointer; +begin + Result:=PsrChain(node)^.FParent^.PrevChain(PsrChain(node)); +end; + +class function ntChain.Parent(node:PsrNode):Pointer; +begin + Result:=PsrChain(node)^.FParent; +end; + +class Procedure ntChain.PrepType(node:PPrepTypeNode); +begin + PsrChain(node^.dnode)^.PrepType(TsrDataType(node^.rtype)); + node^.dnode:=nil; +end; + +class function ntChain.GetPrintName(node:PsrNode):RawByteString; +begin + Result:=PsrChain(node)^.GetPrintName; +end; + +class function ntChain.GetRef(node:PsrNode):Pointer; +begin + Result:=@PsrChain(node)^.ID; +end; + +// + +class Procedure ntDescriptor.zero_read(node:PsrNode); +begin + With PsrDescriptor(node)^ do + begin + pType^.mark_read(node); + end; +end; + +class Procedure ntDescriptor.zero_unread(node:PsrNode); +begin + With PsrDescriptor(node)^ do + begin + pType^.mark_unread(node); + end; +end; + +class Function ntDescriptor.GetPtype(node:PsrNode):PsrNode; +begin + Result:=PsrDescriptor(node)^.FType; +end; + +class Function ntDescriptor.GetStorageClass(node:PsrNode):DWORD; +begin + Result:=PsrDescriptor(node)^.FStorage; +end; + +// + function TsrDataLayout.c(n1,n2:PsrDataLayout):Integer; begin //first parent @@ -136,37 +286,29 @@ begin Result:=Integer(n1^.key.rtype>n2^.key.rtype)-Integer(n1^.key.rtypenil) then + if (lvl_0<>nil) then begin - node.key.ext:=ext^; + node.key.lvl_0:=lvl_0^; end; + if (lvl_1<>nil) then + begin + node.key.lvl_1:=lvl_1^; + end; + Result:=FList.Find(@node); if (Result=nil) then begin - Result:=Alloc(SizeOf(TsrChain)); - Result^.parent:=@Self; - Result^.key.offset:=o; - Result^.key.size :=s; - if (ext<>nil) then - begin - Result^.key.ext:=ext^; - end; - Result^.rSlot.Init(Alloc,'CHAIN'); + Result:=FEmit.Alloc(SizeOf(TsrChain)); + Move(node,Result^,SizeOf(TsrChain)); + + Result^.Init(@Self); + FList.Insert(Result); - end else - begin - if (ext<>nil) then - if (ext^.pIndex<>nil) then - begin - ext^.pIndex^.mark_unread; - end; end; end; @@ -180,21 +322,38 @@ begin Result:=FList.Max; end; -Function TsrDataLayout.Next(node:PsrChain):PsrChain; +Function TsrDataLayout.NextChain(node:PsrChain):PsrChain; begin Result:=FList.Next(node); end; -Function TsrDataLayout.Prev(node:PsrChain):PsrChain; +Function TsrDataLayout.PrevChain(node:PsrChain):PsrChain; begin Result:=FList.Prev(node); end; +function TsrDataLayout.EnumChain(cb:TChainCb):Integer; +var + node:PsrChain; +begin + Result:=0; + node:=First; + While (node<>nil) do + begin + if node^.IsUsed then + begin + Result:=Result+cb(node); + end; + node:=node^.Next; + end; +end; + function TsrDataLayout.GetData:Pointer; begin Result:=nil; if (pData<>nil) then Case key.rtype of + rtRoot, rtBufPtr2, rtFunPtr2:Result:=pData; rtVSharp4:Result:={%H-}Pointer(PVSharpResource4(pData)^.base); @@ -209,16 +368,23 @@ begin Result:=0; if (pData<>nil) then Case key.rtype of + rtRoot, rtBufPtr2:Result:=4; rtVSharp4:Result:=PVSharpResource4(pData)^.stride; else; end; end; +function TsrDataLayout.IsUserData:Boolean; inline; +begin + Result:=(key.rtype=rtRoot); +end; + function TsrDataLayout.GetTypeChar:Char; begin Result:=#0; case key.rtype of + rtRoot :Result:='R'; rtBufPtr2:Result:='B'; rtFunPtr2:Result:='F'; rtVSharp4:Result:='V'; @@ -249,9 +415,9 @@ begin ';LEN='+HexStr(LEN,8); end; -procedure TsrDataLayoutList.Init(cb:TfnAlloc); +procedure TsrDataLayoutList.Init(Emit:TCustomEmit); begin - FTop.Alloc:=cb; + FTop.FEmit:=Emit; FNTree.Insert(@FTop); end; @@ -260,38 +426,42 @@ begin FTop.pData:=pData; end; +function TsrDataLayoutList.pRoot:PsrDataLayout; +begin + Result:=@FTop; +end; + function TsrDataLayoutList.Fetch(p:PsrDataLayout;o:PtrUint;t:TsrResourceType):PsrDataLayout; var node:TsrDataLayout; pData:Pointer; begin + Assert(p<>nil); node:=Default(TsrDataLayout); - node.Alloc:=FTop.Alloc; + node.FEmit:=FTop.FEmit; node.key.parent:=p; node.key.offset:=o; node.key.rtype :=t; Result:=FNTree.Find(@node); if (Result=nil) then begin - Result:=FTop.Alloc(SizeOf(TsrDataLayout)); + Result:=FTop.FEmit.Alloc(SizeOf(TsrDataLayout)); Move(node,Result^,SizeOf(TsrDataLayout)); FNTree.Insert(Result); Result^.FID:=-1; - if (p<>nil) then - begin - pData:=p^.GetData; - if (pData<>nil) then - case t of - rtBufPtr2, - rtFunPtr2:Result^.pData:={%H-}Pointer(PPtrUint(pData+o)^ and (not 3)); - rtVSharp4, - rtSSharp4, - rtTSharp4, - rtTSharp8:Result^.pData:=pData+o; - end; - end; + pData:=p^.GetData; + if (pData<>nil) then + case t of + rtRoot, + rtBufPtr2, + rtFunPtr2:Result^.pData:={%H-}Pointer(PPtrUint(pData+o)^ and (not 3)); + rtVSharp4, + rtSSharp4, + rtTSharp4, + rtTSharp8:Result^.pData:=pData+o; + end; end; end; @@ -310,6 +480,7 @@ function GetResourceSizeDw(r:TsrResourceType):Byte; begin Result:=0; Case r of + rtRoot :Result:=2; rtBufPtr2:Result:=2; rtFunPtr2:Result:=2; rtVSharp4:Result:=4; @@ -333,7 +504,21 @@ begin Assert(False,'indexed chain not support'); end; - Result:=Fetch(chain[0]^.parent,chain[0]^.key.offset,rtype); + Result:=Fetch(chain[0]^.Parent,chain[0]^.offset,rtype); +end; + +function TsrDataLayoutList.EnumChain(cb:TChainCb):Integer; +var + node:PsrDataLayout; +begin + Result:=0; + if (cb=nil) then Exit; + node:=First; + While (node<>nil) do + begin + Result:=Result+node^.EnumChain(cb); + node:=Next(node); + end; end; Procedure TsrDataLayoutList.AllocID; @@ -354,40 +539,53 @@ begin end; end; -procedure TsrDataLayoutList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList); +procedure TsrDataLayoutList.AllocSourceExtension; var + pDebugInfoList:PsrDebugInfoList; node:PsrDataLayout; begin - if (FDebugInfo=nil) then Exit; + pDebugInfoList:=FTop.FEmit.GetDebugInfoList; node:=First; While (node<>nil) do begin - FDebugInfo^.emit_source_extension(node^.GetString); + pDebugInfoList^.OpSourceExtension(node^.GetString); node:=Next(node); end; end; -procedure TsrDataLayoutList.AllocFuncExt(FDebugInfo:PsrDebugInfoList;var Heap:TsrCodeHeap); +procedure TsrDataLayoutList.AllocFuncExt; var + pDebugInfoList:PsrDebugInfoList; + pHeap:PsrCodeHeap; node:PsrDataLayout; block:PsrCodeBlock; begin + pDebugInfoList:=FTop.FEmit.GetDebugInfoList; + pHeap:=FTop.FEmit.GetCodeHeap; node:=First; While (node<>nil) do begin if (node^.key.rtype=rtFunPtr2) then begin - block:=Heap.FindByPtr(node^.pData); + block:=pHeap^.FindByPtr(node^.pData); if (block<>nil) then begin - FDebugInfo^.emit_source_extension(node^.GetFuncString(block^.Size)); + pDebugInfoList^.OpSourceExtension(node^.GetFuncString(block^.Size)); end; end; node:=Next(node); end; end; -function TsrChainExt.c(n1,n2:PsrChainExt):Integer; +// + +Procedure TsrChain.Init(L:PsrDataLayout); +begin + fntype:=ntChain; + FParent:=L; +end; + +function TsrChainLvl_1.c(n1,n2:PsrChainLvl_1):Integer; begin //first pIndex forward Result:=Integer(n1^.pIndex>n2^.pIndex)-Integer(n1^.pIndexn2^.stride)-Integer(n1^.striden2^.size); + if (Result<>0) then Exit; + + //second offset forward + Result:=Integer(n1^.offset>n2^.offset)-Integer(n1^.offset0) then Exit; - //second size backward - Result:=Integer(n1^.key.sizen2^.key.size); - if (Result<>0) then Exit; - - //third offset forward - Result:=Integer(n1^.key.offset>n2^.key.offset)-Integer(n1^.key.offset0) then Dec(read_count); -end; - -Procedure TsrChain.mark_write; -begin - Inc(write_count); + Result:=FParent^.FEmit; end; Procedure TsrChain.SetRegType(rtype:TsrDataType); var - node:PsrRegNode; + pTypeList:PsrTypeList; + FType:PsrType; + node:PVNode; + pLine:PspirvOp; begin - node:=rSlot.pStory.pHead; + Fdtype:=rtype; + + pTypeList:=Emit.GetTypeList; + FType:=pTypeList^.Fetch(rtype); + + node:=FList.pHead; While (node<>nil) do begin - node^.dtype:=rtype; + pLine:=node^.pLine; + + Case pLine^.OpId of + + Op.OpLoad: + begin + pLine^.pDst^.PrepType(ord(rtype)); + pLine^.pType:=Ftype; + end; + + Op.OpStore: + begin + pLine^.ParamFirst^.Value^.PrepType(ord(rtype)); + end; + + else; + end; + node:=node^.pNext; end; end; -function TsrChain.GetRegType:TsrDataType; +Procedure TsrChain.UpdateRegType; var - pReg:PsrRegNode; + pTypeList:PsrTypeList; + pBitcastList:PsrBitcastList; + FType:PsrType; + node:PVNode; + pLine:PspirvOp; + dst:PsrRegNode; + old,rtype:TsrDataType; begin - Result:=dtUnknow; - pReg:=rSlot.current; - if (pReg=nil) then Exit; - Result:=pReg^.dtype; + rtype:=Fdtype; + + pTypeList:=Emit.GetTypeList; + FType:=pTypeList^.Fetch(rtype); + + pBitcastList:=Emit.GetBitcastList; + + node:=FList.pHead; + While (node<>nil) do + begin + pLine:=node^.pLine; + + Case pLine^.OpId of + + Op.OpLoad: + begin + pLine^.pDst^.PrepType(ord(rtype)); + pLine^.pType:=Ftype; + + dst:=pLine^.pDst^.AsType(ntReg); + if (dst<>nil) then + begin + old:=dst^.dtype; + if (old<>dtUnknow) and (not CompareType(rtype,old)) then + begin + //OpLoad -> new -> dst + pBitcastList:=Emit.GetBitcastList; + dst:=pBitcastList^.FetchDstr(rtype,dst); + pLine^.pDst:=dst; + end; + end; + end; + + Op.OpStore: + begin + pLine^.ParamFirst^.Value^.PrepType(ord(rtype)); + + dst:=pLine^.ParamFirst^.Value^.AsType(ntReg); + if (dst<>nil) then + begin + old:=dst^.dtype; + if (old<>dtUnknow) and (rtype<>old) then + begin + //OpStore <- new <- dst + pBitcastList:=Emit.GetBitcastList; + dst:=pBitcastList^.FetchRead(rtype,dst); + pLine^.ParamFirst^.Value:=dst; + end; + end; + end; + + else; + end; + + node:=node^.pNext; + end; end; -function TsrChain.IsUsed:Boolean; +Procedure TsrChain.PrepType(new:TsrDataType); +var + old:TsrDataType; begin - Result:=((read_count<>0) or - (write_count<>0)) and - (rSlot.current<>nil); + if (new=dtUnknow) then Exit; + old:=Fdtype; + if is_unprep_type(old,new,True) then + begin + old:=StoreType(new); + SetRegType(old); + end; +end; + +procedure TsrChain.AddLine(pLine:PspirvOp); +var + node:PVNode; +begin + node:=Emit.Alloc(SizeOf(TVNode)); + node^.pLine:=pLine; + FList.Push_tail(node); +end; + +function TsrChain.FirstLine:PspirvOp; +var + node:PVNode; +begin + Result:=nil; + node:=FList.pHead; + if (node<>nil) then + begin + Result:=node^.pLine; + end; +end; + +procedure TsrChain.FetchLoad(pLine:PspirvOp;dst:PsrRegNode); +var + pTypeList:PsrTypeList; +begin + Assert(dst<>nil); + + PrepType(dst^.dtype); + + pTypeList:=Emit.GetTypeList; + pLine:=PspirvOp(Emit.OpLoad(pLine,pTypeList^.Fetch(Fdtype),dst,@Self)); + + AddLine(pLine); +end; + +Procedure TsrChain.FetchStore(pLine:PspirvOp;src:PsrRegNode); +begin + if (src=nil) then Exit; + + PrepType(src^.dtype); + + pLine:=PspirvOp(Emit.OpStore(pLine,@Self,src)); + + AddLine(pLine); +end; + +function TsrChain.GetPrintName:RawByteString; +begin + Assert(ID.Alloc); + Result:='ac'+IntToStr(ID.ID); +end; + +// + +procedure TsrDescriptor.InitVar(Emit:TCustomEmit); +var + pVariableList:PsrVariableList; +begin + if (Emit=nil) then Exit; + if (FVar<>nil) then Exit; + // + pVariableList:=Emit.GetVariableList; + // + FVar:=pVariableList^.Fetch; + FVar^.pSource:=@Self; +end; + +procedure TsrDescriptor.InitType(rtype:TsrDataType;Emit:TCustomEmit); +var + pTypeList:PsrTypeList; +begin + if (Emit=nil) then Exit; + if (FType<>nil) then Exit; + // + pTypeList:=Emit.GetTypeList; + // + SetType(pTypeList^.Fetch(rtype)); +end; + +procedure TsrDescriptor.SetType(t:PsrType); +begin + if (FType=t) then Exit; + if not IsUsed then + begin + t^.mark_read (@Self); + FType^.mark_unread(@Self); + end; + FType:=t; end; function is_consistents(const chains:TsrChains;count:Byte):Boolean; @@ -467,14 +840,14 @@ begin Result:=False; if (chains[0]=nil) then Exit; parent:=chains[0]^.parent; - offset:=chains[0]^.key.offset; + offset:=chains[0]^.offset; For i:=1 to count-1 do begin - t:=chains[i-1]^.key.size; + t:=chains[i-1]^.size; offset:=offset+t; if (chains[i]=nil) then Exit; if (chains[i]^.parent<>parent) then Exit; - t:=chains[i]^.key.offset; + t:=chains[i]^.offset; if (offset<>t) then Exit; end; Result:=True; @@ -489,7 +862,7 @@ begin For i:=0 to count-1 do begin if (chains[i]=nil) then Exit; - if (chains[i]^.key.ext.pIndex<>nil) then Exit; + if (chains[i]^.key.lvl_1.pIndex<>nil) then Exit; end; Result:=True; end; diff --git a/spirv/srLiteral.pas b/spirv/srLiteral.pas new file mode 100644 index 00000000..7145db98 --- /dev/null +++ b/spirv/srLiteral.pas @@ -0,0 +1,443 @@ +unit srLiteral; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + half16, + srType, + ginodes, + srNode; + +type + ntLiteral=class(TsrNodeVmt) + class function GetPrintData(node:PsrNode):RawByteString; override; + class function GetData(node:PsrNode;data:Pointer):Ptruint; override; + end; + + ntLiteralString=class(ntLiteral) + class function GetPrintData(node:PsrNode):RawByteString; override; + class function GetData(node:PsrNode;data:Pointer):Ptruint; override; + end; + + ntLiteralConst=class(ntLiteral) + class function GetPrintData(node:PsrNode):RawByteString; override; + class function GetData(node:PsrNode;data:Pointer):Ptruint; override; + end; + + PsrLiteral=^TsrLiteral; + TsrLiteral=object(TsrNode) + private + pLeft,pRight:PsrLiteral; + public + dtype:TsrDataType; + Value:PtrUint; + name:PChar; + function c(n1,n2:PsrLiteral):Integer; static; + Procedure Init; inline; + Function AsBool:Boolean; inline; + Function AsUint8:Byte; inline; + Function AsInt8:Shortint; inline; + Function AsUint16:Word; inline; + Function AsInt16:Smallint; inline; + Function AsUint32:DWORD; inline; + function AsInt32:Integer; inline; + Function AsUint64:QWORD; inline; + Function AsInt64:Int64; inline; + Function AsHalf16:THalf16; inline; + Function AsFloat32:Single; inline; + Function AsFloat64:Double; inline; + Function GetPrintData:RawByteString; + Function GetData(data:Pointer):Ptruint; + end; + + PsrLiteralString=^TsrLiteralString; + TsrLiteralString=object(TsrLiteral) + Procedure Init; inline; + Function GetPrintData:RawByteString; + Function GetData(data:Pointer):Ptruint; + end; + + PsrLiteralConst=^TsrLiteralConst; + TsrLiteralConst=object(TsrLiteral) + Procedure Init; inline; + Function GetPrintData:RawByteString; + Function GetData(data:Pointer):Ptruint; + end; + + PsrLiteralList=^TsrLiteralList; + TsrLiteralList=object + type + TNodeFetch=specialize TNodeFetch; + var + FEmit:TCustomEmit; + FNTree:TNodeFetch; + Procedure Init(Emit:TCustomEmit); + function FetchLiteral(Value:PtrUint;name:PChar):PsrLiteral; + function FetchString(name:PChar):PsrLiteralString; + function FetchConst(dtype:TsrDataType;Value:PtrUint):PsrLiteralConst; + end; + + +implementation + +class function ntLiteral.GetPrintData(node:PsrNode):RawByteString; +begin + Result:=PsrLiteral(node)^.GetPrintData; +end; + +class function ntLiteral.GetData(node:PsrNode;data:Pointer):Ptruint; +begin + Result:=PsrLiteral(node)^.GetData(data); +end; + +// + +class function ntLiteralString.GetPrintData(node:PsrNode):RawByteString; +begin + Result:=PsrLiteralString(node)^.GetPrintData; +end; + +class function ntLiteralString.GetData(node:PsrNode;data:Pointer):Ptruint; +begin + Result:=PsrLiteralString(node)^.GetData(data); +end; + +// + +class function ntLiteralConst.GetPrintData(node:PsrNode):RawByteString; +begin + Result:=PsrLiteralConst(node)^.GetPrintData; +end; + +class function ntLiteralConst.GetData(node:PsrNode;data:Pointer):Ptruint; +begin + Result:=PsrLiteralConst(node)^.GetData(data); +end; + +// + +function TsrLiteral.c(n1,n2:PsrLiteral):Integer; +begin + Result:=ord(ptruint(n1^.fntype)>ptruint(n2^.fntype))-ord(ptruint(n1^.fntype)0) then Exit; + // + Result:=Integer(ord(n1^.dtype)>ord(n2^.dtype))-Integer(ord(n1^.dtype)0) then Exit; + // + Result:=Integer(n1^.Value>n2^.Value)-Integer(n1^.Value0) then Exit; + // + Result:=ComparePChar(n1^.name,n2^.name); +end; + +// + +Procedure TsrLiteral.Init; inline; +begin + fntype:=ntLiteral; +end; + +Function TsrLiteral.AsBool:Boolean; inline; +begin + Assert(@Self<>nil); + Result:=PBoolean(@Value)^; +end; + +Function TsrLiteral.AsUint8:Byte; inline; +begin + Assert(@Self<>nil); + Result:=PByte(@Value)^; +end; + +Function TsrLiteral.AsInt8:Shortint; inline; +begin + Assert(@Self<>nil); + Result:=PShortint(@Value)^; +end; + +Function TsrLiteral.AsUint16:Word; inline; +begin + Assert(@Self<>nil); + Result:=PWord(@Value)^; +end; + +Function TsrLiteral.AsInt16:Smallint; inline; +begin + Assert(@Self<>nil); + Result:=PSmallint(@Value)^; +end; + +Function TsrLiteral.AsUint32:DWORD; inline; +begin + Assert(@Self<>nil); + Result:=PDWORD(@Value)^; +end; + +Function TsrLiteral.AsInt32:Integer; inline; +begin + Assert(@Self<>nil); + Result:=PInteger(@Value)^; +end; + +Function TsrLiteral.AsUint64:QWORD; inline; +begin + Assert(@Self<>nil); + Result:=Value; +end; + +Function TsrLiteral.AsInt64:Int64; inline; +begin + Assert(@Self<>nil); + Result:=Int64(Value); +end; + +Function TsrLiteral.AsHalf16:THalf16; inline; +begin + Assert(@Self<>nil); + Result:=PHalf16(@Value)^ +end; + +Function TsrLiteral.AsFloat32:Single; inline; +begin + Assert(@Self<>nil); + Result:=PSingle(@Value)^; +end; + +Function TsrLiteral.AsFloat64:Double; inline; +begin + Assert(@Self<>nil); + Result:=PDouble(@Value)^; +end; + +Function TsrLiteral.GetPrintData:RawByteString; +begin + if (name=nil) or (StrLen(name)=0) then + begin + Result:=IntToStr(Value); + end else + begin + Result:=name; + end; +end; + +Function TsrLiteral.GetData(data:Pointer):Ptruint; +begin + Result:=SizeOf(DWORD); + if (data<>nil) then + begin + PDWORD(data)^:=DWORD(Value); + end; +end; + +// + +Procedure TsrLiteralString.Init; inline; +begin + fntype:=ntLiteralString; +end; + +Function TsrLiteralString.GetPrintData:RawByteString; +begin + Result:='"'+name+'"'; +end; + +Function TsrLiteralString.GetData(data:Pointer):Ptruint; +begin + Result:=StrLen(name)+1; + if (data<>nil) then + begin + Move(name^,data^,Result); + end; +end; + +// + +Procedure TsrLiteralConst.Init; inline; +begin + fntype:=ntLiteralConst; +end; + +const + DefaultFormatSettings : TFormatSettings = ( + CurrencyFormat: 1; + NegCurrFormat: 5; + ThousandSeparator: ','; + DecimalSeparator: '.'; + CurrencyDecimals: 2; + DateSeparator: '-'; + TimeSeparator: ':'; + ListSeparator: ','; + CurrencyString: '$'; + ShortDateFormat: ''; + LongDateFormat: ''; + TimeAMString: ''; + TimePMString: ''; + ShortTimeFormat: ''; + LongTimeFormat : ''; + ShortMonthNames:('','','','','','','','','','','',''); + LongMonthNames :('','','','','','','','','','','',''); + ShortDayNames :('','','','','','',''); + LongDayNames :('','','','','','',''); + TwoDigitYearCenturyWindow: 50; + ); + +Function TsrLiteralConst.GetPrintData:RawByteString; +begin + Result:=''; + case dtype of + dtUnknow :Result:='0x'+HexStr(Value,4); + + dtBool : + Case AsBool of + true :Result:='true'; + false:Result:='false'; + end; + + dtHalf16 : Result:=FloatToStr(Single(AsHalf16),DefaultFormatSettings); + dtFloat32: Result:=FloatToStr( AsFloat32,DefaultFormatSettings); + dtFloat64: Result:=FloatToStr( AsFloat64,DefaultFormatSettings); + + dtInt8 : Result:=IntToStr(AsInt8); + dtUint8 : Result:=IntToStr(AsUint8); + + dtInt16 : Result:=IntToStr(AsInt16); + dtUint16 : Result:=IntToStr(AsUint16); + + dtInt32 : Result:=IntToStr(AsInt32); + dtUint32 : Result:=IntToStr(AsUint32); + + dtInt64 : Result:=IntToStr(AsInt64); + dtUint64 : Result:=IntToStr(AsUint64); + else; + end; +end; + +Function TsrLiteralConst.GetData(data:Pointer):Ptruint; +begin + Result:=0; + Case dtype.BitSize of + 8:begin + Result:=SizeOf(BYTE); + if (data<>nil) then + begin + PBYTE(data)^:=BYTE(Value); + end; + end; + 16:begin + Result:=SizeOf(WORD); + if (data<>nil) then + begin + PWORD(data)^:=WORD(Value); + end; + end; + 32:begin + Result:=SizeOf(DWORD); + if (data<>nil) then + begin + PDWORD(data)^:=DWORD(Value); + end; + end; + 64:begin + Result:=SizeOf(QWORD); + if (data<>nil) then + begin + PQWORD(data)^:=Value; + end; + end; + else; + end; +end; + +// + +Procedure TsrLiteralList.Init(Emit:TCustomEmit); +begin + FEmit:=Emit; +end; + +function TsrLiteralList.FetchLiteral(Value:PtrUint;name:PChar):PsrLiteral; +var + node:TsrLiteral; + size:ptrint; +begin + node:=Default(TsrLiteral); + node.Init; + node.dtype:=dtUint32; + node.Value:=Value; + node.name :=name; + + Result:=FNTree.Find(@node); + if (Result=nil) then + begin + Result:=FEmit.Alloc(SizeOf(TsrLiteral)); + Move(node,Result^,SizeOf(TsrLiteral)); + + if (name<>nil) then + begin + size:=StrLen(name)+1; + Result^.name:=FEmit.Alloc(size); + Move(name^,Result^.name^,size); + end; + + FNTree.Insert(Result); + end; +end; + +function TsrLiteralList.FetchString(name:PChar):PsrLiteralString; +var + node:TsrLiteralString; + size_o:ptrint; + size_a:ptrint; +begin + node:=Default(TsrLiteralString); + node.Init; + node.dtype:=dtString; + node.name:=name; + + Result:=Pointer(FNTree.Find(Pointer(@node))); + if (Result=nil) then + begin + Result:=FEmit.Alloc(SizeOf(TsrLiteralString)); + Move(node,Result^,SizeOf(TsrLiteralString)); + + if (name<>nil) then + begin + size_o:=StrLen(name); + size_a:=Align(size_o+1,SizeOf(DWORD)); //align DW + + Result^.name:=FEmit.Alloc(size_a); + Move(name^,Result^.name^,size_o); + end else + begin + Result^.name:=FEmit.Alloc(SizeOf(DWORD)); + //space DW + end; + + FNTree.Insert(Result); + end; +end; + +function TsrLiteralList.FetchConst(dtype:TsrDataType;Value:PtrUint):PsrLiteralConst; +var + node:TsrLiteralConst; +begin + node:=Default(TsrLiteralConst); + node.Init; + node.dtype:=dtype; + node.Value:=Value; + + Result:=Pointer(FNTree.Find(Pointer(@node))); + if (Result=nil) then + begin + Result:=FEmit.Alloc(SizeOf(TsrLiteralConst)); + Move(node,Result^,SizeOf(TsrLiteralConst)); + + FNTree.Insert(Result); + end; +end; + +end. + diff --git a/spirv/srNode.pas b/spirv/srNode.pas new file mode 100644 index 00000000..d42e8d9d --- /dev/null +++ b/spirv/srNode.pas @@ -0,0 +1,548 @@ +unit srNode; + +{$mode objfpc}{$H+} + +interface + +type + PsrNode=^TsrNode; + PPsrNode=^PsrNode; + + PPrepTypeNode=^TPrepTypeNode; + TPrepTypeNode=record + dnode:PsrNode; + rtype:Integer; + end; + + TsrNodeVmt=class + class Procedure add_read (node,src:PsrNode); virtual; + class Procedure rem_read (node,src:PsrNode); virtual; + // + class Procedure add_write (node,src:PsrNode); virtual; + class Procedure rem_write (node,src:PsrNode); virtual; + // + class Procedure mark_read (node,src:PsrNode); virtual; + class Procedure mark_unread (node,src:PsrNode); virtual; + // + class Procedure zero_read (node:PsrNode); virtual; + class Procedure zero_unread (node:PsrNode); virtual; + // + class Procedure mark_write (node,src:PsrNode); virtual; + class Procedure mark_unwrite(node,src:PsrNode); virtual; + // + class Function pwrite_count(node:PsrNode):PDWORD virtual; + class Procedure SetWriter(node,w,line:PsrNode); virtual; + class Procedure ResetWriter(node,w:PsrNode); virtual; + class Function is_used(node:PsrNode):Boolean virtual; + class Function GetPtype(node:PsrNode):PsrNode; virtual; + class Function GetStorageClass(node:PsrNode):DWORD; virtual; + class function GetStorageName(node:PsrNode):RawByteString; virtual; + class function GetPrintName(node:PsrNode):RawByteString; virtual; + class function GetPrintData(node:PsrNode):RawByteString; virtual; + class function Down(node:PsrNode):Pointer; virtual; + class function Next(node:PsrNode):Pointer; virtual; + class function Prev(node:PsrNode):Pointer; virtual; + class function Parent(node:PsrNode):Pointer; virtual; + class function First(node:PsrNode):Pointer; virtual; + class function Last(node:PsrNode):Pointer; virtual; + class Procedure PrepType(node:PPrepTypeNode); virtual; + // + class function GetIndexCount(node:PsrNode):DWORD; virtual; + // + class function GetRef(node:PsrNode):Pointer; virtual; + // + class function GetData(node:PsrNode;data:Pointer):Ptruint; virtual; + end; + + TsrNodeType=class of TsrNodeVmt; + + TsrNode=packed object + protected + fntype:TsrNodeType; + private + fread_count:DWORD; + public + property ntype:TsrNodeType read fntype; + property read_count:DWORD read fread_count; + function IsType(t:TsrNodeType):Boolean; + function AsType(t:TsrNodeType):Pointer; + Procedure mark_read (src:PsrNode); + Procedure mark_unread (src:PsrNode); + Procedure mark_write (src:PsrNode); + Procedure mark_unwrite(src:PsrNode); + function write_count:DWORD; + Procedure SetWriter(w,line:PsrNode); + Procedure ResetWriter(w:PsrNode); + function IsUsed:Boolean; + Function pType:Pointer; + Function GetStorageClass:DWORD; + function GetStorageName:RawByteString; + function GetPrintName:RawByteString; + function GetPrintData:RawByteString; + function Next:Pointer; + function Prev:Pointer; + function Parent:Pointer; + function First:Pointer; + function Last:Pointer; + procedure PrepType(rtype:Integer); + function GetIndexCount:DWORD; + function GetRef:Pointer; + function GetData(data:Pointer):Ptruint; + end; + + TCustomEmit=class + Function Alloc(Size:ptruint):Pointer; virtual abstract; + Function GetConfig :Pointer; virtual abstract; + Function GetCodeHeap :Pointer; virtual abstract; + Function GetLiteralList :Pointer; virtual abstract; + Function GetTypeList :Pointer; virtual abstract; + Function GetConstList :Pointer; virtual abstract; + Function GetRegsStory :Pointer; virtual abstract; + Function GetCapabilityList :Pointer; virtual abstract; + Function GetHeaderList :Pointer; virtual abstract; + Function GetDecorateList :Pointer; virtual abstract; + Function GetDebugInfoList :Pointer; virtual abstract; + Function GetVariableList :Pointer; virtual abstract; + Function GetInputList :Pointer; virtual abstract; + Function GetOutputList :Pointer; virtual abstract; + Function GetDataLayoutList :Pointer; virtual abstract; + Function GetVertLayoutList :Pointer; virtual abstract; + Function GetFragLayoutList :Pointer; virtual abstract; + Function GetBufferList :Pointer; virtual abstract; + Function GetUniformList :Pointer; virtual abstract; + Function GetBitcastList :Pointer; virtual abstract; + Function GetCacheOpList :Pointer; virtual abstract; + Function GetFuncList :Pointer; virtual abstract; + Function GetCursor :Pointer; virtual abstract; + function curr_line :Pointer; virtual abstract; + function init_line :Pointer; virtual abstract; + function NewRefNode :PsrNode; virtual abstract; + function OpCast (pLine, dst,src:PsrNode):PsrNode; virtual abstract; + function OpLoad (pLine,dtype,dst,src:PsrNode):PsrNode; virtual abstract; + function OpStore (pLine, dst,src:PsrNode):PsrNode; virtual abstract; + procedure PostLink(pLine, dst:PsrNode); virtual abstract; + procedure emit_spi; virtual abstract; + end; + +implementation + +class Procedure TsrNodeVmt.add_read(node,src:PsrNode); +begin + Inc(node^.fread_count); +end; + +class Procedure TsrNodeVmt.rem_read(node,src:PsrNode); +begin + Assert(node^.fread_count<>0); + if (node^.fread_count=0) then Exit; + Dec(node^.fread_count); +end; + +class Procedure TsrNodeVmt.add_write(node,src:PsrNode); +var + p:PDWORD; +begin + p:=node^.fntype.pwrite_count(node); + if (p<>nil) then + begin + Inc(p^); + end; +end; + +class Procedure TsrNodeVmt.rem_write(node,src:PsrNode); +var + p:PDWORD; +begin + p:=node^.fntype.pwrite_count(node); + if (p<>nil) then + begin + Assert(p^<>0); + if (p^=0) then Exit; + Dec(p^); + end; +end; + +class Procedure TsrNodeVmt.mark_read(node,src:PsrNode); +var + prv:Boolean; +begin + repeat + Assert(node^.fntype<>nil); + + prv:=node^.IsUsed; + + node^.fntype.add_read(node,src); + + if (prv=node^.IsUsed) then Exit; + + node^.fntype.zero_read(node); + + src :=node; + node:=node^.fntype.Down(node); + until (node=nil); +end; + +class Procedure TsrNodeVmt.mark_unread(node,src:PsrNode); +var + prv:Boolean; +begin + repeat + Assert(node^.fntype<>nil); + + prv:=node^.IsUsed; + + node^.fntype.rem_read(node,src); + + if (prv=node^.IsUsed) then Exit; + + node^.fntype.zero_unread(node); + + src :=node; + node:=node^.fntype.Down(node); + until (node=nil); +end; + +class Procedure TsrNodeVmt.zero_read(node:PsrNode); +begin + // +end; + +class Procedure TsrNodeVmt.zero_unread(node:PsrNode); +begin + // +end; + +class Procedure TsrNodeVmt.mark_write(node,src:PsrNode); +var + prv:Boolean; +begin + repeat + Assert(node^.fntype<>nil); + + prv:=node^.IsUsed; + + node^.fntype.add_write(node,src); + + if (prv=node^.IsUsed) then Exit; + + node^.fntype.zero_read(node); + + src :=node; + node:=node^.fntype.Down(node); + until (node=nil); +end; + +class Procedure TsrNodeVmt.mark_unwrite(node,src:PsrNode); +var + prv:Boolean; +begin + repeat + Assert(node^.fntype<>nil); + + prv:=node^.IsUsed; + + node^.fntype.rem_write(node,src); + + if (prv=node^.IsUsed) then Exit; + + node^.fntype.zero_unread(node); + + src :=node; + node:=node^.fntype.Down(node); + until (node=nil); +end; + +class Function TsrNodeVmt.pwrite_count(node:PsrNode):PDWORD; +begin + Result:=nil; +end; + +class Procedure TsrNodeVmt.SetWriter(node,w,line:PsrNode); +begin + w^.mark_read(node); +end; + +class Procedure TsrNodeVmt.ResetWriter(node,w:PsrNode); +begin + w^.mark_unread(node); +end; + +class Function TsrNodeVmt.is_used(node:PsrNode):Boolean; +begin + Result:=(node^.read_count<>0) or (node^.write_count<>0); +end; + +class Function TsrNodeVmt.GetPtype(node:PsrNode):PsrNode; +begin + Result:=nil; +end; + +class Function TsrNodeVmt.GetStorageClass(node:PsrNode):DWORD; +begin + Result:=6; +end; + +class function TsrNodeVmt.GetStorageName(node:PsrNode):RawByteString; +begin + Result:=''; +end; + +class function TsrNodeVmt.GetPrintName(node:PsrNode):RawByteString; +begin + Result:=''; +end; + +class function TsrNodeVmt.GetPrintData(node:PsrNode):RawByteString; +begin + Result:=''; +end; + +class function TsrNodeVmt.Down(node:PsrNode):Pointer; +begin + Result:=nil; +end; + +class function TsrNodeVmt.Next(node:PsrNode):Pointer; +begin + Result:=nil; +end; + +class function TsrNodeVmt.Prev(node:PsrNode):Pointer; +begin + Result:=nil; +end; + +class function TsrNodeVmt.Parent(node:PsrNode):Pointer; +begin + Result:=nil; +end; + +class function TsrNodeVmt.First(node:PsrNode):Pointer; +begin + Result:=nil; +end; + +class function TsrNodeVmt.Last(node:PsrNode):Pointer; +begin + Result:=nil; +end; + +class Procedure TsrNodeVmt.PrepType(node:PPrepTypeNode); +begin + node^.dnode:=nil; +end; + +class function TsrNodeVmt.GetIndexCount(node:PsrNode):DWORD; +begin + Result:=0; +end; + +class function TsrNodeVmt.GetRef(node:PsrNode):Pointer; +begin + Result:=nil; +end; + +class function TsrNodeVmt.GetData(node:PsrNode;data:Pointer):Ptruint; +begin + Result:=0; +end; + +// + +function TsrNode.IsType(t:TsrNodeType):Boolean; +begin + Result:=False; + if (@Self=nil) then Exit; + Result:=fntype.InheritsFrom(t); +end; + +function TsrNode.AsType(t:TsrNodeType):Pointer; +begin + Result:=nil; + if (@Self=nil) then Exit; + if not fntype.InheritsFrom(t) then Exit; + Result:=@Self; +end; + +Procedure TsrNode.mark_read(src:PsrNode); +begin + if (@Self=nil) then Exit; + Assert(fntype<>nil); + fntype.mark_read(@Self,src); +end; + +Procedure TsrNode.mark_unread(src:PsrNode); +begin + if (@Self=nil) then Exit; + Assert(fntype<>nil); + fntype.mark_unread(@Self,src); +end; + +Procedure TsrNode.mark_write(src:PsrNode); +begin + if (@Self=nil) then Exit; + Assert(fntype<>nil); + fntype.mark_write(@Self,src); +end; + +Procedure TsrNode.mark_unwrite(src:PsrNode); +begin + if (@Self=nil) then Exit; + Assert(fntype<>nil); + fntype.mark_unwrite(@Self,src); +end; + +function TsrNode.write_count:DWORD; +var + p:PDWORD; +begin + Result:=0; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + p:=fntype.pwrite_count(@Self); + if (p=nil) then Exit; + Result:=p^; +end; + +Procedure TsrNode.SetWriter(w,line:PsrNode); +begin + if (@Self=nil) then Exit; + Assert(fntype<>nil); + fntype.SetWriter(@Self,w,line); +end; + +Procedure TsrNode.ResetWriter(w:PsrNode); +begin + if (@Self=nil) then Exit; + Assert(fntype<>nil); + fntype.ResetWriter(@Self,w); +end; + +function TsrNode.IsUsed:Boolean; +begin + Result:=False; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.is_used(@Self); +end; + +Function TsrNode.pType:Pointer; +begin + Result:=nil; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.GetPtype(@Self); +end; + +Function TsrNode.GetStorageClass:DWORD; +begin + Result:=6; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.GetStorageClass(@Self); +end; + +function TsrNode.GetStorageName:RawByteString; +begin + Result:=''; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.GetStorageName(@Self); +end; + +function TsrNode.GetPrintName:RawByteString; +begin + Result:=''; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.GetPrintName(@Self); +end; + +function TsrNode.GetPrintData:RawByteString; +begin + Result:=''; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.GetPrintData(@Self); +end; + +function TsrNode.Next:Pointer; +begin + Result:=nil; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.Next(@Self); +end; + +function TsrNode.Prev:Pointer; +begin + Result:=nil; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.Prev(@Self); +end; + +function TsrNode.Parent:Pointer; +begin + Result:=nil; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.Parent(@Self); +end; + +function TsrNode.First:Pointer; +begin + Result:=nil; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.First(@Self); +end; + +function TsrNode.Last:Pointer; +begin + Result:=nil; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.Last(@Self); +end; + +procedure TsrNode.PrepType(rtype:Integer); +var + node:TPrepTypeNode; +begin + node:=Default(TPrepTypeNode); + node.dnode:=@Self; + node.rtype:=rtype; + While (node.dnode<>nil) do + begin + Assert(node.dnode^.fntype<>nil); + node.dnode^.fntype.PrepType(@node); + end; +end; + +function TsrNode.GetIndexCount:DWORD; +begin + Result:=0; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.GetIndexCount(@Self); +end; + +function TsrNode.GetRef:Pointer; +begin + Result:=nil; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.GetRef(@Self); +end; + +function TsrNode.GetData(data:Pointer):Ptruint; +begin + Result:=0; + if (@Self=nil) then Exit; + Assert(fntype<>nil); + Result:=fntype.GetData(@Self,data); +end; + +end. + diff --git a/spirv/srOp.pas b/spirv/srOp.pas index e6e4a9ed..c077526c 100644 --- a/spirv/srOp.pas +++ b/spirv/srOp.pas @@ -5,49 +5,110 @@ unit srOp; interface uses - srNodes, - srLabel, - srCFG, - srParser, - srTypes, - srRefId, - srReg; + sysutils, + spirv, + ginodes, + srNode, + srCFGLabel, + srCFGParser, + srCFGCursor, + srLiteral, + srType, + srTypes, + srRefId, + srReg; type + ntOpCustom=class(TsrNodeVmt) + class function Next (node:PsrNode):Pointer; override; + class function Prev (node:PsrNode):Pointer; override; + class function Parent(node:PsrNode):Pointer; override; + end; + + ntOp=class(ntOpCustom) + class Procedure zero_read(node:PsrNode); override; + class Procedure PrepType(node:PPrepTypeNode); override; + class Function GetPtype (node:PsrNode):PsrNode; override; + class function GetIndexCount(node:PsrNode):DWORD; override; + end; + + ntOpBlock=class(ntOpCustom) + class function First (node:PsrNode):Pointer; override; + class function Last (node:PsrNode):Pointer; override; + class function GetIndexCount(node:PsrNode):DWORD; override; + end; + + ntFunc=class(TsrNodeVmt) + class function First (node:PsrNode):Pointer; override; + class function Last (node:PsrNode):Pointer; override; + class function GetRef (node:PsrNode):Pointer; override; + class function GetPrintName(node:PsrNode):RawByteString; override; + end; + + PPspirvOp=^PspirvOp; + PspirvOp=^TspirvOp; + POpParamNode=^TOpParamNode; - TOpParamNode=packed record - pNext:POpParamNode; - //---- - ntype:TsrNodeType; - Case Byte of - 0:(pData:Pointer); - 1:(Value:DWORD;name:record end); + TOpParamNode=packed object + private + pNext:POpParamNode; + pParent:PspirvOp; + pValue:PsrNode; + procedure SetValue(v:PsrNode); + public + property Next:POpParamNode read pNext; + property Parent:PspirvOp read pParent; + property Value:PsrNode read pValue write SetValue; + function AsReg:Pointer; + function TryGetValue(var V:PtrUint):Boolean; end; TOpParamQueue=specialize TNodeQueue; PsrOpBlock=^TsrOpBlock; - PspirvOp=^TspirvOp; - TspirvOp=object - pPrev,pNext:PspirvOp; - //---- - pParent:PsrOpBlock; - pParam:TOpParamQueue; - Adr:TSrcAdr; - dst_type:PsrType; - dst:TOpParamSingle; - OpId:DWORD; - procedure InsertAfter(new:PspirvOp); - procedure InsertBefore(new:PspirvOp); - procedure Remove; - function ParamNode(i:Byte):POpParamNode; - procedure AddParam(const s:TOpParamSingle); - procedure AddParam(ntype:TsrNodeType;Data:Pointer); - procedure AddParamAfter(prev:POpParamNode;ntype:TsrNodeType;Data:Pointer); - procedure AddLiteral(Value:PtrUint;const name:RawByteString=''); - procedure AddString(const name:RawByteString); - Procedure SetDstReg(r:Pointer); + PsrOpCustom=^TsrOpCustom; + TsrOpCustom=object(TsrNode) + private + pPrev,pNext:PsrOpCustom; + pParent:PsrOpBlock; + end; + + TsrOpList=specialize TNodeList; + + TsoFlags=(soClear,soNotUsed); + TsoSetFlags=Set of TsoFlags; + + TspirvOp=object(TsrOpCustom) + private + pParam:TOpParamQueue; + FType:PsrType; + Fdst:PsrNode; + flags:TsoSetFlags; + procedure SetType(t:PsrType); + Procedure SetDst(r:PsrNode); + Procedure UnClear; + public + Adr:TSrcAdr; + OpId:DWORD; + property pType:PsrType read FType write SetType; + property pDst:PsrNode read Fdst write SetDst; + procedure Init(_OpId:DWORD); inline; + procedure InsertAfter(new:PspirvOp); + procedure InsertBefore(new:PspirvOp); + procedure Remove; + Function Alloc(Size:ptruint):Pointer; + function ParamFirst:POpParamNode; + function ParamLast:POpParamNode; + function ParamNode(i:Byte):POpParamNode; + procedure AddParam(p:Pointer); + procedure AddParamAfter(_prev:POpParamNode;p:Pointer); + procedure AddLiteral(Value:PtrUint;const name:RawByteString=''); + procedure AddString(const name:RawByteString); + function is_cleared:Boolean; + function Clear:Boolean; + procedure mark_not_used; + function can_clear:Boolean; end; TsrVolMark=(vmNone,vmEnd,vmBreak,vmCont); @@ -57,77 +118,91 @@ type bType:TsrBlockType; end; - TsrOpList=specialize TNodeList; - - TsrOpBlockSimple=object(TsrOpList) - Alloc:TfnAlloc; - procedure Init(cb:TfnAlloc); - function NewSpirvOp(OpId:DWORD):PSpirvOp; - function AddSpirvOp(node:PSpirvOp):PSpirvOp; - function AddSpirvOp(OpId:DWORD):PSpirvOp; + TsrOpBlockCustom=object(TsrOpCustom) + private + FEmit:TCustomEmit; + FList:TsrOpList; + FIndex:DWORD; + FLevel:DWORD; + procedure AddIndex(d:DWORD); + procedure SubIndex(d:DWORD); + public + property Emit:TCustomEmit read FEmit; + property Level:DWORD read FLevel; + procedure Init(_Emit:TCustomEmit); + procedure InsertAfter(node,new:PsrOpCustom); + procedure InsertBefore(node,new:PsrOpCustom); + procedure Remove(node:PsrOpCustom); + procedure UpdateLevel; + Function Alloc(Size:ptruint):Pointer; + function NewSpirvOp(OpId:DWORD):PSpirvOp; + function AddSpirvOp(node:PSpirvOp):PSpirvOp; + function AddSpirvOp(OpId:DWORD):PSpirvOp; + function line:Pointer; end; - TsrOpBlock=object(TsrOpBlockSimple) - pParent:PsrOpBlock; - pUpLine:PSpirvOp; //from post + TsrOpBlock=packed object(TsrOpBlockCustom) + public - Block:TsrBlockInfo; + Block:TsrBlockInfo; - Labels:record - pBegOp:PspirvOp; - pEndOp:PspirvOp; - pMrgOp:PspirvOp; - end; + Labels:record + pBegOp:PspirvOp; + pEndOp:PspirvOp; + pMrgOp:PspirvOp; + end; - FCursor:TsrCursor; + FCursor:TsrCursor; - Regs:record - pSnap:PsrRegsSnapshot; - FVolMark:TsrVolMark; - end; + Regs:record + pSnap:PsrRegsSnapshot; + FVolMark:TsrVolMark; + end; - Cond:record - pReg:PsrRegNode; - FVal:Boolean; - FUseCont:Boolean; - end; + Cond:record + pReg:PsrRegNode; + FVal:Boolean; + FUseCont:Boolean; + end; - FLevel:DWORD; + dummy:TspirvOp; - dummy:TspirvOp; - - function line:PSpirvOp; - procedure SetCFGBlock(pLBlock:PsrCFGBlock); - procedure SetInfo(const b:TsrBlockInfo); - procedure SetInfo(bType:TsrBlockType;b_adr,e_adr:TSrcAdr); - procedure SetLabels(pBegOp,pEndOp,pMrgOp:PspirvOp); - procedure SetCond(pReg:PsrRegNode;FVal:Boolean); - function IsEndOf(Adr:TSrcAdr):Boolean; - function FindUpLoop:PsrOpBlock; - function FindUpCond(pReg:PsrRegNode):PsrOpBlock; + procedure Init(_Emit:TCustomEmit); + procedure SetCFGBlock(pLBlock:PsrCFGBlock); + procedure SetInfo(const b:TsrBlockInfo); + procedure SetInfo(bType:TsrBlockType;b_adr,e_adr:TSrcAdr); + procedure SetLabels(pBegOp,pEndOp,pMrgOp:PspirvOp); + procedure SetCond(pReg:PsrRegNode;FVal:Boolean); + function IsEndOf(Adr:TSrcAdr):Boolean; + function FindUpLoop:PsrOpBlock; + function FindUpCond(pReg:PsrRegNode):PsrOpBlock; end; PSpirvFunc=^TSpirvFunc; - TSpirvFunc=object - pPrev,pNext,pLeft,pRight:PSpirvFunc; - //---- - read_count:DWORD; - FTop:TsrOpBlock; - pBlock:PsrOpBlock; - ID:TsrRefId; //post id - name:RawByteString; - function c(n1,n2:PSpirvFunc):Integer; static; - Procedure PushBlock(New:PsrOpBlock); - function PopBlock:Boolean; - function line:PSpirvOp; - Procedure Init(const fname:RawByteString;Alloc:TfnAlloc); - Procedure mark_read; - Procedure mark_unread; - function NewSpirvOp(OpId:DWORD):PSpirvOp; - function AddSpirvOp(node:PSpirvOp):PSpirvOp; - function AddSpirvOp(OpId:DWORD):PSpirvOp; + TSpirvFunc=object(TsrNode) + private + pPrev,pNext,pLeft,pRight:PSpirvFunc; + //---- + FName:RawByteString; + FTop:TsrOpBlock; + FBlock:PsrOpBlock; + ID:TsrRefId; //post id + function c(n1,n2:PSpirvFunc):Integer; static; + public + property Name:RawByteString read FName; + property pBlock:PsrOpBlock read FBlock; + Function pTop:PsrOpBlock; + Procedure PushBlock(New:PsrOpBlock); + function PopBlock:Boolean; + function line:Pointer; + Procedure Init(const _name:RawByteString;Emit:TCustomEmit); + function NewSpirvOp(OpId:DWORD):PSpirvOp; + function AddSpirvOp(node:PSpirvOp):PSpirvOp; + function AddSpirvOp(OpId:DWORD):PSpirvOp; + function GetPrintName:RawByteString; end; + PsrFuncList=^TsrFuncList; TsrFuncList=object type TNodeList=specialize TNodeList; @@ -137,60 +212,191 @@ type FNTree:TNodeFetch; function Search(const name:RawByteString):PSpirvFunc; procedure Insert(new:PSpirvFunc); + function First:PSpirvFunc; inline; end; - PsrCacheOp=^TsrCacheOp; - TsrCacheOp=object - pLeft,pRight:PsrCacheOp; - //---- - pReg:PsrRegNode; - key:packed record - place:PsrOpBlock; - OpId:DWORD; - dtype:TsrDataType; - count:DWORD; - end; - Data:record end; - function c(n1,n2:PsrCacheOp):Integer; static; - function GetCompItem(i:Byte):PsrRegNode; inline; - Procedure SetCompItem(i:Byte;p:PsrRegNode); inline; - end; - - TsrCacheOpList=object - type - TNodeFetch=specialize TNodeFetch; - var - Alloc:TfnAlloc; - FNTree:TNodeFetch; - function Fetch(place:PsrOpBlock;OpId:DWORD;rtype:TsrDataType;count:Byte;src:PPsrRegNode):PsrCacheOp; - end; +Function is_write_op(OpId:DWORD):Boolean; implementation -uses - SprvEmit; +class function ntOpCustom.Next(node:PsrNode):Pointer; +begin + Result:=PsrOpCustom(node)^.pNext; +end; + +class function ntOpCustom.Prev(node:PsrNode):Pointer; +begin + Result:=PsrOpCustom(node)^.pPrev; +end; + +class function ntOpCustom.Parent(node:PsrNode):Pointer; +begin + Result:=PsrOpCustom(node)^.pParent; +end; + +// + +class Procedure ntOp.zero_read(node:PsrNode); +begin + PspirvOp(node)^.UnClear; +end; + +class Function ntOp.GetPtype(node:PsrNode):PsrNode; +begin + Result:=PspirvOp(node)^.FType; +end; + +class function ntOp.GetIndexCount(node:PsrNode):DWORD; +begin + Result:=1; +end; + +class Procedure ntOp.PrepType(node:PPrepTypeNode); +var + new:TsrDataType; + pNode:POpParamNode; + pTypeList:PsrTypeList; +begin + With PspirvOp(node^.dnode)^ do + begin + new:=TsrDataType(node^.rtype); + if (new=dtUnknow) then Exit; + + Case OpId of + Op.OpLoad: + begin + pNode:=ParamNode(0); + if (pNode<>nil) then + begin + //change? + pTypeList:=pParent^.FEmit.GetTypeList; + pType:=pTypeList^.Fetch(new); + //next + node^.dnode:=pNode^.pValue; + Exit; + end; + end; + else; + end; + + end; + + node^.dnode:=nil; +end; + +// + +class function ntOpBlock.First(node:PsrNode):Pointer; +begin + Result:=PsrOpBlock(node)^.FList.pHead; +end; + +class function ntOpBlock.Last(node:PsrNode):Pointer; +begin + Result:=PsrOpBlock(node)^.FList.pTail; +end; + +class function ntOpBlock.GetIndexCount(node:PsrNode):DWORD; +begin + Result:=PsrOpBlock(node)^.FIndex; +end; + +// + +class function ntFunc.First(node:PsrNode):Pointer; +begin + Result:=PSpirvFunc(node)^.FTop.FList.pHead; +end; + +class function ntFunc.Last(node:PsrNode):Pointer; +begin + Result:=PSpirvFunc(node)^.FTop.FList.pTail; +end; + +class function ntFunc.GetPrintName(node:PsrNode):RawByteString; +begin + Result:=PSpirvFunc(node)^.GetPrintName; +end; + +class function ntFunc.GetRef(node:PsrNode):Pointer; +begin + Result:=@PSpirvFunc(node)^.ID; +end; + +// + +procedure TOpParamNode.SetValue(v:PsrNode); +begin + if (pValue=v) then Exit; + Assert(pParent<>nil); + if not pParent^.is_cleared then + begin + v^.mark_read (pParent); + pValue^.mark_unread(pParent); + end; + pValue:=v; +end; + +function TOpParamNode.AsReg:Pointer; +begin + Result:=nil; + if (@Self=nil) then Exit; + Result:=pValue^.AsType(ntReg); +end; + +function TOpParamNode.TryGetValue(var V:PtrUint):Boolean; +begin + Result:=False; + if (@Self=nil) then Exit; + if pValue^.IsType(ntLiteral) then + begin + V:=PsrLiteral(pValue)^.Value; + Result:=True; + end; +end; + + +// + +procedure TspirvOp.Init(_OpId:DWORD); inline; +begin + fntype:=ntOp; + OpId:=_OpId; +end; procedure TspirvOp.InsertAfter(new:PspirvOp); begin Assert(new<>nil); Assert(pParent<>nil); pParent^.InsertAfter(@Self,new); - new^.pParent:=pParent; end; procedure TspirvOp.InsertBefore(new:PspirvOp); begin Assert(new<>nil); Assert(pParent<>nil); - pParent^.InsertAfter(@Self,new); - new^.pParent:=pParent; + pParent^.InsertBefore(@Self,new); end; procedure TspirvOp.Remove; begin Assert(pParent<>nil); pParent^.Remove(@Self); - pParent:=nil; +end; + +Function TspirvOp.Alloc(Size:ptruint):Pointer; +begin + Result:=pParent^.Alloc(Size); +end; + +function TspirvOp.ParamFirst:POpParamNode; +begin + Result:=pParam.pHead; +end; + +function TspirvOp.ParamLast:POpParamNode; +begin + Result:=pParam.pTail; end; function TspirvOp.ParamNode(i:Byte):POpParamNode; @@ -207,78 +413,164 @@ begin end; end; -procedure TspirvOp.AddParam(const s:TOpParamSingle); +procedure TspirvOp.AddParam(p:Pointer); var node:POpParamNode; begin - node:=pParent^.Alloc(SizeOf(TOpParamNode)); - node^.ntype:=s.ntype; - node^.pData:=s.pData; + node:=Alloc(SizeOf(TOpParamNode)); + node^.pParent:=@Self; + node^.pValue :=p; pParam.Push_tail(node); + + if not is_cleared then + begin + PsrNode(p)^.mark_read(@Self); + end; end; -procedure TspirvOp.AddParam(ntype:TsrNodeType;Data:Pointer); +procedure TspirvOp.AddParamAfter(_prev:POpParamNode;p:Pointer); var node:POpParamNode; begin - node:=pParent^.Alloc(SizeOf(TOpParamNode)); - node^.ntype:=ntype; - node^.pData:=Data; - pParam.Push_tail(node); -end; + node:=Alloc(SizeOf(TOpParamNode)); + node^.pParent:=@Self; + node^.pValue:=p; + pParam.InsertAfter(_prev,node); -procedure TspirvOp.AddParamAfter(prev:POpParamNode;ntype:TsrNodeType;Data:Pointer); -var - node:POpParamNode; -begin - node:=pParent^.Alloc(SizeOf(TOpParamNode)); - node^.ntype:=ntype; - node^.pData:=Data; - pParam.InsertAfter(prev,node); + if not is_cleared then + begin + PsrNode(p)^.mark_read(@Self); + end; end; procedure TspirvOp.AddLiteral(Value:PtrUint;const name:RawByteString=''); var - node:POpParamNode; - l:ptruint; + pLiterals:PsrLiteralList; + Literal:PsrLiteral; begin - l:={%H-}ptruint(@TOpParamNode(nil^).name)+Length(name)+1; - node:=pParent^.Alloc(l); - node^.ntype:=ntLiteral; - node^.Value:=Value; - Move(PChar(name)^,node^.name,Length(name)+1); - pParam.Push_tail(node); + pLiterals:=pParent^.FEmit.GetLiteralList; + Literal:=pLiterals^.FetchLiteral(Value,Pchar(name)); + AddParam(Literal); end; procedure TspirvOp.AddString(const name:RawByteString); var - node:POpParamNode; - l:ptruint; + pLiterals:PsrLiteralList; + Literal:PsrLiteralString; begin - l:={%H-}ptruint(@TOpParamNode(nil^).name)+Length(name)+1; - l:=Align(l,SizeOf(DWORD)); - node:=pParent^.Alloc(l); - node^.ntype:=ntString; - node^.Value:=0; - Move(PChar(name)^,node^.name,Length(name)+1); - pParam.Push_tail(node); + pLiterals:=pParent^.FEmit.GetLiteralList; + Literal:=pLiterals^.FetchString(Pchar(name)); + AddParam(Literal); end; -Procedure TspirvOp.SetDstReg(r:Pointer); +procedure TspirvOp.SetType(t:PsrType); begin - Assert(r<>nil); - dst.SetParam(ntReg,r); - PsrRegNode(r)^.pWriter.SetParam(ntOp,@Self); - PsrRegNode(r)^.pLine:=@Self; //update line [bitcast order] -end; - -function TsrOpBlock.line:PSpirvOp; -begin - Result:=nil; - if (@Self<>nil) then + if (FType=t) then Exit; + if not is_cleared then begin - Result:=pTail; + t^.mark_read (@Self); + FType^.mark_unread(@Self); end; + FType:=t; +end; + +Procedure TspirvOp.SetDst(r:PsrNode); +begin + if (Fdst=r) then Exit; + + if is_write_op(OpId) then + begin + if not is_cleared then + begin + r^.mark_write (@Self); + Fdst^.mark_unwrite(@Self); + end; + Fdst:=r; + end else + begin + Fdst^.ResetWriter(@Self); + Fdst:=r; + Fdst^.SetWriter(@Self,@Self); + end; + +end; + +function TspirvOp.is_cleared:Boolean; +begin + Result:=(soClear in flags); +end; + +function TspirvOp.Clear:Boolean; +var + node:POpParamNode; +begin + Result:=False; + if not can_clear then Exit; + + Assert(read_count=0); + + if is_write_op(OpId) then + begin + Fdst^.mark_unwrite(@Self); + end; + + FType^.mark_unread(@Self); + node:=pParam.pHead; + While (node<>nil) do + begin + node^.pValue^.mark_unread(@Self); + node:=node^.pNext; + end; + + flags:=flags-[soNotUsed]; + flags:=flags+[soClear]; + Result:=True; +end; + +Procedure TspirvOp.UnClear; +var + node:POpParamNode; +begin + if not is_cleared then Exit; + + if is_write_op(OpId) then + begin + Fdst^.mark_write(@Self); + end; + + FType^.mark_read(@Self); + node:=pParam.pHead; + While (node<>nil) do + begin + node^.pValue^.mark_read(@Self); + node:=node^.pNext; + end; + + flags:=flags-[soClear]; +end; + +procedure TspirvOp.mark_not_used; +begin + flags:=flags+[soNotUsed]; +end; + +function TspirvOp.can_clear:Boolean; +begin + if (soClear in flags) then Exit(False); + if (soNotUsed in flags) then Exit(True); + if (OpId=Op.OpNop) then Exit(True); + if (Fdst=nil) then Exit(False); + Result:=not Fdst^.IsUsed; +end; + +// + +procedure TsrOpBlock.Init(_Emit:TCustomEmit); +begin + fntype:=ntOpBlock; + FEmit :=_Emit; + dummy.Init(Op.OpNop); + AddSpirvOp(@dummy); end; procedure TsrOpBlock.SetCFGBlock(pLBlock:PsrCFGBlock); @@ -356,72 +648,66 @@ function TSpirvFunc.c(n1,n2:PSpirvFunc):Integer; var count1,count2:sizeint; begin - Count1:=Length(n1^.name); - Count2:=Length(n2^.name); + Count1:=Length(n1^.FName); + Count2:=Length(n2^.FName); Result:=Integer(Count1>Count2)-Integer(Count1nil) then + if (FBlock<>nil) then begin - Result:=pBlock^.pTail; + Result:=FBlock^.FList.pTail; end; end; -Procedure TSpirvFunc.Init(const fname:RawByteString;Alloc:TfnAlloc); +Procedure TSpirvFunc.Init(const _name:RawByteString;Emit:TCustomEmit); begin - name:=fname; - pBlock:=@FTop; - pBlock^.Alloc:=Alloc; - pBlock^.dummy.pParent:=pBlock; - pBlock^.Push_head(@pBlock^.dummy); -end; - -Procedure TSpirvFunc.mark_read; -begin - Inc(read_count); -end; - -Procedure TSpirvFunc.mark_unread; -begin - if (read_count<>0) then Dec(read_count); + fntype:=ntFunc; + FName:=_name; + FBlock:=@FTop; + FBlock^.Init(Emit); end; function TSpirvFunc.NewSpirvOp(OpId:DWORD):PSpirvOp; begin Result:=FTop.Alloc(SizeOf(TSpirvOp)); - Result^.OpId:=OpId; + Result^.Init(OpId); end; function TSpirvFunc.AddSpirvOp(node:PSpirvOp):PSpirvOp; begin Result:=node; if (node=nil) then Exit; - pBlock^.Push_tail(node); - node^.pParent:=pBlock; + FBlock^.FList.Push_tail(node); + node^.pParent:=FBlock; end; function TSpirvFunc.AddSpirvOp(OpId:DWORD):PSpirvOp; @@ -429,32 +715,122 @@ begin Result:=AddSpirvOp(NewSpirvOp(OpId)); end; +function TSpirvFunc.GetPrintName:RawByteString; +begin + if (name<>'') then + begin + Result:=name; + end else + begin + Assert(ID.Alloc); + Result:='f'+IntToStr(ID.ID); + end; +end; + // -procedure TsrOpBlockSimple.Init(cb:TfnAlloc); +procedure TsrOpBlockCustom.Init(_Emit:TCustomEmit); begin - Alloc:=cb; + fntype:=ntOpBlock; + FEmit :=_Emit; end; -function TsrOpBlockSimple.NewSpirvOp(OpId:DWORD):PSpirvOp; +procedure TsrOpBlockCustom.AddIndex(d:DWORD); +var + node:PsrOpBlock; +begin + node:=@Self; + While (node<>nil) do + begin + node^.FIndex:=node^.FIndex+d; + node:=node^.pParent; + end; +end; + +procedure TsrOpBlockCustom.SubIndex(d:DWORD); +var + node:PsrOpBlock; +begin + node:=@Self; + While (node<>nil) do + begin + Assert(node^.FIndex>=d); + node^.FIndex:=node^.FIndex-d; + node:=node^.pParent; + end; +end; + +procedure TsrOpBlockCustom.InsertAfter(node,new:PsrOpCustom); +begin + FList.InsertAfter(node,new); + new^.pParent:=@Self; + AddIndex(new^.GetIndexCount); + mark_read(@Self); +end; + +procedure TsrOpBlockCustom.InsertBefore(node,new:PsrOpCustom); +begin + FList.InsertBefore(node,new); + new^.pParent:=@Self; + AddIndex(new^.GetIndexCount); + mark_read(@Self); +end; + +procedure TsrOpBlockCustom.Remove(node:PsrOpCustom); +begin + Assert(node^.pParent=@Self); + FList.Remove(node); + node^.pParent:=nil; + SubIndex(node^.GetIndexCount); + mark_unread(@Self); +end; + +procedure TsrOpBlockCustom.UpdateLevel; +begin + if (pParent=nil) then + begin + FLevel:=0; + end else + begin + FLevel:=pParent^.FLevel+1; + end; +end; + +Function TsrOpBlockCustom.Alloc(Size:ptruint):Pointer; +begin + Result:=FEmit.Alloc(Size); +end; + +function TsrOpBlockCustom.NewSpirvOp(OpId:DWORD):PSpirvOp; begin Result:=Alloc(SizeOf(TSpirvOp)); - Result^.OpId:=OpId; + Result^.Init(OpId); end; -function TsrOpBlockSimple.AddSpirvOp(node:PSpirvOp):PSpirvOp; +function TsrOpBlockCustom.AddSpirvOp(node:PSpirvOp):PSpirvOp; begin Result:=node; if (node=nil) then Exit; - Push_tail(node); + FList.Push_tail(node); node^.pParent:=@Self; + AddIndex(node^.GetIndexCount); + mark_read(@Self); end; -function TsrOpBlockSimple.AddSpirvOp(OpId:DWORD):PSpirvOp; +function TsrOpBlockCustom.AddSpirvOp(OpId:DWORD):PSpirvOp; begin Result:=AddSpirvOp(NewSpirvOp(OpId)); end; +function TsrOpBlockCustom.line:Pointer; +begin + Result:=nil; + if (@Self<>nil) then + begin + Result:=FList.pTail; + end; +end; + // function TsrFuncList.Search(const name:RawByteString):PSpirvFunc; @@ -462,7 +838,7 @@ var node:TSpirvFunc; begin node:=Default(TSpirvFunc); - node.name:=name; + node.FName:=name; Result:=FNTree.Find(@node); end; @@ -472,61 +848,24 @@ begin FList.Push_head(new); end; +function TsrFuncList.First:PSpirvFunc; inline; +begin + Result:=FList.pHead; +end; + //-- -function TsrCacheOp.c(n1,n2:PsrCacheOp):Integer; -var - count:DWORD; +Function is_write_op(OpId:DWORD):Boolean; begin - Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrCacheOp.key)); - if (Result=0) then - begin - count:=n1^.key.count; - if (count<>0) then - begin - Result:=CompareByte(n1^.Data,n2^.Data,count*SizeOf(Pointer)); - end; - end; -end; - -function TsrCacheOp.GetCompItem(i:Byte):PsrRegNode; inline; -begin - Result:=PPsrRegNode(@Data)[i]; -end; - -Procedure TsrCacheOp.SetCompItem(i:Byte;p:PsrRegNode); inline; -begin - PPsrRegNode(@Data)[i]:=p; -end; - -function TsrCacheOpList.Fetch(place:PsrOpBlock;OpId:DWORD;rtype:TsrDataType;count:Byte;src:PPsrRegNode):PsrCacheOp; -var - i:Byte; - size:ptruint; - rec:record - node:TsrCacheOp; - align:array[0..3] of Pointer; - end; -begin - Assert(place<>nil); - Assert((count>0) and (count<=4)); - Result:=nil; - rec.node:=Default(TsrCacheOp); - rec.node.key.place:=place; - rec.node.key.OpId :=OpId; - rec.node.key.dtype:=rtype; - rec.node.key.count:=count; - For i:=0 to count-1 do - begin - rec.node.SetCompItem(i,src[i]); - end; - Result:=FNTree.Find(@rec.node); - if (Result=nil) then - begin - size:=SizeOf(TsrCacheOp)+SizeOf(Pointer)*count; - Result:=Alloc(size); - Move(rec.node,Result^,Size); - FNTree.Insert(Result); + Case OpId of + Op.OpStore, + Op.OpImageWrite, + Op.OpAtomicStore, + Op.OpAtomicExchange, + Op.OpAtomicCompareExchange, + Op.OpAtomicCompareExchangeWeak:Result:=True; + else + Result:=False; end; end; diff --git a/spirv/srOpUtils.pas b/spirv/srOpUtils.pas index 858739ec..3bb50956 100644 --- a/spirv/srOpUtils.pas +++ b/spirv/srOpUtils.pas @@ -1,228 +1,241 @@ unit srOpUtils; {$mode objfpc}{$H+} -{$MODESWITCH ADVANCEDRECORDS} interface uses spirv, - srNodes, - srTypes, + srNode, + srOp, srReg, - srConst, srLayout, - srVariable, - srOp; + srVariable; const - OpLinks =DWORD(-1); - OpBlock =DWORD(-2); - OpMakeExp=DWORD(-3); - OpMakeVec=DWORD(-4); - OpIAddExt=DWORD(-5); - OpISubExt=DWORD(-6); - OpAbsDiff=DWORD(-7); - OpWQM32 =DWORD(-8); - OpPackOfs=DWORD(-9); - //OpMED3F + OpIAddExt=DWORD(-1); + OpISubExt=DWORD(-2); + OpAbsDiff=DWORD(-3); + OpWQM32 =DWORD(-4); - OpCUBEID =DWORD(-10); - OpCUBESC =DWORD(-11); - OpCUBETC =DWORD(-12); - OpCUBEMA =DWORD(-13); + OpBFEU32 =DWORD(-5); + OpBFIB32 =DWORD(-6); - OpMakeCM =DWORD(-14); + OpPackAnc=DWORD(-7); + OpPackOfs=DWORD(-8); + OpMakeExp=DWORD(-9); + OpMakeVec=DWORD(-10); + OpMakeCub=DWORD(-11); -type - TOpParamNodeHelper = record helper for TOpParamNode - function AsParam:TOpParamSingle; - function AsReg:Pointer; - function AsVar:Pointer; - function AsChain:Pointer; - function TryGetValue(var V:DWORD):Boolean; - end; + OpCUBEID =DWORD(-12); + OpCUBESC =DWORD(-13); + OpCUBETC =DWORD(-14); + OpCUBEMA =DWORD(-15); -function InsSpirvOp(pLine,pNew:PspirvOp):PSpirvOp; -Procedure MarkUnreadParamSingle(const node:TOpParamSingle); +function InsSpirvOp(pLine,pNew:PspirvOp):PspirvOp; Function get_inverse_cmp_op(OpId:DWORD):DWORD; Function is_term_op(OpId:DWORD):Boolean; Function is_merge_op(OpId:DWORD):Boolean; Function is_term_op(pLine:PspirvOp):Boolean; -procedure _up_merge_line(var pLine:PspirvOp); +procedure up_merge_line(var pLine:PspirvOp); function FindUpSameOp(pLine,node:PspirvOp):PspirvOp; -function isGTLine(p1,p2:PspirvOp):Boolean; //(p1>p2) -function IsGTFlow(pSrc,pDst:PSpirvOp):Boolean; +function GetGlobalIndex(pLine:PspirvOp):DWORD; +function MaxLine(p1,p2:PspirvOp):PspirvOp; function GetMaxPlace(pLine:PSpirvOp;count:Byte;src:PPsrRegNode):PSpirvOp; +function GetChainRegNode(node:PsrRegNode):PsrChain; +function GetSourceRegNode(node:PsrRegNode):PsrNode; + +function flow_down_next_up(pLine:PspirvOp):PspirvOp; +function flow_down_prev_up(pLine:PspirvOp):PspirvOp; + implementation -function TOpParamNodeHelper.AsParam:TOpParamSingle; -begin - Result:=Default(TOpParamSingle); - if (@Self=nil) then Exit; - Result.ntype:=ntype; - Result.pData:=pData; -end; - -function TOpParamNodeHelper.AsReg:Pointer; -begin - Result:=nil; - if (@Self=nil) then Exit; - if (ntype<>ntReg) then Exit; - Result:=pData; -end; - -function TOpParamNodeHelper.AsVar:Pointer; -begin - Result:=nil; - if (@Self=nil) then Exit; - if (ntype<>ntVar) then Exit; - Result:=pData; -end; - -function TOpParamNodeHelper.AsChain:Pointer; -begin - Result:=nil; - if (@Self=nil) then Exit; - if (ntype<>ntChain) then Exit; - Result:=pData; -end; - -function TOpParamNodeHelper.TryGetValue(var V:DWORD):Boolean; -begin - Result:=False; - if (@Self=nil) then Exit; - if (ntype<>ntLiteral) then Exit; - V:=Value; - Result:=True; -end; - //-- -function InsSpirvOp(pLine,pNew:PspirvOp):PSpirvOp; +function flow_down_next_up(pLine:PspirvOp):PspirvOp; +begin + Result:=pLine^.First; + if (Result=nil) then + begin + repeat + Result:=pLine^.Next; + pLine:=pLine^.Parent; + until (pLine=nil) or (Result<>nil); + end; +end; + +function flow_down_prev_up(pLine:PspirvOp):PspirvOp; +begin + Result:=pLine^.Last; + if (Result=nil) then + begin + repeat + Result:=pLine^.Prev; + pLine:=pLine^.Parent; + until (pLine=nil) or (Result<>nil); + end; +end; + +function flow_prev_up(pLine:PspirvOp):PspirvOp; +begin + repeat + Result:=pLine^.Prev; + pLine:=pLine^.Parent; + until (pLine=nil) or (Result<>nil); +end; + +function InsSpirvOp(pLine,pNew:PspirvOp):PspirvOp; +var + tmp:PspirvOp; begin Result:=nil; Assert(pLine<>nil); if (pLine=nil) or (pNew=nil) then Exit; - if (pLine^.pNext<>nil) then + if (pLine^.Next<>nil) then + if pNew^.IsType(ntOp) then begin - pNew^.adr:=pLine^.adr; + tmp:=pLine; + while (not tmp^.IsType(ntOp)) do + begin + tmp:=flow_down_prev_up(tmp); + Assert(tmp<>nil); + end; + pNew^.Adr:=tmp^.Adr; end; pLine^.InsertAfter(pNew); Result:=pNew; end; -Procedure MarkUnreadParamSingle(const node:TOpParamSingle); +function GetCurrentIndex(pLine:PspirvOp):DWORD; +var + pParent:PsrOpBlock; + node:PspirvOp; begin - Case node.ntype of - ntLiteral:; - ntConst:PsrConst (node.pData)^.mark_unread; - ntType :PsrType (node.pData)^.mark_unread; - ntFunc :PSpirvFunc (node.pData)^.mark_unread; - ntVar :PsrVariable(node.pData)^.mark_unread; - ntRefId:; - ntReg :PsrRegNode (node.pData)^.mark_unread; - //ntReg :RegUnmark(node.pData); - ntChain:PsrChain (node.pData)^.mark_unread; - else - Assert(false); + Result:=0; + if (pLine=nil) then Exit; + pParent:=pLine^.Parent; + if (pParent=nil) then Exit; + node:=pParent^.First; + While (node<>nil) and (node<>pLine) do + begin + Result:=Result+node^.GetIndexCount; + node:=node^.Next; + end; +end; + +function GetGlobalIndex(pLine:PspirvOp):DWORD; +var + pParent:PsrOpBlock; + node:PspirvOp; +begin + Result:=0; + if (pLine=nil) then Exit; + node:=pLine; + pParent:=node^.Parent; + While (pParent<>nil) do + begin + Result:=Result+GetCurrentIndex(node); + node:=PspirvOp(pParent); + pParent:=node^.Parent; end; end; function isGTLine(p1,p2:PspirvOp):Boolean; //(p1>p2) begin Result:=False; - p2:=p2^.pNext; + p2:=p2^.Next; While (p2<>nil) do begin if (p1=p2) then Exit(True); - p2:=p2^.pNext; + p2:=p2^.Next; end; end; -function isGTELine(p1,p2:PspirvOp):Boolean; //(p1>=p2) +Function IsGTLevel(p1,p2:PspirvOp):Boolean; //(p1>p2) +var + pParent1:PsrOpBlock; + pParent2:PsrOpBlock; begin Result:=False; - While (p2<>nil) do + pParent1:=p1^.Parent; + pParent2:=p2^.Parent; + Result:=(pParent1^.Level>pParent2^.Level); +end; + +function MaxLine(p1,p2:PspirvOp):PspirvOp; +var + pParent:PsrOpBlock; + node:PspirvOp; + i,w:DWORD; +begin + Result:=nil; + if (p1=nil) then Exit(p2); + if (p2=nil) or (p1=p2) then Exit(p1); + + if IsGTLevel(p2,p1) then //(p2>p1) begin - if (p1=p2) then Exit(True); - p2:=p2^.pNext; + //swap + node:=p1; + p1:=p2; + p2:=node; + end; + + i:=0; + node:=p1; + pParent:=node^.Parent; + While (pParent<>nil) do + begin + if (pParent=p2^.Parent) then + begin + if isGTLine(node,p2) then //(node>p2) + begin + //Assert(not isGTLine(p2,node)); + Exit(p1); + end else + begin + //Assert(isGTLine(p2,node)); + Exit(p2); + end; + end; + i:=i+GetCurrentIndex(node); + node:=PspirvOp(pParent); + pParent:=node^.Parent; + end; + + w:=GetGlobalIndex(p2); + if (i>w) then + begin + Result:=p1; + end else + begin + Result:=p2; end; end; Function IsParentOf(pLine,pCurr:PsrOpBlock):Boolean; begin Result:=False; + if not pLine^.IsType(ntOpBlock) then Exit; + if not pCurr^.IsType(ntOpBlock) then Exit; While (pLine<>nil) do begin if (pLine=pCurr) then Exit(True); - pLine:=pLine^.pParent; + pLine:=pLine^.Parent; end; end; -function FindBlockLine(pCurent,node:PsrOpBlock):PspirvOp; -var - tmp:PspirvOp; +Function IsParentOfLine(pLine,pCurr:PSpirvOp):Boolean; begin - Result:=nil; - if (pCurent=nil) then Exit; - tmp:=pCurent^.pHead; - While (tmp<>nil) do - begin - if (tmp^.OpId=OpBlock) and (tmp^.dst.pData=node) then - begin - Exit(tmp); - end; - tmp:=tmp^.pNext; - end; -end; - -{ - [pSrc] - | - V - [pBlock] -> [pDst] -} - -function IsGTFlow(pSrc,pDst:PSpirvOp):Boolean; -var - pLine,pCurr:PsrOpBlock; - tmp:PSpirvOp; -begin - Result:=False; - - pLine:=pDst^.pParent; - pCurr:=pSrc^.pParent; - - While (pLine<>nil) do - begin - - if (pLine=pCurr) then - begin - Result:=isGTELine(pSrc,pDst); - Exit; - end; - - if (pLine^.pParent=nil) then Exit; - - tmp:=pLine^.pUpLine; - if (tmp=nil) then - begin - tmp:=FindBlockLine(pLine^.pParent,pLine); - end; - pDst:=tmp; - - pLine:=pDst^.pParent; - end; + Result:=IsParentOf(pLine^.Parent,pCurr^.Parent); end; function GetMaxPlace(pLine:PSpirvOp;count:Byte;src:PPsrRegNode):PSpirvOp; var - m,t:PSpirvOp; + m:PSpirvOp; i:Byte; begin Result:=pLine; @@ -230,25 +243,10 @@ begin m:=nil; For i:=0 to count-1 do begin - t:=src[i]^.pLine; - if not src[i]^.is_const then - if IsParentOf(pLine^.pParent,t^.pParent) then + if (not src[i]^.is_const) then + if IsParentOfLine(pLine,src[i]^.pLine) then begin - if (m=nil) then - begin - m:=t; - end else - if (m^.pParent=t^.pParent) then - begin - if isGTLine(t,m) then - begin - m:=t; - end; - end else - if (t^.pParent^.FLevel>m^.pParent^.FLevel) then - begin - m:=t; - end; + m:=MaxLine(m,src[i]^.pLine); end; end; if (m<>nil) then @@ -325,36 +323,57 @@ begin if (pLine=nil) then Exit; repeat //up - Case pLine^.OpId of - Op.OpNop, - OpLinks:pLine:=pLine^.pPrev; - OpBlock:pLine:=PsrOpBlock(pLine^.dst.pData)^.pTail; - else - Break; + + if pLine^.IsType(ntOpBlock) then + begin + // + end else + if pLine^.IsType(ntOp) then + begin + if not pLine^.is_cleared then + begin + Case pLine^.OpId of + Op.OpNop:; // + else + Break; + end; + end; + end else + begin + Exit; end; - if (pLine=nil) then Exit; + + pLine:=flow_down_prev_up(pLine); + until false; Result:=is_term_op(pLine^.OpId); end; -procedure _up_merge_line(var pLine:PspirvOp); +procedure up_merge_line(var pLine:PspirvOp); +var + node:PspirvOp; begin repeat - if is_merge_op(pLine^.OpId) then + if pLine^.IsType(ntOp) then begin - pLine:=pLine^.pPrev; - Assert(pLine<>nil); - end else - begin - Break; + if pLine^.is_cleared or is_merge_op(pLine^.OpId) then + begin + node:=pLine^.Prev; + if (node<>nil) then + begin + pLine:=node; + Continue; + end; + end; end; + Break; until false; end; function CompareParam(p1,p2:POpParamNode):Boolean; begin - Result:=(p1^.ntype=p2^.ntype) and (p1^.pData=p2^.pData); + Result:=(p1^.Value=p2^.Value); end; function CompareOp(p1,p2:PspirvOp):Boolean; @@ -362,51 +381,68 @@ var n1,n2:POpParamNode; begin Result:=False; - if (p1^.OpId<>p2^.OpId) then Exit; - if (p1^.dst_type<>p2^.dst_type) then Exit; - n1:=p1^.pParam.pHead; - n2:=p2^.pParam.pHead; + if not p1^.IsType(ntOp) then Exit; + if not p2^.IsType(ntOp) then Exit; + + if (p1^.OpId<>p2^.OpId) then Exit; + if (p1^.pDst<>p2^.pDst) then Exit; + + n1:=p1^.ParamNode(0); + n2:=p2^.ParamNode(0); While (n1<>nil) do begin if (n2=nil) then Exit; if not CompareParam(n1,n2) then Exit; - n1:=n1^.pNext; - n2:=n2^.pNext; + n1:=n1^.Next; + n2:=n2^.Next; end; Result:=(n2=nil); end; function FindUpSameOp(pLine,node:PspirvOp):PspirvOp; -var - tmp:PspirvOp; - pBlock:PsrOpBlock; begin Result:=nil; if (pLine=nil) or (node=nil) then Exit; While (pLine<>nil) do begin - if CompareOp(pLine,node) then Exit(pLine); - tmp:=pLine^.pPrev; - if (tmp=nil) then + if not pLine^.is_cleared then begin - pBlock:=pLine^.pParent; - if (pBlock=nil) then Exit; - if (pBlock^.pParent=nil) then Exit; - tmp:=pBlock^.pUpLine; - if (tmp=nil) then - begin - tmp:=FindBlockLine(pBlock^.pParent,pBlock); - end; - tmp:=tmp^.pPrev; + if CompareOp(pLine,node) then Exit(pLine); end; - pLine:=tmp; + pLine:=flow_prev_up(pLine); end; end; +function GetChainRegNode(node:PsrRegNode):PsrChain; +var + pOp:PSpirvOp; +begin + Result:=nil; + node:=RegDown(node); + pOp:=node^.pWriter^.AsType(ntOp); + if (pOp=nil) then Exit; + if (pOp^.OpId<>Op.OpLoad) then Exit; + Result:=pOp^.ParamNode(0)^.Value^.AsType(ntChain); +end; + +function GetSourceRegNode(node:PsrRegNode):PsrNode; +var + pOp:PSpirvOp; + pVar:PsrVariable; +begin + Result:=nil; + node:=RegDown(node); + pOp:=node^.pWriter^.AsType(ntOp); + if (pOp=nil) then Exit; + if (pOp^.OpId<>Op.OpLoad) then Exit; + pVar:=pOp^.ParamNode(0)^.Value^.AsType(ntVariable); + if (pVar=nil) then Exit; + Result:=pVar^.pSource; +end; end. diff --git a/spirv/srOutput.pas b/spirv/srOutput.pas index 2b84e7ae..d2ed3363 100644 --- a/spirv/srOutput.pas +++ b/spirv/srOutput.pas @@ -5,13 +5,14 @@ unit srOutput; interface uses - typinfo, - spirv, - srNodes, - srOp, - srLayout, - srVariable, - srDecorate; + typinfo, + spirv, + srNode, + srType, + srOp, + srLayout, + srVariable, + srDecorate; type TpsslExportType=( @@ -39,55 +40,83 @@ type etParam28,etParam29,etParam30,etParam31 ); - PsrOutput=^TsrOutput; - TsrOutput=object(TsrDescriptor) - etype:TpsslExportType; - function GetName:RawByteString; + ntOutput=class(ntDescriptor) + class Function pwrite_count (node:PsrNode):PDWORD; override; + class function GetStorageName(node:PsrNode):RawByteString; override; end; + PsrOutput=^TsrOutput; + TsrOutput=object(TsrDescriptor) + fwrite_count:DWORD; + etype:TpsslExportType; + function GetStorageName:RawByteString; + end; + + PsrOutputList=^TsrOutputList; TsrOutputList=object + FEmit:TCustomEmit; data:array[TpsslExportType] of TsrOutput; - Procedure Init; - function Fetch(etype:TpsslExportType):PsrOutput; - procedure AllocBinding(Decorates:PsrDecorateList); + Procedure Init(Emit:TCustomEmit); inline; + function Fetch(etype:TpsslExportType;rtype:TsrDataType):PsrOutput; + procedure AllocBinding; procedure AllocEntryPoint(EntryPoint:PSpirvOp); end; implementation -function TsrOutput.GetName:RawByteString; +class Function ntOutput.pwrite_count(node:PsrNode):PDWORD; +begin + Result:=@PsrOutput(node)^.fwrite_count; +end; + +class function ntOutput.GetStorageName(node:PsrNode):RawByteString; +begin + Result:=PsrOutput(node)^.GetStorageName; +end; + +// + +function TsrOutput.GetStorageName:RawByteString; begin Result:=GetEnumName(TypeInfo(TpsslExportType),ord(etype)); end; -Procedure TsrOutputList.Init; +Procedure TsrOutputList.Init(Emit:TCustomEmit); inline; var i:TpsslExportType; begin + FEmit:=Emit; For i:=Low(TpsslExportType) to High(TpsslExportType) do begin - data[i].etype:=i; + data[i].fntype :=ntOutput; + data[i].etype :=i; data[i].FStorage:=StorageClass.Output; data[i].FBinding:=-1; end; end; -function TsrOutputList.Fetch(etype:TpsslExportType):PsrOutput; +function TsrOutputList.Fetch(etype:TpsslExportType;rtype:TsrDataType):PsrOutput; begin Result:=@data[etype]; + // + Result^.InitType(rtype,FEmit); + Result^.InitVar(FEmit); end; -procedure TsrOutputList.AllocBinding(Decorates:PsrDecorateList); +// + +procedure TsrOutputList.AllocBinding; var + pDecorateList:PsrDecorateList; i:TpsslExportType; pVar:PsrVariable; FLocation:Integer; begin - if (Decorates=nil) then Exit; + pDecorateList:=FEmit.GetDecorateList; For i:=Low(TpsslExportType) to High(TpsslExportType) do begin pVar:=data[i].pVar; - if (pVar<>nil) then + if (pVar<>nil) and data[i].IsUsed then begin Case i of etMrt0..etMrt7: @@ -95,7 +124,7 @@ begin if (data[i].FBinding=-1) then //alloc begin FLocation:=ord(i)-ord(etMrt0); - Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,FLocation); + pDecorateList^.OpDecorate(pVar,Decoration.Location,FLocation); data[i].FBinding:=FLocation; end; //Decoration.Index; ??? @@ -103,13 +132,13 @@ begin //etMrtz, etPos0: begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.Position); + pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.Position); end; //etPos1..etPos3, etParam0..etParam31: //interpolate param begin FLocation:=ord(i)-ord(etParam0); - Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,FLocation); + pDecorateList^.OpDecorate(pVar,Decoration.Location,FLocation); data[i].FBinding:=FLocation; end; else @@ -129,9 +158,10 @@ begin For i:=Low(TpsslExportType) to High(TpsslExportType) do begin pVar:=data[i].pVar; - if (pVar<>nil) then + if (not data[i].IsUsed) and (pVar<>nil) then assert(false); + if (pVar<>nil) and data[i].IsUsed then begin - EntryPoint^.AddParam(ntVar,pVar); + EntryPoint^.AddParam(pVar); end; end; end; diff --git a/spirv/srPrivate.pas b/spirv/srPrivate.pas new file mode 100644 index 00000000..0f414244 --- /dev/null +++ b/spirv/srPrivate.pas @@ -0,0 +1,873 @@ +unit srPrivate; + +{$mode ObjFPC}{$H+} + +interface + +uses + sysutils, + spirv, + ginodes, + srNode, + srType, + srTypes, + srLayout, + srOp, + srOpUtils, + srReg, + srVariable, + srBitcast; + +type + ntPrivate=class(ntDescriptor) + class Function pwrite_count (node:PsrNode):PDWORD; override; + class Procedure PrepType (node:PPrepTypeNode); override; + class function GetStorageName(node:PsrNode):RawByteString; override; + end; + + ntVolatile=class(TsrNodeVmt) + class Procedure zero_read (node:PsrNode); override; + class Procedure zero_unread (node:PsrNode); override; + class Procedure PrepType (node:PPrepTypeNode); override; + end; + + PsrPrivate=^TsrPrivate; + + PsrVolatile=^TsrVolatile; + TsrVolatile=object(TsrNode) + type + PVNode=^TVNode; + TVNode=record + pPrev,pNext:PVNode; + pReg:PsrRegNode; + end; + TNodeList=specialize TNodeList; + var + pPrev,pNext:PsrVolatile; + FSource:PsrPrivate; + FList:TNodeList; + Procedure Init(Source:PsrPrivate); inline; + Procedure AddStore(src:PsrRegNode); + Procedure PushStore(node:PVNode); + Function PopStore:PVNode; + Procedure RemoveAllStore; + Procedure zero_read; + Procedure zero_unread; + procedure PrepType(new:TsrDataType); + end; + + TsrPrivate=object(TsrDescriptor) + type + PVNode=^TVNode; + TVNode=record + pPrev,pNext:PVNode; + pLine:PspirvOp; + end; + TNodeList=specialize TNodeList; + TVoltList=specialize TNodeList; + private + pLeft,pRight:PsrPrivate; + //---- + fwrite_count:DWORD; + // + FSource:PsrRegSlot; + // + FLineList:TNodeList; + FVoltList:TVoltList; + function c(n1,n2:PsrPrivate):Integer; static; + Procedure SetRegType(rtype:TsrDataType); + function GetRegType:TsrDataType; + public + //FVolatile:TsrVolatile; + property dtype:TsrDataType read GetRegType write SetRegType; + property Source:PsrRegSlot read FSource; + Procedure Init; inline; + function Emit:TCustomEmit; + function GetStorageName:RawByteString; + function isBoolOnly:Boolean; + Procedure UpdateRegType; + Procedure PrepType(new:TsrDataType); + Procedure SortLines; + Procedure Optimize; + procedure AddLine(pLine:PspirvOp); + procedure AddLine(pLine:PspirvOp;node:TsrVolatile.PVNode); + procedure FetchLoad(pLine:PspirvOp;dst:PsrRegNode); + Procedure FetchStore(pLine:PspirvOp;node:TsrVolatile.PVNode); + function NewVolatile:PsrVolatile; + procedure RemoveAllStore; + end; + + PsrPrivateList=^TsrPrivateList; + TsrPrivateList=object + type + TNodeFetch=specialize TNodeFetch; + var + FEmit:TCustomEmit; + FNTree:TNodeFetch; + procedure Init(Emit:TCustomEmit); inline; + function Fetch(pSource:PsrRegSlot):PsrPrivate; + function First:PsrPrivate; inline; + Function Next(node:PsrPrivate):PsrPrivate; + // + procedure build_slot_dis(pSlot:PsrRegSlot;var old:PsrRegNode); + procedure build_slot_cur(pSlot:PsrRegSlot;var old:PsrRegNode); + procedure build_slot_old(pSlot:PsrRegSlot;var old:PsrRegNode); + procedure build_volatile_dis(old:PsrRegsSnapshot); + procedure build_volatile_cur(old:PsrRegsSnapshot); + procedure build_volatile_old(old:PsrRegsSnapshot); + procedure make_copy_slot(pSlot:PsrRegSlot); + procedure make_copy_all; + procedure PrepVolatile(dst:PspirvOp;src:PsrRegNode); + Procedure Post; + end; + +implementation + +class Procedure ntVolatile.zero_read(node:PsrNode); +begin + PsrVolatile(node)^.zero_read; +end; + +class Procedure ntVolatile.zero_unread(node:PsrNode); +begin + PsrVolatile(node)^.zero_unread; +end; + +class Procedure ntVolatile.PrepType(node:PPrepTypeNode); +begin + PsrVolatile(node^.dnode)^.PrepType(TsrDataType(node^.rtype)); + node^.dnode:=nil; +end; + +// + +Procedure TsrVolatile.Init(Source:PsrPrivate); inline; +begin + fntype :=ntVolatile; + FSource:=Source; +end; + +procedure TsrVolatile.PrepType(new:TsrDataType); +var + node:PVNode; +begin + if FSource^.isBoolOnly then + begin + new:=dtBool; + end; + if (new=dtUnknow) then exit; + + node:=FList.pHead; + While (node<>nil) do + begin + node^.pReg^.PrepType(ord(new)); + node:=node^.pNext; + end; +end; + +Procedure TsrVolatile.AddStore(src:PsrRegNode); +var + node:PVNode; +begin + if (src=nil) then Exit; + node:=FSource^.Emit.Alloc(SizeOf(TVNode)); + node^.pReg:=src; + if IsUsed then + begin + src^.mark_read(@Self); + end; + FList.Push_head(node); +end; + +Procedure TsrVolatile.PushStore(node:PVNode); +begin + if (node=nil) then Exit; + if IsUsed then + begin + node^.pReg^.mark_read(@Self); + end; + FList.Push_head(node); +end; + +Function TsrVolatile.PopStore:PVNode; +begin + Result:=FList.Pop_head; + if (Result<>nil) and IsUsed then + begin + Result^.pReg^.mark_unread(@Self); + end; +end; + +Procedure TsrVolatile.RemoveAllStore; +var + node:PVNode; +begin + repeat + node:=PopStore; + until (node=nil); +end; + +Procedure TsrVolatile.zero_read; +var + node:PVNode; +begin + node:=FList.pHead; + While (node<>nil) do + begin + node^.pReg^.mark_read(@Self); + node:=node^.pNext; + end; +end; + +Procedure TsrVolatile.zero_unread; +var + node:PVNode; +begin + node:=FList.pHead; + While (node<>nil) do + begin + node^.pReg^.mark_unread(@Self); + node:=node^.pNext; + end; +end; + +// + +class Function ntPrivate.pwrite_count(node:PsrNode):PDWORD; +begin + Result:=@PsrPrivate(node)^.fwrite_count; +end; + +class Procedure ntPrivate.PrepType(node:PPrepTypeNode); +begin + PsrPrivate(node^.dnode)^.PrepType(TsrDataType(node^.rtype)); + node^.dnode:=nil; +end; + +class function ntPrivate.GetStorageName(node:PsrNode):RawByteString; +begin + Result:=PsrPrivate(node)^.GetStorageName; +end; + +// + +function TsrPrivate.c(n1,n2:PsrPrivate):Integer; +begin + Result:=Integer(n1^.FSource>n2^.FSource)-Integer(n1^.FSourcenil) do + begin + pLine:=node^.pLine; + + Case pLine^.OpId of + + Op.OpLoad: + begin + pLine^.pDst^.PrepType(ord(rtype)); + pLine^.pType:=Ftype; + end; + + Op.OpStore: + begin + pLine^.ParamFirst^.Value^.PrepType(ord(rtype)); + end; + + else; + end; + + node:=node^.pNext; + end; +end; + +function TsrPrivate.GetRegType:TsrDataType; +begin + Result:=FType^.dtype; +end; + +Procedure TsrPrivate.UpdateRegType; +var + pBitcastList:PsrBitcastList; + node:PVNode; + pLine:PspirvOp; + dst:PsrRegNode; + old,rtype:TsrDataType; +begin + rtype:=FType^.dtype; + + pBitcastList:=Emit.GetBitcastList; + + node:=FLineList.pHead; + While (node<>nil) do + begin + pLine:=node^.pLine; + + Case pLine^.OpId of + + Op.OpLoad: + begin + pLine^.pDst^.PrepType(ord(rtype)); + pLine^.pType:=Ftype; + + dst:=pLine^.pDst^.AsType(ntReg); + if (dst<>nil) then + begin + old:=dst^.dtype; + if (old<>dtUnknow) and (not CompareType(rtype,old)) then + begin + //OpLoad -> new -> dst + pBitcastList:=Emit.GetBitcastList; + dst:=pBitcastList^.FetchDstr(rtype,dst); + pLine^.pDst:=dst; + end; + end; + end; + + Op.OpStore: + begin + pLine^.ParamFirst^.Value^.PrepType(ord(rtype)); + + dst:=pLine^.ParamFirst^.Value^.AsType(ntReg); + if (dst<>nil) then + begin + old:=dst^.dtype; + if (old<>dtUnknow) and (rtype<>old) then + begin + //OpStore <- new <- dst + pBitcastList:=Emit.GetBitcastList; + dst:=pBitcastList^.FetchRead(rtype,dst); + pLine^.ParamFirst^.Value:=dst; + end; + end; + end; + + else; + end; + + node:=node^.pNext; + end; +end; + +Procedure TsrPrivate.PrepType(new:TsrDataType); +var + old:TsrDataType; +begin + if isBoolOnly then + begin + new:=dtBool; + end; + if (new=dtUnknow) then Exit; + old:=GetRegType; + if is_unprep_type(old,new,True) then + begin + SetRegType(new); + end; +end; + +Procedure TsrPrivate.SortLines; +var + pnode,pnext:PVNode; + pLine:array[0..1] of PspirvOp; + nswp:Boolean; +begin + repeat + nswp:=True; + pnode:=FLineList.pHead; + While true do + begin + pnext:=pnode^.pNext; + if (pnext=nil) then Break; + + pLine[0]:=pnode^.pLine; + pLine[1]:=pnext^.pLine; + + if (MaxLine(pLine[0],pLine[1])=pLine[0]) then //pnode>pnext + begin + //swap + nswp:=False; + FLineList.Remove(pnode); + FLineList.InsertAfter(pnext,pnode); + end else + begin + pnode:=pnext; + end; + + end; + until nswp; +end; + +Procedure TsrPrivate.Optimize; +var + pnode,pprev:PVNode; + pLine:array[0..1] of PspirvOp; +begin + pnode:=FLineList.pTail; + While true do + begin + pprev:=pnode^.pPrev; + if (pprev=nil) then Break; + + pLine[0]:=pnode^.pLine; + pLine[1]:=pprev^.pLine; + + if (pLine[0]^.Parent=pLine[1]^.Parent) then + begin + //OpStore %v %r + //OpStore %v %r + if (pLine[0]^.OpId=Op.OpStore) and (pLine[1]^.OpId=Op.OpStore) then + begin + //Remove pprev + FLineList.Remove(pprev); + pLine[1]^.mark_not_used; + Continue; + end else + if (pLine[0]^.OpId=Op.OpStore) and (pLine[1]^.OpId=Op.OpLoad) then + begin + //%r = OpLoad %type %v ; pLine[1] ; pprev + //OpStore %v %r ; pLine[0] ; pnode + if CompareReg(RegDown(pLine[0]^.pDst^.AsType(ntReg)),RegDown(pLine[1]^.ParamFirst^.Value^.AsType(ntReg))) then + begin + //Remove pnode + FLineList.Remove(pnode); + pLine[0]^.mark_not_used; + + pnode:=pprev; + Continue; + end; + end; + end; + + pnode:=pprev; + end; +end; + +procedure TsrPrivate.AddLine(pLine:PspirvOp); +var + node:PVNode; +begin + node:=Emit.Alloc(SizeOf(TVNode)); + node^.pLine:=pLine; + FLineList.Push_tail(node); +end; + +procedure TsrPrivate.AddLine(pLine:PspirvOp;node:TsrVolatile.PVNode); +var + _node:PVNode; +begin + _node:=Pointer(node); //hack + _node^:=Default(TVNode); + _node^.pLine:=pLine; + FLineList.Push_tail(_node); +end; + +procedure TsrPrivate.FetchLoad(pLine:PspirvOp;dst:PsrRegNode); +begin + Assert(dst<>nil); + + pLine:=PspirvOp(Emit.OpLoad(pLine,FType,dst,FVar)); + + AddLine(pLine); +end; + +Procedure TsrPrivate.FetchStore(pLine:PspirvOp;node:TsrVolatile.PVNode); +var + src:PsrRegNode; +begin + if (node=nil) then Exit; + src:=node^.pReg; + if (src=nil) then Exit; + + pLine:=PspirvOp(Emit.OpStore(pLine,FVar,src)); + + AddLine(pLine,node); +end; + +function TsrPrivate.NewVolatile:PsrVolatile; +begin + Result:=Emit.Alloc(SizeOf(TsrVolatile)); + Result^.Init(@Self); + FVoltList.Push_tail(Result); +end; + +procedure TsrPrivate.RemoveAllStore; +var + node:PsrVolatile; +begin + node:=FVoltList.pHead; + While (node<>nil) do + begin + node^.RemoveAllStore; + node:=node^.pNext; + end; +end; + +// + +procedure TsrPrivateList.Init(Emit:TCustomEmit); inline; +begin + FEmit:=Emit; +end; + +function TsrPrivateList.Fetch(pSource:PsrRegSlot):PsrPrivate; +var + node:TsrPrivate; +begin + Assert(pSource<>nil); + node:=Default(TsrPrivate); + node.Init; + node.FSource:=pSource; + Result:=FNTree.Find(@node); + if (Result=nil) then + begin + Result:=FEmit.Alloc(SizeOf(TsrPrivate)); + Move(node,Result^,SizeOf(TsrPrivate)); + // + //Result^.FVolatile.Init(Result); + // + FNTree.Insert(Result); + end; +end; + +Function TsrPrivateList.First:PsrPrivate; +begin + Result:=FNTree.Min; +end; + +Function TsrPrivateList.Next(node:PsrPrivate):PsrPrivate; +begin + Result:=FNTree.Next(node); +end; + +procedure TsrPrivateList.build_slot_dis(pSlot:PsrRegSlot;var old:PsrRegNode); +var + cur:PsrRegNode; +begin + cur:=pSlot^.current; + While (cur<>old) do + begin + pSlot^.Remove(cur); + cur:=pSlot^.current; + end; +end; + +procedure TsrPrivateList.build_slot_cur(pSlot:PsrRegSlot;var old:PsrRegNode); +var + cur,prv,new:PsrRegNode; + pPrivate :PsrPrivate; + pVolatile:PsrVolatile; + rtype:TsrDataType; +begin + cur:=RegDownSlot(pSlot^.current); + prv:=RegDownSlot(old); + if CompareReg(cur,prv) then Exit; + + cur:=pSlot^.current; + + if (cur=nil) then + begin + Assert(false,'WTF'); + end; + if (old=nil) then + begin + //////old:=pSlot^.New(line,rtype); //Unresolve + end; + + pPrivate :=Fetch(pSlot); + //pVolatile:=@pPrivate^.FVolatile; + pVolatile:=pPrivate^.NewVolatile; + + rtype:=dtUnknow; + + if (old<>nil) then + //if (old^.pWriter^.AsType(ntVolatile)<>pVolatile) then + //if not old^.pWriter^.IsType(ntVolatile) then + begin + pVolatile^.AddStore(old); + rtype:=old^.dtype; + end; + // + if (cur<>nil) then + //if (cur^.pWriter^.AsType(ntVolatile)<>pVolatile) then + //if not cur^.pWriter^.IsType(ntVolatile) then + begin + pVolatile^.AddStore(cur); + rtype:=cur^.dtype; + end; + + //old^.PrepType(ord(pVolatile^.Ftype)); + //cur^.PrepType(ord(pVolatile^.Ftype)); + + new:=pSlot^.New(cur^.pLine,rtype); + new^.pWriter:=pVolatile; + FEmit.PostLink(cur^.pLine,new); //post processing + + old:=new; //update snap +end; + +procedure TsrPrivateList.build_slot_old(pSlot:PsrRegSlot;var old:PsrRegNode); +var + cur,prv,new:PsrRegNode; + pPrivate :PsrPrivate; + pVolatile:PsrVolatile; +begin + cur:=RegDownSlot(pSlot^.current); + prv:=RegDownSlot(old); + if CompareReg(cur,prv) then Exit; + + cur:=pSlot^.current; + + if (old<>nil) then + if old^.pWriter^.IsType(ntVolatile) then + begin + pVolatile:=old^.pWriter^.AsType(ntVolatile); + //if (pVolatile<>cur^.pWriter^.AsType(ntVolatile)) then + begin + pVolatile^.AddStore(cur); + end; + Exit; + end; + + prv:=nil; + if (old<>nil) then + begin + prv:=old^.pWriter^.AsType(ntReg); + Assert(prv<>nil); + end; + + pPrivate :=Fetch(pSlot); + //pVolatile:=@pPrivate^.FVolatile; + pVolatile:=pPrivate^.NewVolatile; + + //if (pVolatile<>prv^.pWriter^.AsType(ntVolatile)) then + begin + pVolatile^.AddStore(prv); + end; + + //if (pVolatile<>cur^.pWriter^.AsType(ntVolatile)) then + begin + pVolatile^.AddStore(cur); + end; + + if (old<>nil) then + begin + old^.pWriter:=pVolatile; + end else + if (cur<>nil) then + begin + new:=pSlot^.New(cur^.pLine,cur^.dtype); + new^.pWriter:=pVolatile; + FEmit.PostLink(FEmit.curr_line,new); //post processing + end; +end; + + +procedure TsrPrivateList.build_volatile_dis(old:PsrRegsSnapshot); +var + pRegsStory:PsrRegsStory; +begin + //exit; + pRegsStory:=FEmit.GetRegsStory; + pRegsStory^.ForEachSnap(@build_slot_dis,old); +end; + +procedure TsrPrivateList.build_volatile_cur(old:PsrRegsSnapshot); +var + pRegsStory:PsrRegsStory; +begin + //exit; + pRegsStory:=FEmit.GetRegsStory; + //NextVolatileID; FVolatileID:SizeUint; + pRegsStory^.ForEachSnap(@build_slot_cur,old); +end; + +procedure TsrPrivateList.build_volatile_old(old:PsrRegsSnapshot); +var + pRegsStory:PsrRegsStory; +begin + //exit; + pRegsStory:=FEmit.GetRegsStory; + //NextVolatileID; FVolatileID:SizeUint; + pRegsStory^.ForEachSnap(@build_slot_old,old); +end; + +procedure TsrPrivateList.make_copy_slot(pSlot:PsrRegSlot); +var + cur,node:PsrRegNode; +begin + //exit; + if (pSlot^.current<>nil) then + begin + cur:=pSlot^.current; + + //MakeCopy(pSlot,cur); + node:=pSlot^.New(FEmit.curr_line,cur^.dtype); + node^.pWriter:=cur; + FEmit.PostLink(FEmit.curr_line,node); //post processing + + pSlot^.current^.pLine:=cur^.pLine; + end; +end; + +procedure TsrPrivateList.make_copy_all; +var + pRegsStory:PsrRegsStory; +begin + //exit; + pRegsStory:=FEmit.GetRegsStory; + pRegsStory^.ForEachSlot(@make_copy_slot); +end; + +function get_load_from(r:PsrRegNode):PsrVariable; +var + pOp:PspirvOp; +begin + Result:=nil; + pOp:=r^.pWriter^.AsType(ntOp); + if (pOp=nil) then Exit; + if (pOp^.OpId<>Op.OpLoad) then Exit; + Result:=pOp^.ParamFirst^.Value^.AsType(ntVariable); +end; + +function get_load_from2(r:PsrRegNode):PsrVolatile; +begin + Result:=r^.pWriter^.AsType(ntVolatile); +end; + +procedure _Move(dst,src:PsrVolatile); +var + node:TsrVolatile.PVNode; +begin + node:=src^.PopStore; + While (node<>nil) do + begin + dst^.PushStore(node); + node:=src^.PopStore; + end; +end; + +procedure TsrPrivateList.PrepVolatile(dst:PspirvOp;src:PsrRegNode); //use forward only +var + tmp:PsrRegNode; + pPrivate :PsrPrivate; + pVolatile:PsrVolatile; + node:TsrVolatile.PVNode; + pLine:PspirvOp; + vtmp:PsrVolatile; +begin + if (src=nil) then Exit; + if (not src^.pWriter^.IsType(ntVolatile)) then Exit; + + pVolatile:=src^.pWriter^.AsType(ntVolatile); + pPrivate :=pVolatile^.FSource; + src^.pWriter:=nil; + + pPrivate^.InitVar(FEmit); + + pPrivate ^.PrepType(src^.dtype); + pVolatile^.PrepType(pPrivate^.GetRegType); + + if (pPrivate^.GetRegType=dtUnknow) then + begin + Assert(false); + end; + + node:=pVolatile^.PopStore; + While (node<>nil) do + begin + + tmp:=RegDown{Slot}(node^.pReg); + + if (src<>tmp) {and (pPrivate^.pVar<>get_load_from(tmp))} then + begin + pLine:=node^.pReg^.pLine; + Assert(pLine<>nil); + + if (tmp^.pWriter^.IsType(ntVolatile)) then + begin + vtmp:=tmp^.pWriter^.AsType(ntVolatile); + Assert(vtmp<>nil); + + _Move(pVolatile,vtmp); + + tmp^.pWriter:=src; + + Continue; + end; + + up_merge_line(pLine); + + pPrivate^.FetchStore(pLine,node); + end; + + node:=pVolatile^.PopStore; + end; + + pLine:=dst; + Assert(pLine<>nil); + pLine:=pLine^.Prev; + Assert(pLine<>nil); + + up_merge_line(pLine); + + Assert(pLine<>nil); + + //ntVolatile -> src -> next + //Opload -> src -> next + + pPrivate^.FetchLoad(pLine,src); //before reg +end; + +Procedure TsrPrivateList.Post; +var + node:PsrPrivate; +begin + node:=FNTree.Min; + While (node<>nil) do + begin + if node^.IsUsed then + begin + node^.RemoveAllStore; + node^.SortLines; + node^.Optimize; + node^.UpdateRegType; + end; + node:=FNTree.Next(node); + end; +end; + + +end. + + diff --git a/spirv/srRefId.pas b/spirv/srRefId.pas index 0437765c..2afddc26 100644 --- a/spirv/srRefId.pas +++ b/spirv/srRefId.pas @@ -4,11 +4,27 @@ unit srRefId; interface +uses + sysutils, + srNode; + type + ntRefId=class(TsrNodeVmt) + class function GetPrintName(node:PsrNode):RawByteString; override; + class function GetRef(node:PsrNode):Pointer; override; + end; + PsrRefId=^TsrRefId; - TsrRefId=packed object + TsrRefId=object ID:DWORD; - function Alloc:Boolean; inline; + function Alloc:Boolean; inline; + end; + + PsrRefNode=^TsrRefNode; + TsrRefNode=object(TsrNode) + ID:TsrRefId; + Procedure Init; inline; + function GetPrintName:RawByteString; end; PsrRefIdAlloc=^TsrRefIdAlloc; @@ -21,6 +37,27 @@ type implementation +class function ntRefId.GetPrintName(node:PsrNode):RawByteString; +begin + Result:=PsrRefNode(node)^.GetPrintName; +end; + +class function ntRefId.GetRef(node:PsrNode):Pointer; +begin + Result:=@PsrRefNode(node)^.ID; +end; + +Procedure TsrRefNode.Init; inline; +begin + fntype:=ntRefId; +end; + +function TsrRefNode.GetPrintName:RawByteString; +begin + Assert(ID.ID<>0); + Result:=IntToStr(ID.ID); +end; + function TsrRefId.Alloc:Boolean; inline; begin Result:=(ID<>0); diff --git a/spirv/srReg.pas b/spirv/srReg.pas index 75276b22..9818ddea 100644 --- a/spirv/srReg.pas +++ b/spirv/srReg.pas @@ -5,38 +5,101 @@ unit srReg; interface uses - srNodes, - srRefId, - srTypes, - srConst; + sysutils, + ginodes, + srNode, + srRefId, + srType, + srConst; type + ntReg=class(TsrNodeVmt) + class Procedure add_read (node,src:PsrNode); override; + class Procedure rem_read (node,src:PsrNode); override; + class Procedure SetWriter (node,w,line:PsrNode); override; + class Procedure ResetWriter (node,w:PsrNode); override; + class function Down (node:PsrNode):Pointer; override; + class function Next (node:PsrNode):Pointer; override; + class function Prev (node:PsrNode):Pointer; override; + class Procedure PrepType (node:PPrepTypeNode); override; + class function GetPrintName(node:PsrNode):RawByteString; override; + class function GetRef (node:PsrNode):Pointer; override; + end; + + ntRegPair=class(TsrNodeVmt) + class function Down (node:PsrNode):Pointer; override; + class Procedure SetWriter (node,w,line:PsrNode); override; + class Procedure ResetWriter(node,w:PsrNode); override; + end; + PPsrRegSlot=^PsrRegSlot; PsrRegSlot=^TsrRegSlot; PPsrRegNode=^PsrRegNode; PsrRegNode=^TsrRegNode; - TsrRegNode=packed object - pPrev,pNext:PsrRegNode; - //---- - read_count:DWORD; - ID:TsrRefId; //post id - pSlot:PsrRegSlot; - pWriter:TOpParamSingle; //ntReg,ntConst,ntOp,ntVolatile - pLine:Pointer; //PspirvOp; - dtype:TsrDataType; - function GetName:RawByteString; - Procedure mark_read; - Procedure mark_unread; - procedure SetConst(pConst:PsrConst); - procedure SetReg(pReg:PsrRegNode); - function AsConst:PsrConst; - function AsOp:Pointer; - function AsReg:PsrRegNode; - function is_const:Boolean; - function is_bool:Boolean; - function is_bool_or_const_bool:Boolean; - function is_unknow:Boolean; + + PRegDNode=^TRegDNode; + TRegDNode=record + pNext:PRegDNode; + pNode:PsrNode; + end; + TRegDNodeList=specialize TNodeStack; + + TsrRegNode=packed object(TsrNode) + private + pPrev,pNext:PsrRegNode; + // + ID:TsrRefId; //post id + F:bitpacked record + dtype:TsrDataType; + weak:Boolean; + end; + FSlot:PsrRegSlot; + FWriter:PsrNode; //ntReg,ntConst,ntOp,ntVolatile + FDList:TRegDNodeList; + FLine:Pointer; + Procedure AddDep(t:PsrNode); + Procedure RemDep(t:PsrNode); + function GetDtype:TsrDataType; + Procedure SetDtype(t:TsrDataType); + function GetWeak:Boolean; + Procedure SetWeak(t:Boolean); + Procedure SetWriter(t:PsrNode); + Function GetWriter:PsrNode; + Procedure SetLine(t:Pointer); + public + property pLine :Pointer read FLine write SetLine; //PspirvOp; + property pSlot :PsrRegSlot read FSlot; + property dtype :TsrDataType read GetDtype write SetDtype; + property Weak :Boolean read GetWeak write SetWeak; + property pWriter:PsrNode read GetWriter write SetWriter; + Procedure Init; inline; + function FirstDep:PRegDNode; + function GetName:RawByteString; + function AsConst:PsrConst; + function AsReg:PsrRegNode; + function is_const:Boolean; + function is_bool:Boolean; + function is_bool_or_const_bool:Boolean; + function is_unknow:Boolean; + function GetPrintName:RawByteString; + end; + + PsrRegPair=^TsrRegPair; + TsrRegPair=object(TsrNode) + private + FWriter:PsrNode; + FDst0:PsrNode; + FDst1:PsrNode; + Procedure SetWriter(t:PsrNode); + Procedure SetDst0(r:PsrNode); + Procedure SetDst1(r:PsrNode); + public + property pLine:PsrNode read FWriter; + property pWriter:PsrNode read FWriter write SetWriter; + property pDst0:PsrNode read FDst0 write SetDst0; + property pDst1:PsrNode read FDst1 write SetDst1; + Procedure Init; inline; end; TRegStory=specialize TNodeList; @@ -44,15 +107,16 @@ type TString5=string[5]; TsrRegSlot=object - Alloc:TfnAlloc; - pVar:Pointer; + FEmit:TCustomEmit; pStory:TRegStory; rid:TString5; - Procedure Init(a:TfnAlloc;const n:TString5); + Procedure Init(Emit:TCustomEmit;const n:TString5); function first:PsrRegNode; function current:PsrRegNode; + function isBoolOnly:Boolean; function New(pLine:Pointer;rtype:TsrDataType):PsrRegNode; function NewAfter(rtype:TsrDataType;r:PsrRegNode):PsrRegNode; + function NewBefore(rtype:TsrDataType;r:PsrRegNode):PsrRegNode; procedure Remove(r:PsrRegNode); end; @@ -69,6 +133,7 @@ type TForEachSlot=procedure(pSlot:PsrRegSlot) of object; TForEachSnap=procedure(pSlot:PsrRegSlot;var old:PsrRegNode) of object; + PsrRegsStory=^TsrRegsStory; TsrRegsStory=object SGRP:array[0..103] of TsrRegSlot; VCC:array[0..1] of TsrRegSlot; @@ -77,25 +142,171 @@ type SCC:TsrRegSlot; VGRP:array[0..255] of TsrRegSlot; FUnattach:TsrRegSlot; - Procedure Init(Alloc:TfnAlloc); - function get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean; + // + FDList:TRegDNodeList; + // + Procedure Init(Emit:TCustomEmit); + // + Function AllocDep:PRegDNode; + Procedure FreeDep(node:PRegDNode); + // function get_sdst7(SDST:Byte):PsrRegSlot; + function get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean; function get_ssrc8(SSRC:Byte):PsrRegSlot; - function get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean; 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; procedure ForEachSlot(cb:TForEachSlot); procedure ForEachSnap(cb:TForEachSnap;old:PsrRegsSnapshot); end; +function RegDown(node:PsrRegNode):PsrRegNode; +function RegDownSlot(node:PsrRegNode):PsrRegNode; +function CompareReg(r1,r2:PsrRegNode):Boolean; + implementation -Procedure TsrRegsStory.Init(Alloc:TfnAlloc); +// + +class Procedure ntReg.add_read(node,src:PsrNode); +begin + inherited; + PsrRegNode(node)^.AddDep(src); +end; + +class Procedure ntReg.rem_read(node,src:PsrNode); +begin + inherited; + PsrRegNode(node)^.RemDep(src); +end; + +class Procedure ntReg.SetWriter(node,w,line:PsrNode); +begin + With PsrRegNode(node)^ do + begin + SetWriter(w); + pLine:=line; + end; +end; + +class Procedure ntReg.ResetWriter(node,w:PsrNode); +begin + With PsrRegNode(node)^ do + if (FWriter=w) then + begin + SetWriter(nil); + pLine:=nil; + end; +end; + +class function ntReg.Down(node:PsrNode):Pointer; +begin + Result:=PsrRegNode(node)^.FWriter; +end; + +class function ntReg.Next(node:PsrNode):Pointer; +begin + Result:=PsrRegNode(node)^.pNext; +end; + +class function ntReg.Prev(node:PsrNode):Pointer; +begin + Result:=PsrRegNode(node)^.pPrev; +end; + +class Procedure ntReg.PrepType(node:PPrepTypeNode); +var + new:TsrDataType; + pConstList:PsrConstList; +begin + With PsrRegNode(node^.dnode)^ do + begin + new:=TsrDataType(node^.rtype); + if (new=dtUnknow) then + begin + node^.dnode:=nil; + Exit; + end; + + if FSlot^.isBoolOnly then + begin + //next + node^.rtype:=ord(dtBool); + node^.dnode:=pWriter; + Exit; + end else + if is_unprep_type(dtype,new,Weak) then + begin + dtype:=new; + Weak:=True; + if is_const then + begin + pConstList:=FSlot^.FEmit.GetConstList; + pWriter:=pConstList^.Bitcast(new,pWriter^.AsType(ntConst)); + end else + begin + //next + node^.dnode:=pWriter; + Exit; + end; + end; + + end; + + node^.dnode:=nil; +end; + +class function ntReg.GetPrintName(node:PsrNode):RawByteString; +begin + Result:=PsrRegNode(node)^.GetPrintName; +end; + +class function ntReg.GetRef(node:PsrNode):Pointer; +begin + With PsrRegNode(node)^ do + begin + if is_const then + begin + Result:=AsConst^.GetRef; + end else + begin + Result:=@ID; + end; + end; +end; + +// + +class function ntRegPair.Down(node:PsrNode):Pointer; +begin + Result:=PsrRegPair(node)^.FWriter; +end; + +class Procedure ntRegPair.SetWriter(node,w,line:PsrNode); +begin + With PsrRegPair(node)^ do + begin + SetWriter(w); + end; +end; + +class Procedure ntRegPair.ResetWriter(node,w:PsrNode); +begin + With PsrRegPair(node)^ do + if (FWriter=w) then + begin + SetWriter(nil); + end; +end; + +// + +Procedure TsrRegsStory.Init(Emit:TCustomEmit); var i:Word; n:TString5; @@ -104,20 +315,50 @@ begin For i:=0 to 103 do begin Str(i,n); - SGRP[i].Init(Alloc,'S'+n); + SGRP[i].Init(Emit,'S'+n); end; - VCC[0].Init(Alloc,'VCCL'); - VCC[1].Init(Alloc,'VCCH'); - M0.Init(Alloc,'M0'); - EXEC[0].Init(Alloc,'EXECL'); - EXEC[1].Init(Alloc,'EXECH'); - SCC.Init(Alloc,'SCC'); + VCC[0].Init(Emit,'VCCL'); + VCC[1].Init(Emit,'VCCH'); + M0.Init(Emit,'M0'); + EXEC[0].Init(Emit,'EXECL'); + EXEC[1].Init(Emit,'EXECH'); + SCC.Init(Emit,'SCC'); For i:=0 to 255 do begin Str(i,n); - VGRP[i].Init(Alloc,'V'+n); + VGRP[i].Init(Emit,'V'+n); + end; + FUnattach.Init(Emit,'UNATT'); +end; + +Function TsrRegsStory.AllocDep:PRegDNode; +begin + Result:=FDList.Pop_head; + if (Result=nil) then + begin + Result:=FUnattach.FEmit.Alloc(SizeOf(TRegDNode)); + end; +end; + +Procedure TsrRegsStory.FreeDep(node:PRegDNode); +begin + if (node=nil) then Exit; + node^:=Default(TRegDNode); + FDList.Push_head(node); +end; + +function TsrRegsStory.get_sdst7(SDST:Byte):PsrRegSlot; +begin + Case SDST of + 0..103:Result:=@SGRP[SDST]; + 106:Result:=@VCC[0]; + 107:Result:=@VCC[1]; + 124:Result:=@M0; + 126:Result:=@EXEC[0]; + 127:Result:=@EXEC[1]; + else + Result:=nil; end; - FUnattach.Init(Alloc,'UNATT'); end; function TsrRegsStory.get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean; @@ -145,20 +386,6 @@ begin end; end; -function TsrRegsStory.get_sdst7(SDST:Byte):PsrRegSlot; -begin - Case SDST of - 0..103:Result:=@SGRP[SDST]; - 106:Result:=@VCC[0]; - 107:Result:=@VCC[1]; - 124:Result:=@M0; - 126:Result:=@EXEC[0]; - 127:Result:=@EXEC[1]; - else - Result:=nil; - end; -end; - function TsrRegsStory.get_ssrc8(SSRC:Byte):PsrRegSlot; begin Case SSRC of @@ -179,6 +406,27 @@ begin end; end; +function TsrRegsStory.get_ssrc9(SSRC:Word):PsrRegSlot; +begin + Case SSRC of + 0..103:Result:=@SGRP[SSRC]; + 106:Result:=@VCC[0]; + 107:Result:=@VCC[1]; + 124:Result:=@M0; + 126:Result:=@EXEC[0]; + 127:Result:=@EXEC[1]; + + //251:Result:=@VCC[0]; //VCCZ + //252:Result:=@EXEC[0]; //EXECZ + + 253:Result:=@SCC; + //254:Write('LDS_DIRECT'); + 256..511:Result:=@VGRP[SSRC-256]; + else + Result:=nil; + end; +end; + function TsrRegsStory.get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean; begin Result:=True; @@ -209,27 +457,6 @@ begin end; end; -function TsrRegsStory.get_ssrc9(SSRC:Word):PsrRegSlot; -begin - Case SSRC of - 0..103:Result:=@SGRP[SSRC]; - 106:Result:=@VCC[0]; - 107:Result:=@VCC[1]; - 124:Result:=@M0; - 126:Result:=@EXEC[0]; - 127:Result:=@EXEC[1]; - - //251:Result:=@VCC[0]; //VCCZ - //252:Result:=@EXEC[0]; //EXECZ - - 253:Result:=@SCC; - //254:Write('LDS_DIRECT'); - 256..511:Result:=@VGRP[SSRC-256]; - else - Result:=nil; - end; -end; - function TsrRegsStory.get_vsrc8(VSRC:Byte):PsrRegSlot; begin Result:=@VGRP[VSRC]; @@ -350,85 +577,210 @@ end; //-- +Procedure TsrRegNode.Init; inline; +begin + fntype:=ntReg; +end; + function TsrRegNode.GetName:RawByteString; begin Result:=''; - if (pSlot<>nil) then Result:=pSlot^.rid; + if (FSlot<>nil) then Result:=FSlot^.rid; end; -Procedure TsrRegNode.mark_read; +Procedure TsrRegNode.AddDep(t:PsrNode); +var + pRegsStory:PsrRegsStory; + node:PRegDNode; begin - Inc(read_count); + if (t=nil) or (@Self=nil) then Exit; + + pRegsStory:=FSlot^.FEmit.GetRegsStory; + node:=pRegsStory^.AllocDep; + + node^.pNode:=t; + FDList.Push_head(node); end; -Procedure TsrRegNode.mark_unread; +Procedure TsrRegNode.RemDep(t:PsrNode); +var + pRegsStory:PsrRegsStory; + node,_prev:PRegDNode; begin - Assert(read_count<>0); - if (read_count<>0) then Dec(read_count); + if (t=nil) or (@Self=nil) then Exit; + node:=FDList.pHead; + _prev:=nil; + While (node<>nil) do + begin + if (node^.pNode=t) then + begin + if (_prev=nil) then + begin + FDList.pHead:=node^.pNext; + end else + begin + _prev^.pNext:=node^.pNext; + end; + + pRegsStory:=FSlot^.FEmit.GetRegsStory; + pRegsStory^.FreeDep(node); + + Exit; + end; + _prev:=node; + node:=node^.pNext; + end; end; -procedure TsrRegNode.SetConst(pConst:PsrConst); +function TsrRegNode.FirstDep:PRegDNode; begin - pWriter.SetParam(ntConst,pConst); - dtype:=pConst^.key.dtype; + Result:=nil; + if (@Self=nil) then Exit; + Result:=FDList.pHead; end; -procedure TsrRegNode.SetReg(pReg:PsrRegNode); +function TsrRegNode.GetDtype:TsrDataType; begin - Assert(@Self<>pReg); - pWriter.SetParam(ntReg,pReg); + Result:=F.dtype; +end; + +Procedure TsrRegNode.SetDtype(t:TsrDataType); +begin + F.dtype:=t; +end; + +function TsrRegNode.GetWeak:Boolean; +begin + Result:=F.weak; +end; + +Procedure TsrRegNode.SetWeak(t:Boolean); +begin + F.weak:=t; +end; + +Procedure TsrRegNode.SetWriter(t:PsrNode); +begin + if (@Self=nil) then Exit; + if (FWriter=t) then Exit; + + Assert(RegDown(t^.AsType(ntReg))<>@Self,'Circular reference'); + + if isUsed then + begin + t^.mark_read (@Self); + FWriter^.mark_unread(@Self); + end; + FWriter:=t; +end; + +Function TsrRegNode.GetWriter:PsrNode; +begin + Result:=nil; + if (@Self=nil) then Exit; + Result:=FWriter; +end; + +Procedure TsrRegNode.SetLine(t:Pointer); +begin + if (@Self=nil) then Exit; + if (FWriter<>nil) then + if (FWriter^.ntype.ClassName='ntOp') then + begin + Assert(FWriter=t); + end; + FLine:=t; end; function TsrRegNode.AsConst:PsrConst; begin - Result:=nil; - if (@Self=nil) then Exit; - if (pWriter.ntype<>ntConst) then Exit; - Result:=pWriter.pData; -end; - -function TsrRegNode.AsOp:Pointer; -begin - Result:=nil; - if (@Self=nil) then Exit; - if (pWriter.ntype<>ntOp) then Exit; - Result:=pWriter.pData; + if (@Self=nil) then Exit(nil); + Result:=PsrConst(FWriter^.AsType(ntConst)); end; function TsrRegNode.AsReg:PsrRegNode; begin - Result:=nil; - if (@Self=nil) then Exit; - if (pWriter.ntype<>ntReg) then Exit; - Result:=pWriter.pData; + if (@Self=nil) then Exit(nil); + Result:=PsrRegNode(FWriter^.AsType(ntReg)); end; function TsrRegNode.is_const:Boolean; begin - Result:=(pWriter.ntype=ntConst); + if (@Self=nil) then Exit(False); + Result:=FWriter^.IsType(ntConst); end; function TsrRegNode.is_bool:Boolean; begin + if (@Self=nil) then Exit(False); Result:=(dtype=dtBool); end; function TsrRegNode.is_bool_or_const_bool:Boolean; begin + if (@Self=nil) then Exit(False); Result:=is_bool or - (is_const and (AsConst<>nil) and AsConst^.isBoolVal); + (is_const and AsConst^.isBoolVal); end; function TsrRegNode.is_unknow:Boolean; begin + if (@Self=nil) then Exit(True); Result:=(dtype=dtUnknow); end; +function TsrRegNode.GetPrintName:RawByteString; +begin + if is_const then + begin + Result:=AsConst^.GetPrintName; + end else + begin + Assert(ID.Alloc); + Result:='r'+IntToStr(ID.ID); + end; +end; + +// + + +Procedure TsrRegPair.SetWriter(t:PsrNode); +begin + if (FWriter=t) then Exit; + if isUsed then + begin + t^.mark_read (@Self); + FWriter^.mark_unread(@Self); + end; + FWriter:=t; +end; + +Procedure TsrRegPair.SetDst0(r:PsrNode); +begin + if (FDst0=r) then Exit; + FDst0^.ResetWriter(@Self); + FDst0:=r; + FDst0^.SetWriter(@Self,pLine); +end; + +Procedure TsrRegPair.SetDst1(r:PsrNode); +begin + if (FDst1=r) then Exit; + FDst1^.ResetWriter(@Self); + FDst1:=r; + FDst1^.SetWriter(@Self,pLine); +end; + +Procedure TsrRegPair.Init; inline; +begin + fntype:=ntRegPair; +end; + //-- -Procedure TsrRegSlot.Init(a:TfnAlloc;const n:TString5); +Procedure TsrRegSlot.Init(Emit:TCustomEmit;const n:TString5); begin - Alloc:=a; + FEmit:=Emit; rid :=n; end; @@ -442,12 +794,22 @@ begin Result:=pStory.pTail; end; +function TsrRegSlot.isBoolOnly:Boolean; +begin + Result:=(rid='SCC'); +end; + function TsrRegSlot.New(pLine:Pointer;rtype:TsrDataType):PsrRegNode; var node:PsrRegNode; begin - node:=Alloc(SizeOf(TsrRegNode)); - node^.pSlot:=@Self; + if isBoolOnly then + begin + rtype:=dtBool; + end; + node:=FEmit.Alloc(SizeOf(TsrRegNode)); + node^.Init; + node^.FSlot:=@Self; node^.dtype:=rtype; node^.pLine:=pLine; pStory.Push_tail(node); @@ -458,19 +820,85 @@ function TsrRegSlot.NewAfter(rtype:TsrDataType;r:PsrRegNode):PsrRegNode; var node:PsrRegNode; begin - node:=Alloc(SizeOf(TsrRegNode)); - node^.pSlot:=@Self; + if isBoolOnly then + begin + rtype:=dtBool; + end; + node:=FEmit.Alloc(SizeOf(TsrRegNode)); + node^.Init; + node^.FSlot:=@Self; node^.dtype:=rtype; node^.pLine:=r^.pLine; pStory.InsertAfter(r,node); Result:=node; end; +function TsrRegSlot.NewBefore(rtype:TsrDataType;r:PsrRegNode):PsrRegNode; +var + node:PsrRegNode; +begin + if isBoolOnly then + begin + rtype:=dtBool; + end; + node:=FEmit.Alloc(SizeOf(TsrRegNode)); + node^.Init; + node^.FSlot:=@Self; + node^.dtype:=rtype; + node^.pLine:=r^.pLine; + pStory.InsertBefore(r,node); + Result:=node; +end; + procedure TsrRegSlot.Remove(r:PsrRegNode); begin if (r=nil) then Exit; pStory.Remove(r); end; +// + +function RegDown(node:PsrRegNode):PsrRegNode; +var + tmp:PsrRegNode; +begin + //backtrace + Result:=node; + While (Result<>nil) do + begin + tmp:=Result^.AsReg; //next + if (tmp=nil) then Break; + Assert(tmp<>Result); + Result:=tmp; + end; +end; + +function RegDownSlot(node:PsrRegNode):PsrRegNode; +var + tmp:PsrRegNode; +begin + //backtrace + Result:=node; + While (Result<>nil) do + begin + tmp:=Result^.AsReg; //next + if (tmp=nil) then Break; + Assert(tmp<>Result); + if (tmp^.pSlot<>Result^.pSlot) then Break; + Result:=tmp; + end; +end; + +function CompareReg(r1,r2:PsrRegNode):Boolean; +begin + r1:=RegDown(r1); + r2:=RegDown(r2); + Result:=(r1=r2); + if not Result then + begin + Result:=CompareConst(r1^.AsConst,r2^.AsConst); + end; +end; + end. diff --git a/spirv/srType.pas b/spirv/srType.pas new file mode 100644 index 00000000..fcb80576 --- /dev/null +++ b/spirv/srType.pas @@ -0,0 +1,623 @@ +unit srType; + +{$mode objfpc}{$H+} +{$modeswitch typehelpers} + +interface + +uses + bittype, + Half16; + +type + TsrDataType=( + //Real types + dtUnknow, + dtBool, + + dtHalf16, + dtFloat32, + dtFloat64, + + dtInt8, + dtUint8, + + dtInt16, + dtUint16, + + dtInt32, + dtUint32, + + dtInt64, + dtUint64, + + //Composite types + dtVec2b, + dtVec3b, + dtVec4b, + + dtStruct2u, + + dtVec2u8, + dtVec4u8, + + dtVec2i8, + dtVec4i8, + + dtVec2u16, + dtVec4u16, + + dtVec2i16, + dtVec4i16, + + dtVec2u, + dtVec3u, + dtVec4u, + + dtVec2i, + dtVec3i, + dtVec4i, + + dtVec2h, + dtVec4h, + + dtVec2f, + dtVec3f, + dtVec4f, + + //Spirv types + dtTypeVoid, + dtTypeFunction, + dtTypePointer, + dtTypeStruct, + dtTypeArray, + dtTypeRuntimeArray, + dtTypeImage, + dtTypeSampler, + dtTypeSampledImage, + + dtString, + dtConstant + ); + + TsrDataTypeHelper = type helper for TsrDataType + function isInt:Boolean; + function isFloat:Boolean; + function isBool:Boolean; + function isVector:Boolean; + function isScalar:Boolean; + function Child:TsrDataType; + function Count:Byte; + function Sign:Byte; + function BitSize:Byte; + function High:QWORD; + function AsVector(_count:Byte):TsrDataType; + end; + + Pvec2f=^Tvec2f; + Tvec2f=array[0..1] of Single; + + Pvec3f=^Tvec3f; + Tvec3f=array[0..2] of Single; + + Pvec4f=^Tvec4f; + Tvec4f=array[0..3] of Single; + + Pvec2h=^Tvec2h; + Tvec2h=array[0..1] of THalf16; + + Pvec4h=^Tvec4h; + Tvec4h=array[0..3] of THalf16; + + //child - result type + TsrTypeImageInfo=bitpacked record + Dim :bit3; //Dim.* + Depth :bit2; //0:no,1:yes,2:any + Arrayed:bit1; //0:no,1:yes + MS :bit1; //0:no,1:yes + Sampled:bit2; //0:runtime,1:sampling,2:read/write + Format :bit23; //ImageFormat.* + end; + + PsrImageInfo=^TsrImageInfo; + TsrImageInfo=packed record + dtype:TsrDataType; + tinfo:TsrTypeImageInfo; + end; + +function type_get_base_name1(dtype:TsrDataType):RawByteString; +function LazyType2(t1,t2:TsrDataType):TsrDataType; +function LazyType3(t1,t2,t3:TsrDataType):TsrDataType; +function StoreType(t:TsrDataType):TsrDataType; +function CompareType(rtype1,rtype2:TsrDataType):Boolean; +function TryBitcastType(rtype1,rtype2:TsrDataType):Boolean; +function is_unprep_type(old,new:TsrDataType;weak:Boolean):Boolean; + +implementation + +function type_get_base_name1(dtype:TsrDataType):RawByteString; +begin + Result:=''; + case dtype of + + dtBool :Result:='bool'; + + dtHalf16 :Result:='half'; + dtFloat32 :Result:='float'; + dtFloat64 :Result:='double'; + + dtInt8 :Result:='int8'; + dtUint8 :Result:='uint8'; + + dtInt16 :Result:='int16'; + dtUint16 :Result:='uint16'; + + dtInt32 :Result:='int'; + dtUint32 :Result:='uint'; + + dtInt64 :Result:='int64'; + dtUint64 :Result:='uint64'; + + //Composite types + dtVec2b :Result:='bvec2'; + dtVec3b :Result:='bvec3'; + dtVec4b :Result:='bvec4'; + + dtStruct2u :Result:='rec2u'; + + dtVec2u8 :Result:='u8vec2'; + dtVec4u8 :Result:='u8vec4'; + + dtVec2i8 :Result:='i8vec2'; + dtVec4i8 :Result:='i8vec4'; + + dtVec2u16 :Result:='u16vec2'; + dtVec4u16 :Result:='u16vec4'; + + dtVec2i16 :Result:='i16vec2'; + dtVec4i16 :Result:='i16vec4'; + + dtVec2u :Result:='uvec2'; + dtVec3u :Result:='uvec3'; + dtVec4u :Result:='uvec4'; + + dtVec2i :Result:='ivec2'; + dtVec3i :Result:='ivec3'; + dtVec4i :Result:='ivec4'; + + dtVec2h :Result:='hvec2'; + dtVec4h :Result:='hvec4'; + + dtVec2f :Result:='vec2'; + dtVec3f :Result:='vec3'; + dtVec4f :Result:='vec4'; + + dtTypeVoid :Result:='void'; + dtTypeSampler:Result:='samp'; + + else; + end; +end; + +function LazyType2(t1,t2:TsrDataType):TsrDataType; +begin + if (t1<>dtUnknow) then Result:=t1 else Result:=t2; +end; + +function LazyType3(t1,t2,t3:TsrDataType):TsrDataType; +begin + if (t1<>dtUnknow) then Result:=t1 else Result:=t2; + if (Result=dtUnknow) then Result:=t3; +end; + +function StoreType(t:TsrDataType):TsrDataType; +begin + if (t=dtBool) then + Result:=dtUint32 + else + Result:=t; +end; + +function TsrDataTypeHelper.isInt:Boolean; +begin + Case Self of + dtInt8, + dtUint8, + + dtInt16, + dtUint16, + + dtInt32, + dtUint32, + + dtInt64, + dtUint64, + + dtStruct2u, + + dtVec2u8, + dtVec4u8, + + dtVec2i8, + dtVec4i8, + + dtVec2u16, + dtVec4u16, + + dtVec2i16, + dtVec4i16, + + dtVec2u, + dtVec3u, + dtVec4u, + + dtVec2i, + dtVec3i, + dtVec4i, + + dtVec2f, + dtVec3f, + dtVec4f: + Result:=True; + + else + Result:=False; + end; +end; + +function TsrDataTypeHelper.isFloat:Boolean; +begin + Case Self of + dtHalf16, + dtFloat32, + dtFloat64, + + dtVec2h, + dtVec4h, + + dtVec2f, + dtVec3f, + dtVec4f: + Result:=True; + + else + Result:=False; + end; +end; + +function TsrDataTypeHelper.isBool:Boolean; +begin + Case Self of + dtBool, + + dtVec2b, + dtVec3b, + dtVec4b:Result:=True; + else + Result:=False; + end; +end; + +function TsrDataTypeHelper.isVector:Boolean; +begin + Case Self of + dtVec2b, + dtVec3b, + dtVec4b, + + dtStruct2u, + + dtVec2u8, + dtVec4u8, + + dtVec2i8, + dtVec4i8, + + dtVec2u16, + dtVec4u16, + + dtVec2i16, + dtVec4i16, + + dtVec2u, + dtVec3u, + dtVec4u, + + dtVec2i, + dtVec3i, + dtVec4i, + + dtVec2h, + dtVec4h, + + dtVec2f, + dtVec3f, + dtVec4f: + Result:=True; + + else + Result:=False; + end; +end; + +function TsrDataTypeHelper.isScalar:Boolean; +begin + Result:=not isVector; +end; + +function TsrDataTypeHelper.Child:TsrDataType; +begin + Case Self of + dtVec2b, + dtVec3b, + dtVec4b:Result:=dtBool; + + dtVec2u8, + dtVec4u8:Result:=dtUint8; + + dtVec2i8, + dtVec4i8:Result:=dtInt8; + + dtVec2u16, + dtVec4u16:Result:=dtUint16; + + dtVec2i16, + dtVec4i16:Result:=dtInt16; + + dtStruct2u, + dtVec2u, + dtVec3u, + dtVec4u:Result:=dtUint32; + + dtVec2i, + dtVec3i, + dtVec4i:Result:=dtInt32; + + dtVec2h, + dtVec4h:Result:=dtHalf16; + + dtVec2f, + dtVec3f, + dtVec4f:Result:=dtFloat32; + else + Result:=dtUnknow; + end; +end; + +function TsrDataTypeHelper.Count:Byte; +begin + Case Self of + dtVec2b, + dtVec2u8, + dtVec2i8, + dtVec2u16, + dtVec2i16, + dtVec2u, + dtVec2i, + dtVec2h, + dtVec2f, + dtStruct2u:Result:=2; + + dtVec3b, + dtVec3u, + dtVec3i, + dtVec3f:Result:=3; + + dtVec4b, + dtVec4u8, + dtVec4i8, + dtVec4u16, + dtVec4i16, + dtVec4u, + dtVec4i, + dtVec4f, + dtVec4h:Result:=4; + else + Result:=0; + end; +end; + +function TsrDataTypeHelper.Sign:Byte; +begin + Case Self of + dtInt8, + dtInt16, + dtInt32, + dtInt64, + + dtHalf16, + dtFloat32, + dtFloat64, + dtVec2h, + dtVec4h, + dtVec2f, + dtVec3f, + dtVec4f:Result:=1; + + else + Result:=0; + end; +end; + +function TsrDataTypeHelper.BitSize:Byte; +begin + Case Self of + dtInt8, + dtUint8:Result:=8; + + dtHalf16, + dtInt16, + dtUint16, + dtVec2u8, + dtVec2i8:Result:=16; + + dtUnknow, + dtBool, //for typecast + dtFloat32, + dtInt32, + dtUint32, + dtVec4u8, + dtVec4i8, + dtVec2u16, + dtVec2i16, + dtVec2h:Result:=32; + + dtFloat64, + dtInt64, + dtUint64, + dtVec4u16, + dtVec4i16, + dtVec2f, + dtVec4h, + dtStruct2u:Result:=64; + + dtVec3u, + dtVec3i, + dtVec3f:Result:=96; + + dtVec4u, + dtVec4i, + dtVec4f:Result:=128; + + else + Result:=0; + end; +end; + +function TsrDataTypeHelper.High:QWORD; +var + s:Byte; +begin + Result:=0; + if (Self=dtBool) then Exit(1); + s:=BitSize; + Case s of + 8:Result:=System.High(Byte); + 16:Result:=System.High(Word); + 32:Result:=System.High(DWord); + 64:Result:=System.High(QWord); + else + Assert(false); + end; +end; + +function TsrDataTypeHelper.AsVector(_count:Byte):TsrDataType; +begin + Result:=dtUnknow; + if (_count<=1) then Exit(Self); + Case Self of + dtBool: + Case _count of + 2:Result:=dtVec2b; + 3:Result:=dtVec3b; + 4:Result:=dtVec4b; + end; + dtUint8: + Case _count of + 2:Result:=dtVec2u8; + 4:Result:=dtVec4u8; + end; + dtInt8: + Case _count of + 2:Result:=dtVec2i8; + 4:Result:=dtVec4i8; + end; + dtUint16: + Case _count of + 2:Result:=dtVec2u16; + 4:Result:=dtVec4u16; + end; + dtInt16: + Case _count of + 2:Result:=dtVec2i16; + 4:Result:=dtVec4i16; + end; + dtHalf16: + Case _count of + 2:Result:=dtVec2h; + 4:Result:=dtVec4h; + end; + dtFloat32: + Case _count of + 2:Result:=dtVec2f; + 3:Result:=dtVec3f; + 4:Result:=dtVec4f; + end; + dtInt32: + Case _count of + 2:Result:=dtVec2i; + 3:Result:=dtVec3i; + 4:Result:=dtVec4i; + end; + dtUint32: + Case _count of + 2:Result:=dtVec2u; + 3:Result:=dtVec3u; + 4:Result:=dtVec4u; + end; + else; + end; +end; + +function CompareType(rtype1,rtype2:TsrDataType):Boolean; +begin + Case rtype1 of + dtInt8, + dtUint8:Result:=(rtype2=dtInt8) or (rtype2=dtUint8); + + dtInt16, + dtUint16:Result:=(rtype2=dtInt16) or (rtype2=dtUint16); + + dtInt32, + dtUint32:Result:=(rtype2=dtInt32) or (rtype2=dtUint32); + + dtVec2u8, + dtVec2i8:Result:=(rtype2=dtVec2u8) or (rtype2=dtVec2i8); + + dtVec4u8, + dtVec4i8:Result:=(rtype2=dtVec4u8) or (rtype2=dtVec4i8); + + dtVec2u16, + dtVec2i16:Result:=(rtype2=dtVec2u16) or (rtype2=dtVec2i16); + + dtVec4u16, + dtVec4i16:Result:=(rtype2=dtVec4u16) or (rtype2=dtVec4i16); + + dtVec2u, + dtVec2i:Result:=(rtype2=dtVec2u) or (rtype2=dtVec2i); + + dtVec3u, + dtVec3i:Result:=(rtype2=dtVec3u) or (rtype2=dtVec3i); + + dtVec4u, + dtVec4i:Result:=(rtype2=dtVec4u) or (rtype2=dtVec4i); + + else + Result:=(rtype1=rtype2); + end; +end; + +function TryBitcastType(rtype1,rtype2:TsrDataType):Boolean; +var + s,d:Byte; +begin + s:=rtype1.BitSize; + d:=rtype2.BitSize; + Result:=(s<>0) and (d<>0) and (s=d); +end; + +function is_unprep_type(old,new:TsrDataType;weak:Boolean):Boolean; +begin + Result:=False; + if (new<>dtUnknow) and (old<>new) then + begin + Case old of + dtUnknow:Result:=True; + dtBool :Result:=weak; + else; + end; + end; +end; + +end. + diff --git a/spirv/srTypes.pas b/spirv/srTypes.pas index 2e4a153e..0ff40819 100644 --- a/spirv/srTypes.pas +++ b/spirv/srTypes.pas @@ -5,353 +5,502 @@ unit srTypes; interface uses - bittype, - Half16, - spirv, - srNodes, - srRefId; + sysutils, + spirv, + srType, + ginodes, + srNode, + srLiteral, + srRefId; type - TsrDataType=( - //Real types - dtUnknow, - dtBool, - - dtFloat32, - dtHalf16, - - dtInt8, - dtUint8, - - dtInt16, - dtUint16, - - dtInt32, - dtUint32, - - dtInt64, - dtUint64, - - //Composite types - dtVec2b, - dtVec3b, - dtVec4b, - - dtStruct2u, - - dtVec2u8, - dtVec4u8, - - dtVec2i8, - dtVec4i8, - - dtVec2u16, - dtVec4u16, - - dtVec2i16, - dtVec4i16, - - dtVec2u, - dtVec3u, - dtVec4u, - - dtVec2i, - dtVec3i, - dtVec4i, - - dtVec2f, - dtVec3f, - dtVec4f, - - dtVec2h, - dtVec4h, - - //Spirv types - dtTypeVoid, - dtTypeFunction, - dtTypePointer, - dtTypeStruct, - dtTypeArray, - dtTypeRuntimeArray, - dtTypeImage, - dtTypeSampler, - dtTypeSampledImage - ); - - Pvec2f=^Tvec2f; - Tvec2f=array[0..1] of Single; - - Pvec3f=^Tvec3f; - Tvec3f=array[0..2] of Single; - - Pvec4f=^Tvec4f; - Tvec4f=array[0..3] of Single; - - Pvec2h=^Tvec2h; - Tvec2h=array[0..1] of THalf16; - - Pvec4h=^Tvec4h; - Tvec4h=array[0..3] of THalf16; + ntType=class(TsrNodeVmt) + class Procedure zero_read (node:PsrNode); override; + class Procedure zero_unread (node:PsrNode); override; + class function Next (node:PsrNode):Pointer; override; + class function Prev (node:PsrNode):Pointer; override; + class function GetPrintName(node:PsrNode):RawByteString; override; + class function GetRef (node:PsrNode):Pointer; override; + end; PPsrType=^PsrType; PsrType=^TsrType; - - //child - result type - TsrTypeImageInfo=bitpacked record - Dim :bit3; //Dim.* - Depth :bit2; //0:no,1:yes,2:any - Arrayed:bit1; //0:no,1:yes - MS :bit1; //0:no,1:yes - Sampled:bit2; //0:runtime,1:sampling,2:read/write - Format :bit23; //ImageFormat.* - end; - - PsrImageInfo=^TsrImageInfo; - TsrImageInfo=packed record - dtype:TsrDataType; - tinfo:TsrTypeImageInfo; - end; - - TsrType=object - pPrev,pNext,pLeft,pRight:PsrType; - //---- - ID:TsrRefId; //post id - read_count:DWORD; - dtype:TsrDataType; - key:packed record - OpId:DWORD; - count:DWORD; - ext:packed record - case byte of - 0:(int_size,int_sign:DWORD); - 1:(float_size:DWORD); - 2:(storage_class:DWORD); - 3:(pField:Pointer); - 4:(array_count,array_stride:DWORD); - 5:(vector_count:DWORD); - 6:(image:TsrTypeImageInfo); - end; - end; - Data:record end; - function c(n1,n2:PsrType):Integer; static; - Procedure mark_read; - Procedure mark_unread; - function GetCompItem(i:DWORD):PsrType; inline; - Procedure SetCompItem(i:DWORD;p:PsrType); inline; - Procedure _mark_read_child; - Procedure _mark_unread_child; - Procedure Clear; + TsrType=packed object(TsrNode) + private + pPrev,pNext,pLeft,pRight:PsrType; + // + ID:TsrRefId; //post id + fdtype:TsrDataType; + fsize:DWORD; + fOpId:WORD; + fcount:WORD; + pData:PPsrNode; + function c(n1,n2:PsrType):Integer; static; + public + property size:DWORD read fsize; + property OpId:WORD read fOpId; + property ItemCount:WORD read fcount; + Procedure Init; inline; + function dtype:TsrDataType; + function GetItem(i:Word):PsrNode; + function GetDWORD(i:Word):DWORD; + function array_stride:DWORD; + function array_count:DWORD; + function storage_class:DWORD; + function image_info:TsrTypeImageInfo; + function GetPrintName:RawByteString; end; + PsrTypeList=^TsrTypeList; TsrTypeList=object type TNodeList=specialize TNodeList; TNodeFetch=specialize TNodeFetch; var - Alloc:TfnAlloc; + FEmit:TCustomEmit; FList:TNodeList; FNTree:TNodeFetch; - function _New(count:DWORD):PsrType; - function _Insert(node:PsrType):PsrType; - function _Fetch(node:PsrType):PsrType; - function _FetchVector(dtype,ctype:TsrDataType;vector_count:DWORD):PsrType; - function Fetch(dtype:TsrDataType):PsrType; - function FetchPointer(child:PsrType;storage_class:DWORD):PsrType; - function FetchFunction(ret:PsrType):PsrType; - function FetchFunction1(ret,param:PsrType):PsrType; - function FetchStruct(child:PsrType;pField:Pointer):PsrType; - function FetchStructNode(node:PsrType;count:DWORD;pField:Pointer):PsrType; - function FetchArrayNode(node,child:PsrType;array_count,array_stride:DWORD):PsrType; - function FetchArray(child:PsrType;array_count,array_stride:DWORD):PsrType; - function FetchRuntimeArray(child:PsrType;array_stride:DWORD):PsrType; - function FetchImage(child:PsrType;image_info:TsrTypeImageInfo):PsrType; - function FetchSampledImage(child:PsrType):PsrType; + Procedure Init(Emit:TCustomEmit); + function _Insert(node:PsrType;copy:Boolean):PsrType; + function _Fetch(node:PsrType;copy:Boolean):PsrType; + function _Fetch0(dtype:TsrDataType;OpId:DWORD):PsrType; + function _FetchVector(dtype:TsrDataType):PsrType; + function _FetchInt(dtype:TsrDataType):PsrType; + function _FetchFloat(dtype:TsrDataType):PsrType; + function _FetchStruct2(dtype:TsrDataType):PsrType; + function _FetchConst(dtype:TsrDataType;Value:QWORD):PsrType; + function Fetch(dtype:TsrDataType):PsrType; + function FetchPointer(child:PsrType;storage_class:DWORD):PsrType; + function FetchFunction(ret:PsrType):PsrType; + function FetchFunction(copy:Boolean;count:Byte;pData:PPsrType):PsrType; + function FetchStruct (count:Word;pData:PPsrType;copy:Boolean;_size:DWORD):PsrType; + function InsertStruct(count:Word;pData:PPsrType;copy:Boolean;_size:DWORD):PsrType; + function FetchArray(child:PsrType;array_count:DWORD):PsrType; + function FetchRuntimeArray(child:PsrType):PsrType; + function FetchImage(child:PsrType;image_info:TsrTypeImageInfo):PsrType; + function FetchSampledImage(child:PsrType):PsrType; + function First:PsrType; inline; end; -const - ExtImgBuf:TsrTypeImageInfo=( - Dim :0; //Dim1D - Depth :0; - Arrayed:0; - MS :0; - Sampled:2; - Format :0; //Unknown - ); - - ExtImage2D:TsrTypeImageInfo=( - Dim :1; //Dim2D - Depth :0; - Arrayed:0; - MS :0; - Sampled:1; - Format :0; //Unknown - ); - -function _GetNodeSize(count:DWORD):ptruint; inline; -function LazyType2(t1,t2:TsrDataType):TsrDataType; -function LazyType3(t1,t2,t3:TsrDataType):TsrDataType; -function isIntVector(rtype:TsrDataType):Boolean; inline; -function isIntScalar(rtype:TsrDataType):Boolean; inline; -function GetVecChild(rtype:TsrDataType):TsrDataType; -function GetVecCount(rtype:TsrDataType):Byte; -Function GetVecType(elem:TsrDataType;count:Byte):TsrDataType; -function isVector(rtype:TsrDataType):Boolean; inline; -function GetTypeHigh(rtype:TsrDataType):QWORD; -function CompareType(rtype1,rtype2:TsrDataType):Boolean; -function SignType(rtype:TsrDataType):Byte; -function BitSizeType(rtype:TsrDataType):Byte; -function TryBitcastType(rtype1,rtype2:TsrDataType):Boolean; - implementation +// + +class Procedure ntType.zero_read(node:PsrNode); +var + i:DWORD; +begin + With PsrType(node)^ do + begin + if (fcount<>0) then + For i:=0 to fcount-1 do + begin + GetItem(i)^.mark_read(node); + end; + end; +end; + +class Procedure ntType.zero_unread(node:PsrNode); +var + i:DWORD; +begin + With PsrType(node)^ do + begin + if (fcount<>0) then + For i:=0 to fcount-1 do + begin + GetItem(i)^.mark_unread(node); + end; + end; +end; + +class function ntType.Next(node:PsrNode):Pointer; +begin + Result:=PsrType(node)^.pNext; +end; + +class function ntType.Prev(node:PsrNode):Pointer; +begin + Result:=PsrType(node)^.pPrev; +end; + +class function ntType.GetPrintName(node:PsrNode):RawByteString; +begin + Result:=PsrType(node)^.GetPrintName; +end; + +class function ntType.GetRef(node:PsrNode):Pointer; +begin + Result:=@PsrType(node)^.ID; +end; + +// + +Procedure TsrType.Init; inline; +begin + fntype:=ntType; +end; + function TsrType.c(n1,n2:PsrType):Integer; begin - Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrType.key)); + //first OpId + Result:=Integer(n1^.fOpId>n2^.fOpId)-Integer(n1^.fOpId0) then Exit; - Result:=ComparePtruint(@n1^.Data,@n2^.Data,n1^.key.count); + //second fCount + Result:=Integer(n1^.fCount>n2^.fCount)-Integer(n1^.fCount0) then Exit; + //third pData + Result:=ComparePtruint(PPtruint(n1^.pData),PPtruint(n2^.pData),n1^.fCount); end; -Procedure TsrType.mark_read; +function TsrType.dtype:TsrDataType; begin - Inc(read_count); + Result:=dtUnknow; + if (@Self=nil) then Exit; + Result:=fdtype; end; -Procedure TsrType.mark_unread; +function TsrType.GetItem(i:Word):PsrNode; begin - if (read_count<>0) then Dec(read_count); + if (i>fCount) then Exit(nil); + Result:=pData[i]; end; - -function TsrType.GetCompItem(i:DWORD):PsrType; inline; -begin - Result:=PPsrType(@Data)[i]; -end; - -Procedure TsrType.SetCompItem(i:DWORD;p:PsrType); inline; -begin - PPsrType(@Data)[i]:=p; -end; - -Procedure TsrType._mark_read_child; +function TsrType.GetDWORD(i:Word):DWORD; var - i:DWORD; + pCount:PsrLiteral; begin - if (key.count<>0) then - For i:=0 to key.count-1 do - begin - GetCompItem(i)^.mark_read; - end; + Result:=0; + if (i>fCount) then Exit; + pCount:=pData[i]^.AsType(ntLiteral); + if (pCount=nil) then Exit; + Result:=pCount^.Value; end; -Procedure TsrType._mark_unread_child; +function TsrType.array_stride:DWORD; var - i:DWORD; + child:PsrType; begin - if (key.count<>0) then - For i:=0 to key.count-1 do - begin - GetCompItem(i)^.mark_unread; - end; + Result:=0; + + Case fdtype of + dtTypeArray:; + dtTypeRuntimeArray:; + else + Exit; + end; + + child:=GetItem(0)^.AsType(ntType); + if (child=nil) then Exit; + + Result:=child^.fsize; end; -Procedure TsrType.Clear; +function TsrType.array_count:DWORD; var - i:DWORD; + pConst:PsrType; begin - if (key.count<>0) then - begin - For i:=0 to key.count-1 do - begin - GetCompItem(i)^.mark_unread; - SetCompItem(i,nil); - end; - key.count:=0; + Result:=0; + if (fdtype<>dtTypeArray) then Exit; + pConst:=GetItem(1)^.AsType(ntType); + if (pConst=nil) then Exit; + Result:=pConst^.GetDWORD(1); +end; + +function TsrType.storage_class:DWORD; +begin + Result:=0; + if (fdtype<>dtTypePointer) then Exit; + Result:=GetDWORD(0); +end; + +function TsrType.image_info:TsrTypeImageInfo; + +begin + Result:=Default(TsrTypeImageInfo); + if (fdtype<>dtTypeImage) then Exit; + if (fCount<>7) then Exit; + // + Result.Dim :=GetDWORD(1); + Result.Depth :=GetDWORD(2); + Result.Arrayed:=GetDWORD(3); + Result.MS :=GetDWORD(4); + Result.Sampled:=GetDWORD(5); + Result.Format :=GetDWORD(6); +end; + +function type_get_base_name2(node:PsrType):RawByteString; +var + R:PsrRefId; + child:PsrType; +begin + Result:=''; + case node^.dtype of + dtTypeImage: + begin + R:=node^.GetRef; + Assert(R<>nil ,'type_get_base_name2$1'); + Assert(R^.Alloc,'type_get_base_name2$2'); + Result:='ti'+IntToStr(R^.ID); + end; + dtTypeSampledImage: + begin + child:=node^.GetItem(0)^.AsType(ntType); + if (child=nil) then Exit; + Result:=type_get_base_name2(child); + if (Result='') then Exit; + Result:='tm'+Result; + end; + dtTypeArray: + begin + child:=node^.GetItem(0)^.AsType(ntType); + if (child=nil) then Exit; + Result:=type_get_base_name2(child); + if (Result='') then Exit; + Result:='ta'+Result+IntToStr(node^.array_count); + end; + dtTypeRuntimeArray: + begin + child:=node^.GetItem(0)^.AsType(ntType); + if (child=nil) then Exit; + Result:=type_get_base_name2(child); + if (Result='') then Exit; + Result:='tr'+Result; + end; + dtTypeStruct: + begin + Assert(node^.ID.Alloc); + Result:='ts'+IntToStr(node^.ID.ID); + end; + dtTypeFunction: + begin + child:=node^.GetItem(0)^.AsType(ntType); + if (child=nil) then Exit; + Result:=type_get_base_name2(child); + if (Result='') then Exit; + Result:='tf'+Result; + end; + dtConstant: + begin + Result:='tc'+IntToStr(node^.GetDWORD(1)); + end; + else + Result:=type_get_base_name1(node^.dtype); end; end; -function _GetNodeSize(count:DWORD):ptruint; inline; +function type_get_base_name3(node:PsrType):RawByteString; +var + child:PsrType; begin - Result:=SizeOf(TsrType)+SizeOf(Pointer)*count; -end; - -function TsrTypeList._New(count:DWORD):PsrType; -begin - Result:=Alloc(_GetNodeSize(count)); -end; - -function TsrTypeList._Insert(node:PsrType):PsrType; -begin - Result:=FNTree.Find(node); - if (Result=nil) then - begin - FNTree.Insert(node); - FList.Push_tail(node); - Result:=node; - end else - begin - node^._mark_unread_child; + case node^.dtype of + dtTypePointer: + begin + child:=node^.GetItem(1)^.AsType(ntType); + if (child=nil) then Exit; + Result:=type_get_base_name2(child); + if (Result='') then Exit; + Case node^.storage_class of + StorageClass.UniformConstant :Result:='p'+Result+'_uc'; + StorageClass.Input :Result:='p'+Result+'_in'; + StorageClass.Uniform :Result:='p'+Result+'_uf'; + StorageClass.Output :Result:='p'+Result+'_ot'; + StorageClass.Workgroup :Result:='p'+Result+'_wg'; + StorageClass.CrossWorkgroup :Result:='p'+Result+'_cw'; + StorageClass.Private_ :Result:='p'+Result+'_pv'; + StorageClass.Function_ :Result:='p'+Result+'_fc'; + StorageClass.PushConstant :Result:='p'+Result+'_pc'; + StorageClass.Image :Result:='p'+Result+'_im'; + StorageClass.StorageBuffer :Result:='p'+Result+'_sb'; + else + Exit(''); + end; + end; + else + begin + Result:=type_get_base_name2(node); + end; end; end; -function TsrTypeList._Fetch(node:PsrType):PsrType; +function TsrType.GetPrintName:RawByteString; +begin + Result:=type_get_base_name3(@Self); + if (Result='') then + begin + Assert(ID.Alloc); + Result:='t'+IntToStr(ID.ID); + end; +end; + +// + +Procedure TsrTypeList.Init(Emit:TCustomEmit); +begin + FEmit:=Emit; +end; + +function TsrTypeList._Insert(node:PsrType;copy:Boolean):PsrType; var size:ptruint; +begin + Result:=FEmit.Alloc(SizeOf(TsrType)); + Move(node^,Result^,SizeOf(TsrType)); + + if copy and (node^.fCount<>0) then + begin + size:=SizeOf(Pointer)*node^.fCount; + Result^.pData:=FEmit.Alloc(size); + Move(node^.pData^,Result^.pData^,Size); + end; + + FList.Push_tail(Result); +end; + +function TsrTypeList._Fetch(node:PsrType;copy:Boolean):PsrType; begin Result:=FNTree.Find(node); if (Result=nil) then begin - size:=_GetNodeSize(node^.key.count); - Result:=Alloc(size); - Move(node^,Result^,Size); + Result:=_Insert(node,copy); FNTree.Insert(Result); - FList.Push_tail(Result); - end else - begin - node^._mark_unread_child; end; end; -function TsrTypeList._FetchVector(dtype,ctype:TsrDataType;vector_count:DWORD):PsrType; +function TsrTypeList._Fetch0(dtype:TsrDataType;OpId:DWORD):PsrType; var - rec:record - node:TsrType; - align:Pointer; - end; - child:PsrType; + node:TsrType; begin Result:=nil; - child:=Fetch(ctype); - rec.node:=Default(TsrType); - rec.node.dtype:=dtype; - rec.node.key.OpId:=Op.OpTypeVector; - rec.node.key.ext.vector_count:=vector_count; - rec.node.key.count:=1; - rec.node.SetCompItem(0,child); - Result:=_Fetch(@rec.node); - Result^.mark_read; + // + node:=Default(TsrType); + node.Init; + node.fdtype:=dtype; + node.fsize :=dtype.BitSize div 8; + node.fOpId :=OpId; + Result:=_Fetch(@node,True); +end; + +function TsrTypeList._FetchVector(dtype:TsrDataType):PsrType; +var + pLiteralList:PsrLiteralList; + node:TsrType; + item:array[0..1] of PsrNode; +begin + Result:=nil; + pLiteralList:=FEmit.GetLiteralList; + // + item[0]:=Fetch(dtype.Child); + item[1]:=pLiteralList^.FetchLiteral(dtype.Count,nil); + // + node:=Default(TsrType); + node.Init; + node.fdtype:=dtype; + node.fsize :=dtype.BitSize div 8; + node.fOpId :=Op.OpTypeVector; + node.fCount:=2; + node.pData :=@item; + Result:=_Fetch(@node,True); +end; + +function TsrTypeList._FetchInt(dtype:TsrDataType):PsrType; +var + pLiteralList:PsrLiteralList; + node:TsrType; + item:array[0..1] of PsrNode; +begin + Result:=nil; + pLiteralList:=FEmit.GetLiteralList; + // + item[0]:=pLiteralList^.FetchLiteral(dtype.BitSize,nil); + item[1]:=pLiteralList^.FetchLiteral(dtype.Sign ,nil); + // + node:=Default(TsrType); + node.Init; + node.fdtype:=dtype; + node.fsize :=dtype.BitSize div 8; + node.fOpId :=Op.OpTypeInt; + node.fCount:=2; + node.pData :=@item; + Result:=_Fetch(@node,True); +end; + +function TsrTypeList._FetchFloat(dtype:TsrDataType):PsrType; +var + pLiteralList:PsrLiteralList; + node:TsrType; + item:array[0..0] of PsrNode; +begin + Result:=nil; + pLiteralList:=FEmit.GetLiteralList; + // + item[0]:=pLiteralList^.FetchLiteral(dtype.BitSize,nil); + // + node:=Default(TsrType); + node.Init; + node.fdtype:=dtype; + node.fsize :=dtype.BitSize div 8; + node.fOpId :=Op.OpTypeFloat; + node.fCount:=1; + node.pData :=@item; + Result:=_Fetch(@node,True); +end; + +function TsrTypeList._FetchStruct2(dtype:TsrDataType):PsrType; +var + node:TsrType; + item:array[0..1] of PsrNode; +begin + Result:=nil; + item[0]:=Fetch(dtype.Child); + item[1]:=item[0]; + // + node:=Default(TsrType); + node.Init; + node.fdtype:=dtype; + node.fsize :=dtype.BitSize div 8; + node.fOpId :=Op.OpTypeStruct; + node.fCount:=2; + node.pData :=@item; + Result:=_Fetch(@node,True); +end; + +function TsrTypeList._FetchConst(dtype:TsrDataType;Value:QWORD):PsrType; +var + pLiteralList:PsrLiteralList; + node:TsrType; + item:array[0..1] of PsrNode; +begin + Result:=nil; + pLiteralList:=FEmit.GetLiteralList; + // + item[0]:=Fetch(dtype); + item[1]:=pLiteralList^.FetchConst(dtype,Value); + // + node:=Default(TsrType); + node.Init; + node.fdtype:=dtConstant; + node.fsize :=dtype.BitSize div 8; + node.fOpId :=Op.OpConstant; + node.fCount:=2; + node.pData :=@item; + Result:=_Fetch(@node,True); end; function TsrTypeList.Fetch(dtype:TsrDataType):PsrType; -var - rec:record - node:TsrType; - align:array[0..1] of Pointer; - end; - child:PsrType; begin Result:=nil; - rec.node:=Default(TsrType); + Case dtype of dtUnknow:; dtBool: begin - rec.node.dtype:=dtype; - rec.node.key.OpId:=Op.OpTypeBool; - Result:=_Fetch(@rec.node); - Result^.mark_read; + Result:=_Fetch0(dtype,Op.OpTypeBool); end; + // + dtInt8, dtUint8, dtInt16, @@ -361,38 +510,24 @@ begin dtInt64, dtUint64: begin - rec.node.dtype:=dtype; - rec.node.key.OpId:=Op.OpTypeInt; - rec.node.key.ext.int_sign:=SignType(dtype); - rec.node.key.ext.int_size:=BitSizeType(dtype); - Result:=_Fetch(@rec.node); - Result^.mark_read; + Result:=_FetchInt(dtype); end; + dtHalf16, dtFloat32, - dtHalf16: + dtFloat64: begin - rec.node.dtype:=dtype; - rec.node.key.OpId:=Op.OpTypeFloat; - rec.node.key.ext.float_size:=BitSizeType(dtype); - Result:=_Fetch(@rec.node); - Result^.mark_read; + Result:=_FetchFloat(dtype); end; dtTypeVoid: begin - rec.node.dtype:=dtype; - rec.node.key.OpId:=Op.OpTypeVoid; - Result:=_Fetch(@rec.node); - Result^.mark_read; + Result:=_Fetch0(dtype,Op.OpTypeVoid); end; dtTypeSampler: begin - rec.node.dtype:=dtype; - rec.node.key.OpId:=Op.OpTypeSampler; - Result:=_Fetch(@rec.node); - Result^.mark_read; + Result:=_Fetch0(dtype,Op.OpTypeSampler); end; // @@ -421,26 +556,21 @@ begin dtVec3i, dtVec4i, + dtVec2h, + dtVec4h, + dtVec2f, dtVec3f, - dtVec4f, - - dtVec2h, - dtVec4h:Result:=_FetchVector(dtype,GetVecChild(dtype),GetVecCount(dtype)); + dtVec4f: + begin + Result:=_FetchVector(dtype); + end; // dtStruct2u: begin - child:=Fetch(dtUint32); - child^.mark_read; - rec.node.dtype:=dtStruct2u; - rec.node.key.OpId:=Op.OpTypeStruct; - rec.node.key.count:=2; - rec.node.SetCompItem(0,child); - rec.node.SetCompItem(1,child); - Result:=_Fetch(@rec.node); - Result^.mark_read; + Result:=_FetchStruct2(dtype); end; // @@ -453,500 +583,182 @@ end; function TsrTypeList.FetchPointer(child:PsrType;storage_class:DWORD):PsrType; var - rec:record - node:TsrType; - align:Pointer; - end; + pLiteralList:PsrLiteralList; + node:TsrType; + item:array[0..1] of PsrNode; begin Assert(child<>nil); - rec.node:=Default(TsrType); - rec.node.dtype:=dtTypePointer; - rec.node.key.OpId:=Op.OpTypePointer; - rec.node.key.ext.storage_class:=storage_class; - rec.node.key.count:=1; - rec.node.SetCompItem(0,child); - Result:=_Fetch(@rec.node); - Result^.mark_read; + pLiteralList:=FEmit.GetLiteralList; + // + item[0]:=pLiteralList^.FetchLiteral(storage_class,PChar(StorageClass.GetStr(storage_class))); + item[1]:=child; + // + node:=Default(TsrType); + node.Init; + node.fdtype:=dtTypePointer; + node.fOpId :=Op.OpTypePointer; + node.fCount:=2; + node.pData :=@item; + Result:=_Fetch(@node,True); end; function TsrTypeList.FetchFunction(ret:PsrType):PsrType; var - rec:record - node:TsrType; - align:Pointer; - end; + node:TsrType; begin Assert(ret<>nil); - rec.node:=Default(TsrType); - rec.node.dtype:=dtTypeFunction; - rec.node.key.OpId:=Op.OpTypeFunction; - rec.node.key.count:=1; - rec.node.SetCompItem(0,ret); - Result:=_Fetch(@rec.node); - Result^.mark_read; + node:=Default(TsrType); + node.Init; + node.fdtype:=dtTypeFunction; + node.fOpId :=Op.OpTypeFunction; + node.fCount:=1; + node.pData :=@ret; + Result:=_Fetch(@node,True); end; -function TsrTypeList.FetchFunction1(ret,param:PsrType):PsrType; +function TsrTypeList.FetchFunction(copy:Boolean;count:Byte;pData:PPsrType):PsrType; var - rec:record - node:TsrType; - align:array[0..1] of Pointer; - end; + node:TsrType; begin - Assert(ret<>nil); - rec.node:=Default(TsrType); - rec.node.dtype:=dtTypeFunction; - rec.node.key.OpId:=Op.OpTypeFunction; - rec.node.key.count:=2; - rec.node.SetCompItem(0,ret); - rec.node.SetCompItem(1,param); - Result:=_Fetch(@rec.node); - Result^.mark_read; + Assert(count<>0); + Assert(pData<>nil); + node:=Default(TsrType); + node.Init; + node.fdtype:=dtTypeFunction; + node.fOpId :=Op.OpTypeFunction; + node.fCount:=count; + node.pData :=Pointer(pData); + Result:=_Fetch(@node,copy); end; -function TsrTypeList.FetchStruct(child:PsrType;pField:Pointer):PsrType; +function TsrTypeList.FetchStruct(count:Word;pData:PPsrType;copy:Boolean;_size:DWORD):PsrType; var - rec:record - node:TsrType; - align:Pointer; - end; + node:TsrType; +begin + Assert(count<>0); + Assert(pData<>nil); + Assert(_size<>0); + node:=Default(TsrType); + node.Init; + node.fdtype:=dtTypeStruct; + node.fsize :=_size; + node.fOpId :=Op.OpTypeStruct; + node.fCount:=count; + node.pData :=Pointer(pData); + Result:=_Fetch(@node,copy); +end; + +function TsrTypeList.InsertStruct(count:Word;pData:PPsrType;copy:Boolean;_size:DWORD):PsrType; +var + node:TsrType; +begin + Assert(count<>0); + Assert(pData<>nil); + Assert(_size<>0); + node:=Default(TsrType); + node.Init; + node.fdtype:=dtTypeStruct; + node.fsize :=_size; + node.fOpId :=Op.OpTypeStruct; + node.fCount:=count; + node.pData :=Pointer(pData); + Result:=_Insert(@node,copy); +end; + +function TsrTypeList.FetchArray(child:PsrType;array_count:DWORD):PsrType; +var + node:TsrType; + item:array[0..1] of PsrType; begin Assert(child<>nil); - rec.node:=Default(TsrType); - rec.node.dtype:=dtTypeStruct; - rec.node.key.OpId:=Op.OpTypeStruct; - rec.node.key.ext.pField:=pField; - rec.node.key.count:=1; - rec.node.SetCompItem(0,child); - Result:=_Fetch(@rec.node); - Result^.mark_read; + // + item[0]:=child; + item[1]:=_FetchConst(dtUInt32,array_count); + // + node:=Default(TsrType); + node.Init; + node.fdtype:=dtTypeArray; + node.fsize :=child^.fsize*array_count; + node.fOpId :=Op.OpTypeArray; + node.fCount:=2; + node.pData :=@item; + Result:=_Fetch(@node,True); end; -function TsrTypeList.FetchStructNode(node:PsrType;count:DWORD;pField:Pointer):PsrType; -begin - Assert(node<>nil); - node^.dtype:=dtTypeStruct; - node^.key.OpId:=Op.OpTypeStruct; - node^.key.ext.pField:=pField; - node^.key.count:=count; - Result:=_Insert(node); - Result^.mark_read; -end; - -function TsrTypeList.FetchArrayNode(node,child:PsrType;array_count,array_stride:DWORD):PsrType; +function TsrTypeList.FetchRuntimeArray(child:PsrType):PsrType; var - aUint:PsrType; + node:TsrType; begin - Assert(node<>nil); Assert(child<>nil); - node^:=Default(TsrType); - node^.dtype:=dtTypeArray; - node^.key.OpId:=Op.OpTypeArray; - node^.key.ext.array_count:=array_count; - node^.key.ext.array_stride:=array_stride; - node^.key.count:=2; - node^.SetCompItem(0,child); - aUint:=Fetch(dtUInt32); - node^.SetCompItem(1,aUint); - FList.Push_tail(node); - Result:=node; - Result^.mark_read; + node:=Default(TsrType); + node.Init; + node.fdtype:=dtTypeRuntimeArray; + node.fsize :=DWORD(-1); + node.fOpId :=Op.OpTypeRuntimeArray; + node.fCount:=1; + node.pData :=@child; + Result:=_Fetch(@node,True); end; -function TsrTypeList.FetchArray(child:PsrType;array_count,array_stride:DWORD):PsrType; -var - rec:record - node:TsrType; - align:array[0..1] of Pointer; +function Dim_GetStr(w:Word):PChar; +begin + Result:=''; + Case w of + Dim.Dim1D :Result:='1D'; + Dim.Dim2D :Result:='2D'; + Dim.Dim3D :Result:='3D'; + Dim.Cube :Result:='Cube'; + Dim.Rect :Result:='Rect'; + Dim.Buffer :Result:='Buffer'; + Dim.SubpassData:Result:='SubpassData'; + else; end; - aUint:PsrType; -begin - Assert(child<>nil); - rec.node:=Default(TsrType); - rec.node.dtype:=dtTypeArray; - rec.node.key.OpId:=Op.OpTypeArray; - rec.node.key.ext.array_count:=array_count; - rec.node.key.ext.array_stride:=array_stride; - rec.node.key.count:=2; - rec.node.SetCompItem(0,child); - aUint:=Fetch(dtUInt32); - rec.node.SetCompItem(1,aUint); - Result:=_Fetch(@rec.node); - Result^.mark_read; -end; - -function TsrTypeList.FetchRuntimeArray(child:PsrType;array_stride:DWORD):PsrType; -var - rec:record - node:TsrType; - align:Pointer; - end; -begin - Assert(child<>nil); - rec.node:=Default(TsrType); - rec.node.dtype:=dtTypeRuntimeArray; - rec.node.key.OpId:=Op.OpTypeRuntimeArray; - rec.node.key.ext.array_stride:=array_stride; - rec.node.key.count:=1; - rec.node.SetCompItem(0,child); - Result:=_Fetch(@rec.node); - Result^.mark_read; end; function TsrTypeList.FetchImage(child:PsrType;image_info:TsrTypeImageInfo):PsrType; var - rec:record - node:TsrType; - align:Pointer; - end; + pLiteralList:PsrLiteralList; + node:TsrType; + item:array[0..6] of PsrNode; begin Assert(child<>nil); - rec.node:=Default(TsrType); - rec.node.dtype:=dtTypeImage; - rec.node.key.OpId:=Op.OpTypeImage; - rec.node.key.ext.image:=image_info; - rec.node.key.count:=1; - rec.node.SetCompItem(0,child); - Result:=_Fetch(@rec.node); - Result^.mark_read; + pLiteralList:=FEmit.GetLiteralList; + // + item[0]:=child; + item[1]:=pLiteralList^.FetchLiteral(image_info.Dim ,Dim_GetStr(image_info.Dim)); + item[2]:=pLiteralList^.FetchLiteral(image_info.Depth ,nil); + item[3]:=pLiteralList^.FetchLiteral(image_info.Arrayed,nil); + item[4]:=pLiteralList^.FetchLiteral(image_info.MS ,nil); + item[5]:=pLiteralList^.FetchLiteral(image_info.Sampled,nil); + item[6]:=pLiteralList^.FetchLiteral(image_info.Format ,PChar(ImageFormat.GetStr(image_info.Format))); + // + node:=Default(TsrType); + node.Init; + node.fdtype:=dtTypeImage; + node.fOpId :=Op.OpTypeImage; + node.fCount:=7; + node.pData :=@item; + Result:=_Fetch(@node,True); end; function TsrTypeList.FetchSampledImage(child:PsrType):PsrType; var - rec:record - node:TsrType; - align:Pointer; - end; + node:TsrType; begin Assert(child<>nil); - rec.node:=Default(TsrType); - rec.node.dtype:=dtTypeSampledImage; - rec.node.key.OpId:=Op.OpTypeSampledImage; - rec.node.key.count:=1; - rec.node.SetCompItem(0,child); - Result:=_Fetch(@rec.node); - Result^.mark_read; + node:=Default(TsrType); + node.Init; + node.fdtype:=dtTypeSampledImage; + node.fOpId :=Op.OpTypeSampledImage; + node.fCount:=1; + node.pData :=@child; + Result:=_Fetch(@node,True); end; -function LazyType2(t1,t2:TsrDataType):TsrDataType; +function TsrTypeList.First:PsrType; inline; begin - if (t1<>dtUnknow) then Result:=t1 else Result:=t2; + Result:=FList.pHead; end; -function LazyType3(t1,t2,t3:TsrDataType):TsrDataType; -begin - if (t1<>dtUnknow) then Result:=t1 else Result:=t2; - if (Result=dtUnknow) then Result:=t3; -end; - -function isIntVector(rtype:TsrDataType):Boolean; inline; -begin - Case rtype of - dtVec2u8, - dtVec4u8, - - dtVec2i8, - dtVec4i8, - - dtVec2u16, - dtVec4u16, - - dtVec2i16, - dtVec4i16, - - dtVec2u, - dtVec3u, - dtVec4u, - - dtVec2i, - dtVec3i, - dtVec4i:Result:=True; - else - Result:=False; - end; -end; - -function isIntScalar(rtype:TsrDataType):Boolean; inline; -begin - Case rtype of - dtInt8, - dtUint8, - - dtInt16, - dtUint16, - - dtInt32 , - dtUint32, - - dtInt64 , - dtUint64:Result:=True; - else - Result:=False; - end; -end; - -function GetVecChild(rtype:TsrDataType):TsrDataType; -begin - Case rtype of - dtVec2b, - dtVec3b, - dtVec4b:Result:=dtBool; - - dtVec2u8, - dtVec4u8:Result:=dtUint8; - - dtVec2i8, - dtVec4i8:Result:=dtInt8; - - dtVec2u16, - dtVec4u16:Result:=dtUint16; - - dtVec2i16, - dtVec4i16:Result:=dtInt16; - - dtStruct2u, - dtVec2u, - dtVec3u, - dtVec4u:Result:=dtUint32; - - dtVec2i, - dtVec3i, - dtVec4i:Result:=dtInt32; - - dtVec2f, - dtVec3f, - dtVec4f:Result:=dtFloat32; - - dtVec2h, - dtVec4h:Result:=dtHalf16; - else - Result:=dtUnknow; - end; -end; - -function GetVecCount(rtype:TsrDataType):Byte; -begin - Case rtype of - dtVec2b, - dtVec2u8, - dtVec2i8, - dtVec2u16, - dtVec2i16, - dtVec2u, - dtVec2i, - dtVec2f, - dtVec2h, - dtStruct2u:Result:=2; - - dtVec3b, - dtVec3u, - dtVec3i, - dtVec3f:Result:=3; - - dtVec4b, - dtVec4u8, - dtVec4i8, - dtVec4u16, - dtVec4i16, - dtVec4u, - dtVec4i, - dtVec4f, - dtVec4h:Result:=4; - else - Result:=0; - end; -end; - -Function GetVecType(elem:TsrDataType;count:Byte):TsrDataType; -begin - Result:=dtUnknow; - if (count<=1) then Exit(elem); - Case elem of - dtBool: - Case count of - 2:Result:=dtVec2b; - 3:Result:=dtVec3b; - 4:Result:=dtVec4b; - end; - dtUint8: - Case count of - 2:Result:=dtVec2u8; - 4:Result:=dtVec4u8; - end; - dtInt8: - Case count of - 2:Result:=dtVec2i8; - 4:Result:=dtVec4i8; - end; - dtUint16: - Case count of - 2:Result:=dtVec2u16; - 4:Result:=dtVec4u16; - end; - dtInt16: - Case count of - 2:Result:=dtVec2i16; - 4:Result:=dtVec4i16; - end; - dtHalf16: - Case count of - 2:Result:=dtVec2h; - 4:Result:=dtVec4h; - end; - dtFloat32: - Case count of - 2:Result:=dtVec2f; - 3:Result:=dtVec3f; - 4:Result:=dtVec4f; - end; - dtInt32: - Case count of - 2:Result:=dtVec2i; - 3:Result:=dtVec3i; - 4:Result:=dtVec4i; - end; - dtUint32: - Case count of - 2:Result:=dtVec2u; - 3:Result:=dtVec3u; - 4:Result:=dtVec4u; - end; - else; - end; -end; - -function isVector(rtype:TsrDataType):Boolean; inline; -begin - Result:=GetVecChild(rtype)<>dtUnknow; -end; - -function GetTypeHigh(rtype:TsrDataType):QWORD; -var - s:Byte; -begin - Result:=0; - if (rtype=dtBool) then Exit(1); - s:=BitSizeType(rtype); - Case s of - 8:Result:=High(Byte); - 16:Result:=High(Word); - 32:Result:=High(DWord); - 64:Result:=High(QWord); - else - Assert(false); - end; -end; - -function CompareType(rtype1,rtype2:TsrDataType):Boolean; -begin - Case rtype1 of - dtInt8, - dtUint8:Result:=(rtype2=dtInt8) or (rtype2=dtUint8); - - dtInt16, - dtUint16:Result:=(rtype2=dtInt16) or (rtype2=dtUint16); - - dtInt32, - dtUint32:Result:=(rtype2=dtInt32) or (rtype2=dtUint32); - - dtVec2u8, - dtVec2i8:Result:=(rtype2=dtVec2u8) or (rtype2=dtVec2i8); - - dtVec4u8, - dtVec4i8:Result:=(rtype2=dtVec4u8) or (rtype2=dtVec4i8); - - dtVec2u16, - dtVec2i16:Result:=(rtype2=dtVec2u16) or (rtype2=dtVec2i16); - - dtVec4u16, - dtVec4i16:Result:=(rtype2=dtVec4u16) or (rtype2=dtVec4i16); - - dtVec2u, - dtVec2i:Result:=(rtype2=dtVec2u) or (rtype2=dtVec2i); - - dtVec3u, - dtVec3i:Result:=(rtype2=dtVec3u) or (rtype2=dtVec3i); - - dtVec4u, - dtVec4i:Result:=(rtype2=dtVec4u) or (rtype2=dtVec4i); - - else - Result:=(rtype1=rtype2); - end; -end; - -function SignType(rtype:TsrDataType):Byte; -begin - Result:=0; - Case rtype of - - dtInt8, - dtInt16, - dtInt32, - dtInt64:Result:=1; - - dtHalf16, - dtFloat32, - dtVec2h, - dtVec4h, - dtVec2f, - dtVec3f, - dtVec4f:Result:=1; - - else; - end; -end; - -function BitSizeType(rtype:TsrDataType):Byte; -begin - Result:=0; - Case rtype of - - dtInt8, - dtUint8:Result:=8; - - dtInt16, - dtUint16, - dtVec2u8, - dtVec2i8, - dtHalf16:Result:=16; - - dtUnknow, - dtBool, //for typecast - dtFloat32, - dtInt32, - dtUint32, - dtVec4u8, - dtVec4i8, - dtVec2u16, - dtVec2i16, - dtVec2h:Result:=32; - - dtInt64, - dtUint64, - dtVec4u16, - dtVec4i16, - dtVec2f, - dtVec4h, - dtStruct2u:Result:=64; - - dtVec3u, - dtVec3f:Result:=96; - dtVec4f:Result:=128; - - else; - end; -end; - -function TryBitcastType(rtype1,rtype2:TsrDataType):Boolean; -var - s,d:Byte; -begin - s:=BitSizeType(rtype1); - d:=BitSizeType(rtype2); - Result:=(s<>0) and (d<>0) and (s=d); -end; - - end. diff --git a/spirv/srUniform.pas b/spirv/srUniform.pas index 0522dac7..f561b0e2 100644 --- a/spirv/srUniform.pas +++ b/spirv/srUniform.pas @@ -5,77 +5,245 @@ unit srUniform; interface uses - spirv, - srNodes, - srTypes, - srLayout, - srReg, - srVariable, - srDecorate; + sysutils, + spirv, + ginodes, + srNode, + srRefId, + srType, + srTypes, + srLayout, + srVariable, + srCapability, + srDecorate, + srConfig; type + ntRegUniform=class(TsrNodeVmt) + class function Down (node:PsrNode):Pointer; override; + class Procedure SetWriter (node,w,line:PsrNode); override; + class Procedure ResetWriter (node,w:PsrNode); override; + class Function pwrite_count(node:PsrNode):PDWORD; override; + class function GetPrintName(node:PsrNode):RawByteString; override; + class function GetRef (node:PsrNode):Pointer; override; + end; + + ntUniform=class(ntDescriptor) + class Function pwrite_count (node:PsrNode):PDWORD; override; + class function GetStorageName(node:PsrNode):RawByteString; override; + end; + String2=String[2]; + PsrRegUniform=^TsrRegUniform; + TsrRegUniform=packed object(TsrNode) + private + fwrite_count:DWORD; + ID:TsrRefId; //post id + // + FWriter:PsrNode; + FVar:PsrVariable; + Procedure SetWriter(t:PsrNode); + public + property pLine:PsrNode read FWriter; + Procedure Init(pVar:PsrVariable); inline; + function GetPrintName:RawByteString; + end; + PsrUniform=^TsrUniform; TsrUniform=object(TsrDescriptor) - pLeft,pRight:PsrUniform; - //---- - - key:packed record + private + pLeft,pRight:PsrUniform; + //---- pLayout:PsrDataLayout; - pType:PsrType; - end; - - pReg:PsrRegNode; - - function c(n1,n2:PsrUniform):Integer; static; - function GetTypeChar:String2; - function GetString:RawByteString; + // + fwrite_count:DWORD; + // + FReg:TsrRegUniform; + function c(n1,n2:PsrUniform):Integer; static; + public + Procedure Init; inline; + function pReg:PsrRegUniform; inline; + function GetStorageName:RawByteString; + function GetTypeChar:String2; + function GetString:RawByteString; end; + PsrUniformList=^TsrUniformList; TsrUniformList=object type TNodeFetch=specialize TNodeFetch; var - Alloc:TfnAlloc; + FEmit:TCustomEmit; FNTree:TNodeFetch; - procedure Init(cb:TfnAlloc); + procedure Init(Emit:TCustomEmit); inline; function Fetch(s:PsrDataLayout;t:PsrType):PsrUniform; Function First:PsrUniform; Function Next(node:PsrUniform):PsrUniform; - procedure AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList); - procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList); + procedure AllocBinding(Var FBinding:Integer); + procedure AllocSourceExtension; end; implementation +class function ntRegUniform.Down(node:PsrNode):Pointer; +begin + Result:=PsrRegUniform(node)^.FVar; +end; + +class Procedure ntRegUniform.SetWriter(node,w,line:PsrNode); +begin + With PsrRegUniform(node)^ do + begin + SetWriter(w); + end; +end; + +class Procedure ntRegUniform.ResetWriter(node,w:PsrNode); +begin + With PsrRegUniform(node)^ do + if (FWriter=w) then + begin + SetWriter(nil); + end; +end; + +class Function ntRegUniform.pwrite_count(node:PsrNode):PDWORD; +begin + Result:=@PsrRegUniform(node)^.fwrite_count; +end; + +class function ntRegUniform.GetPrintName(node:PsrNode):RawByteString; +begin + Result:=PsrRegUniform(node)^.GetPrintName; +end; + +class function ntRegUniform.GetRef(node:PsrNode):Pointer; +begin + Result:=@PsrRegUniform(node)^.ID; +end; + +// + +class Function ntUniform.pwrite_count(node:PsrNode):PDWORD; +begin + Result:=@PsrUniform(node)^.fwrite_count; +end; + +class function ntUniform.GetStorageName(node:PsrNode):RawByteString; +begin + Result:=PsrUniform(node)^.GetStorageName; +end; + +// + +Procedure TsrRegUniform.Init(pVar:PsrVariable); inline; +begin + fntype:=ntRegUniform; + FVar:=pVar; +end; + +Procedure TsrRegUniform.SetWriter(t:PsrNode); +begin + if (FWriter=t) then Exit; + if isUsed then + begin + t^.mark_read (@Self); + FWriter^.mark_unread(@Self); + end; + FWriter:=t; +end; + +function TsrRegUniform.GetPrintName:RawByteString; +begin + Result:=FVar^.GetStorageName; + if (Result<>'') then + begin + Result:='r_'+Result; + end else + begin + Assert(ID.Alloc); + Result:='r'+IntToStr(ID.ID); + end; +end; + +// + function TsrUniform.c(n1,n2:PsrUniform):Integer; begin //first pLayout - Result:=Integer(n1^.key.pLayout>n2^.key.pLayout)-Integer(n1^.key.pLayoutn2^.pLayout)-Integer(n1^.pLayout0) then Exit; //second pType - Result:=Integer(n1^.key.pType>n2^.key.pType)-Integer(n1^.key.pTypen2^.FType)-Integer(n1^.FTypenil) then - With key.pType^.key do - Case key.pType^.dtype of + if (FType<>nil) then + Case FType^.dtype of dtTypeImage: begin - if (ext.image.Dim=Dim.Buffer) then + image_info:=FType^.image_info; + + if (image_info.Dim=Dim.Buffer) then begin - Case ext.image.Sampled of + Case image_info.Sampled of + 1:Result:='uTex'+IntToStr(FBinding); + 2:Result:='sTex'+IntToStr(FBinding); + else Result:='rTex'+IntToStr(FBinding); + end; + end else + begin + Case image_info.Sampled of + 1:Result:='uImg'+IntToStr(FBinding); + 2:Result:='sImg'+IntToStr(FBinding); + else Result:='rImg'+IntToStr(FBinding); + end; + end; + end; + dtTypeSampler:Result:='uSmp'+IntToStr(FBinding); + else; + end; +end; + + +function TsrUniform.GetTypeChar:String2; +var + image_info:TsrTypeImageInfo; +begin + Result:=''; + if (FType<>nil) then + Case FType^.dtype of + dtTypeImage: + begin + image_info:=FType^.image_info; + + if (image_info.Dim=Dim.Buffer) then + begin + Case image_info.Sampled of 1:Result:='UB'; //VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER 2:Result:='SB'; //VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER else Result:='RB'; //runtime texel buffer end; end else begin - Case ext.image.Sampled of + Case image_info.Sampled of 1:Result:='UI'; //VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE 2:Result:='SI'; //VK_DESCRIPTOR_TYPE_STORAGE_IMAGE else Result:='RI'; //runtime image @@ -92,18 +260,18 @@ var PID:DWORD; begin PID:=0; - if (key.pLayout<>nil) then + if (pLayout<>nil) then begin - PID:=key.pLayout^.FID; + PID:=pLayout^.FID; end; Result:=GetTypeChar+ ';PID='+HexStr(PID,8)+ ';BND='+HexStr(FBinding,8); end; -procedure TsrUniformList.Init(cb:TfnAlloc); +procedure TsrUniformList.Init(Emit:TCustomEmit); inline; begin - Alloc:=cb; + FEmit:=Emit; end; function TsrUniformList.Fetch(s:PsrDataLayout;t:PsrType):PsrUniform; @@ -111,19 +279,19 @@ var node:TsrUniform; begin node:=Default(TsrUniform); - node.key.pLayout:=s; - node.key.pType:=t; - node.FStorage:=StorageClass.UniformConstant; - node.FBinding:=-1; + node.Init; + node.pLayout:=s; + node.FType :=t; Result:=FNTree.Find(@node); if (Result=nil) then begin - Result:=Alloc(SizeOf(TsrUniform)); + Result:=FEmit.Alloc(SizeOf(TsrUniform)); Move(node,Result^,SizeOf(TsrUniform)); + // + Result^.InitVar(FEmit); + Result^.FReg.Init(Result^.FVar); + // FNTree.Insert(Result); - end else - begin - t^.mark_unread; end; end; @@ -137,43 +305,144 @@ begin Result:=FNTree.Next(node); end; -procedure TsrUniformList.AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList); +procedure TsrUniformList.AllocBinding(Var FBinding:Integer); var + pConfig:PsrConfig; + pDecorateList:PsrDecorateList; + pCapabilityList:PsrCapabilityList; + // node:PsrUniform; pVar:PsrVariable; + // + FType:PsrType; + image_info:TsrTypeImageInfo; begin - if (Decorates=nil) then Exit; + pConfig :=FEmit.GetConfig; + pDecorateList :=FEmit.GetDecorateList; + pCapabilityList:=FEmit.GetCapabilityList; + node:=First; While (node<>nil) do begin pVar:=node^.pVar; - if (pVar<>nil) then + if (pVar<>nil) and node^.IsUsed and (node^.FBinding=-1) then begin - if (node^.FBinding=-1) then //alloc + pDecorateList^.OpDecorate(pVar,Decoration.Binding,FBinding); + pDecorateList^.OpDecorate(pVar,Decoration.DescriptorSet,pConfig^.DescriptorSet); + + node^.FBinding:=FBinding; + Inc(FBinding); + + FType:=node^.pType; + if (FType<>nil) then begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.Binding,FBinding); - Decorates^.emit_decorate(ntVar,pVar,Decoration.DescriptorSet,Decorates^.FDescriptorSet); - node^.FBinding:=FBinding; - Inc(FBinding); + Case FType^.dtype of + dtTypeImage: + begin + image_info:=FType^.image_info; + + if (image_info.Sampled=2) then //storage image + begin + if (node^.FReg.read_count=0) then + begin + pDecorateList^.OpDecorate(pVar,Decoration.NonReadable,0); + end; + if (node^.FReg.write_count=0) then + begin + pDecorateList^.OpDecorate(pVar,Decoration.NonWritable,0); + end; + end; + + Case image_info.Dim of + Dim.Dim1D: + Case image_info.Sampled of + 1:pCapabilityList^.Add(Capability.Sampled1D); //sampling + 2:pCapabilityList^.Add(Capability.Image1D); //read/write + else; + end; + Dim.Buffer: + Case image_info.Sampled of + 1:pCapabilityList^.Add(Capability.SampledBuffer); //sampling + 2:pCapabilityList^.Add(Capability.ImageBuffer); //read/write + else; + end; + else; + end; + + if (image_info.Sampled=2) and + (image_info.Arrayed=1) then + begin + pCapabilityList^.Add(Capability.ImageMSArray); + end; + + Case image_info.Format of + + ImageFormat.Unknown: + begin + if (node^.FReg.read_count<>0) then + begin + pCapabilityList^.Add(Capability.StorageImageWriteWithoutFormat); + end; + if (node^.FReg.write_count<>0) then + begin + pCapabilityList^.Add(Capability.StorageImageWriteWithoutFormat); + end; + end; + + ImageFormat.Rg32f , + ImageFormat.Rg16f , + ImageFormat.R11fG11fB10f, + ImageFormat.R16f , + ImageFormat.Rgba16 , + ImageFormat.Rgb10A2 , + ImageFormat.Rg16 , + ImageFormat.Rg8 , + ImageFormat.R16 , + ImageFormat.R8 , + ImageFormat.Rgba16Snorm , + ImageFormat.Rg16Snorm , + ImageFormat.Rg8Snorm , + ImageFormat.R16Snorm , + ImageFormat.R8Snorm , + ImageFormat.Rg32i , + ImageFormat.Rg16i , + ImageFormat.Rg8i , + ImageFormat.R16i , + ImageFormat.R8i , + ImageFormat.Rgb10a2ui , + ImageFormat.Rg32ui , + ImageFormat.Rg16ui , + ImageFormat.Rg8ui , + ImageFormat.R16ui , + ImageFormat.R8ui :pCapabilityList^.Add(Capability.StorageImageExtendedFormats); + + else; + end; + + end; + else; + end; end; + end; node:=Next(node); end; end; -procedure TsrUniformList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList); +procedure TsrUniformList.AllocSourceExtension; var + pDebugInfoList:PsrDebugInfoList; node:PsrUniform; pVar:PsrVariable; begin - if (FDebugInfo=nil) then Exit; + pDebugInfoList:=FEmit.GetDebugInfoList; node:=First; While (node<>nil) do begin pVar:=node^.pVar; - if (pVar<>nil) then + if (pVar<>nil) and node^.IsUsed then begin - FDebugInfo^.emit_source_extension(node^.GetString); + pDebugInfoList^.OpSourceExtension(node^.GetString); end; node:=Next(node); end; diff --git a/spirv/srVBufInfo.pas b/spirv/srVBufInfo.pas index 78005515..678d66e5 100644 --- a/spirv/srVBufInfo.pas +++ b/spirv/srVBufInfo.pas @@ -5,9 +5,8 @@ unit srVBufInfo; interface uses - sysutils, ps4_pssl, - srTypes, + srType, srLayout, spirv; diff --git a/spirv/srVariable.pas b/spirv/srVariable.pas index f655c326..25ab7532 100644 --- a/spirv/srVariable.pas +++ b/spirv/srVariable.pas @@ -5,112 +5,235 @@ unit srVariable; interface uses - spirv, - srNodes, - srTypes, - srRefId; + sysutils, + ginodes, + srNode, + srTypes, + srRefId, + srDecorate; type - PsrVariable=^TsrVariable; - - TsrVariable=object - pPrev,pNext:PsrVariable; - //---- - read_count:DWORD; - write_count:DWORD; - ID:TsrRefId; //post id - pType:PsrType; - dtype:TsrDataType; - pSource:TOpParamSingle; //ntInput,ntVertLayout,ntFragLayout,ntOutput,ntUniform,ntBuffer - Procedure mark_read; - Procedure mark_unread; - Procedure mark_write; - Function GetStorageClass:DWORD; - Procedure Clear; - function GetName:RawByteString; + ntVariable=class(TsrNodeVmt) + class Procedure zero_read (node:PsrNode); override; + class Procedure zero_unread (node:PsrNode); override; + class Function pwrite_count (node:PsrNode):PDWORD; override; + class Function GetStorageClass(node:PsrNode):DWORD; override; + class function GetStorageName (node:PsrNode):RawByteString; override; + class function Down (node:PsrNode):Pointer; override; + class function Next (node:PsrNode):Pointer; override; + class function Prev (node:PsrNode):Pointer; override; + class Procedure PrepType (node:PPrepTypeNode); override; + class Function GetPtype (node:PsrNode):PsrNode; override; + class function GetPrintName (node:PsrNode):RawByteString; override; + class function GetRef (node:PsrNode):Pointer; override; end; - TsrVariableList=specialize TNodeList; + PsrVariable=^TsrVariable; + TsrVariable=packed object(TsrNode) + private + pPrev,pNext:PsrVariable; + // + fwrite_count:DWORD; + ID:TsrRefId; //post id + FType:PsrType; + FSource:PsrNode; //ntInput,ntVertLayout,ntFragLayout,ntUniform,ntBuffer,ntOutput + procedure SetType(t:PsrType); + procedure SetSource(t:PsrNode); + public + property pSource:PsrNode read FSource write SetSource; + procedure UpdateType(Emit:TCustomEmit); + Procedure Init; inline; + function GetPrintName:RawByteString; + end; + + PsrVariableList=^TsrVariableList; + TsrVariableList=object + type + TNodeList=specialize TNodeList; + var + FEmit:TCustomEmit; + FList:TNodeList; + procedure Init(Emit:TCustomEmit); inline; + function Fetch:PsrVariable; + function First:PsrVariable; inline; + procedure AllocName; + end; implementation -uses - srLayout, - srVertLayout, - srFragLayout, - srInput, - srOutput; - -Procedure TsrVariable.mark_read; +class Procedure ntVariable.zero_read(node:PsrNode); begin - Inc(read_count); -end; - -Procedure TsrVariable.mark_unread; -begin - if (read_count<>0) then Dec(read_count); -end; - -Procedure TsrVariable.mark_write; -begin - Inc(write_count); -end; - -Function TsrVariable.GetStorageClass:DWORD; -begin - Result:=StorageClass.Private_; - if (pSource.pData<>nil) then - Case pSource.ntype of - ntInput, - ntVertLayout, - ntFragLayout, - ntOutput , - ntUniform , - ntBuffer :Result:=PsrDescriptor(pSource.pData)^.FStorage; - else - Assert(false,'GetStorageClass'); + With PsrVariable(node)^ do + begin + FType^.mark_read(@Self); end; end; -Procedure TsrVariable.Clear; +class Procedure ntVariable.zero_unread(node:PsrNode); begin - if (pType<>nil) then + With PsrVariable(node)^ do begin - pType^.mark_unread; - pType:=nil; + FType^.mark_unread(@Self); end; - if (pSource.pData<>nil) then +end; + +class Function ntVariable.pwrite_count(node:PsrNode):PDWORD; +begin + Result:=@PsrVariable(node)^.fwrite_count; +end; + +class Function ntVariable.GetStorageClass(node:PsrNode):DWORD; +begin + Result:=inherited; + With PsrVariable(node)^ do + if (FSource<>nil) then + if (FSource^.ntype<>nil) then begin - Case pSource.ntype of - ntInput , - ntVertLayout, - ntFragLayout, - ntOutput , - ntUniform , - ntBuffer :PsrDescriptor(pSource.pData)^.pVar:=nil; - else - Assert(false,'Clear'); - end; - pSource.pData:=nil; - end; -end; - -function TsrVariable.GetName:RawByteString; -begin - Result:=''; - if (pSource.pData<>nil) then - begin - Case pSource.ntype of - ntInput : - Result:=PsrInput(pSource.pData)^.GetName; - ntVertLayout: - Result:=PsrVertLayout(pSource.pData)^.GetName; - ntFragLayout: - Result:=PsrFragLayout(pSource.pData)^.GetName; - ntOutput: - Result:=PsrOutput(pSource.pData)^.GetName; - else; + Result:=FSource^.ntype.GetStorageClass(FSource); + end; +end; + +class function ntVariable.GetStorageName(node:PsrNode):RawByteString; +begin + Result:=inherited; + With PsrVariable(node)^ do + if (FSource<>nil) then + if (FSource^.ntype<>nil) then + begin + Result:=FSource^.ntype.GetStorageName(FSource); + end; +end; + +class function ntVariable.Down(node:PsrNode):Pointer; +begin + Result:=PsrVariable(node)^.FSource; +end; + +class function ntVariable.Next(node:PsrNode):Pointer; +begin + Result:=PsrVariable(node)^.pNext; +end; + +class function ntVariable.Prev(node:PsrNode):Pointer; +begin + Result:=PsrVariable(node)^.pPrev; +end; + +class Procedure ntVariable.PrepType(node:PPrepTypeNode); +begin + node^.dnode:=PsrVariable(node^.dnode)^.FSource; +end; + +class Function ntVariable.GetPtype(node:PsrNode):PsrNode; +begin + Result:=PsrVariable(node)^.FType; +end; + +class function ntVariable.GetPrintName(node:PsrNode):RawByteString; +begin + Result:=PsrVariable(node)^.GetPrintName; +end; + +class function ntVariable.GetRef(node:PsrNode):Pointer; +begin + Result:=@PsrVariable(node)^.ID; +end; + +// + +Procedure TsrVariable.Init; inline; +begin + fntype:=ntVariable; +end; + +procedure TsrVariable.SetType(t:PsrType); +begin + if (FType=t) then Exit; + if IsUsed then + begin + t^.mark_read (@Self); + FType^.mark_unread(@Self); + end; + FType:=t; +end; + +procedure TsrVariable.UpdateType(Emit:TCustomEmit); +var + _Type:PsrType; + pTypeList:PsrTypeList; +begin + if (@Self=nil) then Exit; + _Type:=FSource^.pType; + if (_Type=nil) then + begin + SetType(nil); + end else + begin + pTypeList:=Emit.GetTypeList; + _Type:=pTypeList^.FetchPointer(_Type,FSource^.GetStorageClass); + SetType(_Type); + end; +end; + +procedure TsrVariable.SetSource(t:PsrNode); +begin + if (FSource=t) then Exit; + if IsUsed then + begin + t^.mark_read (@Self); + FSource^.mark_unread(@Self); + end; + FSource:=t; +end; + +function TsrVariable.GetPrintName:RawByteString; +begin + Result:=GetStorageName; + if (Result='') then + begin + Assert(ID.Alloc); + Result:='v'+IntToStr(ID.ID); + end; +end; + +// + +procedure TsrVariableList.Init(Emit:TCustomEmit); inline; +begin + FEmit:=Emit; +end; + +function TsrVariableList.Fetch:PsrVariable; +begin + Result:=FEmit.Alloc(SizeOf(TsrVariable)); + Result^.Init; + FList.Push_tail(Result); +end; + +function TsrVariableList.First:PsrVariable; inline; +begin + Result:=FList.pHead; +end; + +procedure TsrVariableList.AllocName; +var + FDebugInfo:PsrDebugInfoList; + node:PsrVariable; + n:RawByteString; +begin + FDebugInfo:=FEmit.GetDebugInfoList; + node:=First; + While (node<>nil) do + begin + if (node^.pType<>nil) then + begin + n:=node^.GetStorageName; + if (n<>'') then + begin + FDebugInfo^.OpName(node,n); + end; end; + node:=node^.Next; end; end; diff --git a/spirv/srVertLayout.pas b/spirv/srVertLayout.pas index 0f409490..9541ea8a 100644 --- a/spirv/srVertLayout.pas +++ b/spirv/srVertLayout.pas @@ -5,48 +5,72 @@ unit srVertLayout; interface uses - sysutils, - spirv, - srNodes, - srReg, - srOp, - srVariable, - srLayout, - srDecorate; + sysutils, + spirv, + ginodes, + srNode, + srType, + srReg, + srOp, + srVariable, + srLayout, + srDecorate; type - PsrVertLayout=^TsrVertLayout; - TsrVertLayout=object(TsrDescriptor) - pLeft,pRight:PsrVertLayout; - //---- - pLayout:PsrDataLayout; - pReg:PsrRegNode; - function c(n1,n2:PsrVertLayout):Integer; static; - function GetString:RawByteString; - function GetName:RawByteString; + ntVertLayout=class(ntDescriptor) + class function GetStorageName(node:PsrNode):RawByteString; override; end; + PsrVertLayout=^TsrVertLayout; + TsrVertLayout=object(TsrDescriptor) + private + pLeft,pRight:PsrVertLayout; + //---- + pLayout:PsrDataLayout; + function c(n1,n2:PsrVertLayout):Integer; static; + public + pReg:PsrRegNode; + procedure Init(p:PsrDataLayout); inline; + function GetString:RawByteString; + function GetStorageName:RawByteString; + end; + + PsrVertLayoutList=^TsrVertLayoutList; TsrVertLayoutList=object type TNodeFetch=specialize TNodeFetch; var - Alloc:TfnAlloc; + FEmit:TCustomEmit; FNTree:TNodeFetch; - procedure Init(cb:TfnAlloc); - function Fetch(p:PsrDataLayout):PsrVertLayout; + procedure Init(Emit:TCustomEmit); inline; + function Fetch(p:PsrDataLayout;rtype:TsrDataType):PsrVertLayout; Function First:PsrVertLayout; Function Next(node:PsrVertLayout):PsrVertLayout; - procedure AllocBinding(Decorates:PsrDecorateList); + procedure AllocBinding; procedure AllocEntryPoint(EntryPoint:PSpirvOp); - procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList); + procedure AllocSourceExtension; end; implementation +class function ntVertLayout.GetStorageName(node:PsrNode):RawByteString; +begin + Result:=PsrVertLayout(node)^.GetStorageName; +end; + +// + function TsrVertLayout.c(n1,n2:PsrVertLayout):Integer; begin Result:=Integer(n1^.pLayout>n2^.pLayout)-Integer(n1^.pLayoutnil) do begin pVar:=node^.pVar; - if (pVar<>nil) then + if (pVar<>nil) and node^.IsUsed and (node^.FBinding=-1) then begin - if (node^.FBinding=-1) then //alloc - begin - Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,FBinding); - node^.FBinding:=FBinding; - Inc(FBinding); - end; + pDecorateList^.OpDecorate(pVar,Decoration.Location,FBinding); + node^.FBinding:=FBinding; + Inc(FBinding); end; node:=Next(node); end; @@ -134,27 +158,28 @@ begin While (node<>nil) do begin pVar:=node^.pVar; - if (pVar<>nil) then + if (pVar<>nil) and node^.IsUsed then begin - EntryPoint^.AddParam(ntVar,pVar); + EntryPoint^.AddParam(pVar); end; node:=Next(node); end; end; -procedure TsrVertLayoutList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList); +procedure TsrVertLayoutList.AllocSourceExtension; var + FDebugInfo:PsrDebugInfoList; node:PsrVertLayout; pVar:PsrVariable; begin - if (FDebugInfo=nil) then Exit; + FDebugInfo:=FEmit.GetDebugInfoList; node:=First; While (node<>nil) do begin pVar:=node^.pVar; - if (pVar<>nil) then + if (pVar<>nil) and node^.IsUsed then begin - FDebugInfo^.emit_source_extension(node^.GetString); + FDebugInfo^.OpSourceExtension(node^.GetString); end; node:=Next(node); end; diff --git a/spirv/srVolatile.pas b/spirv/srVolatile.pas deleted file mode 100644 index b57bbe2c..00000000 --- a/spirv/srVolatile.pas +++ /dev/null @@ -1,489 +0,0 @@ -unit srVolatile; - -{$mode ObjFPC}{$H+} - -interface - -uses - spirv, - srNodes, - srTypes, - srConst, - srReg, - srVariable, - srOp, - srOpUtils, - SprvEmit; - -type - PsrVolatile=^TsrVolatile; - TsrVolatile=object - pNext:PsrVolatile; - pReg:PsrRegNode; - pPar:PsrOpBlock; - FID:SizeUint; - end; - - PsrVolatiles=^TsrVolatiles; - _TsrVolatiles=specialize TNodeStack; - TsrVolatiles=object(_TsrVolatiles) - function pop_reg:PsrRegNode; - function find_reg(pReg:PsrRegNode):PsrVolatile; - end; - - TEmitVolatile=object(TSprvEmit) - procedure NextVolatileID; - function AllocVolatile:PsrVolatile; - function NewVolatile(pReg:PsrRegNode):PsrVolatile; - procedure build_slot_dis(pSlot:PsrRegSlot;var old:PsrRegNode); - procedure build_slot_cur(pSlot:PsrRegSlot;var old:PsrRegNode); - procedure build_slot_old(pSlot:PsrRegSlot;var old:PsrRegNode); - procedure build_volatile_dis(old:PsrRegsSnapshot); - procedure build_volatile_cur(old:PsrRegsSnapshot); - procedure build_volatile_old(old:PsrRegsSnapshot); - procedure make_copy_slot(pSlot:PsrRegSlot); - procedure make_copy_all; - procedure PrepVolatile(dst:PspirvOp;src:PsrRegNode); - end; - -implementation - -uses - emit_post; - -function CompareReg(r1,r2:PsrRegNode):Boolean; -begin - r1:=RegDown(r1); - r2:=RegDown(r2); - Result:=(r1=r2); - if not Result then - begin - Result:=CompareConst(r1^.AsConst,r2^.AsConst); - end; -end; - -function TsrVolatiles.pop_reg:PsrRegNode; -var - node:PsrVolatile; -begin - Result:=nil; - node:=Pop_head; - if (node=nil) then Exit; - Result:=node^.pReg; -end; - -function TsrVolatiles.find_reg(pReg:PsrRegNode):PsrVolatile; -var - node:PsrVolatile; -begin - Result:=nil; - //pReg:=RegDownSlot(pReg); - node:=pHead; - While (node<>nil) do - begin - if (pReg={RegDownSlot}(node^.pReg)) then Exit(node); - node:=node^.pNext; - end; -end; - -procedure TEmitVolatile.NextVolatileID; -begin - Inc(FVolatileID); -end; - -function TEmitVolatile.AllocVolatile:PsrVolatile; -begin - Result:=Alloc(SizeOf(TsrVolatile)); -end; - -function TEmitVolatile.NewVolatile(pReg:PsrRegNode):PsrVolatile; -begin - Result:=AllocVolatile; - Result^.pReg:=pReg; - Result^.pPar:=FMain^.pBlock; - Result^.FID :=FVolatileID; - pReg^.mark_read; -end; - -procedure TEmitVolatile.build_slot_dis(pSlot:PsrRegSlot;var old:PsrRegNode); -var - cur:PsrRegNode; -begin - cur:=pSlot^.current; - While (cur<>old) do - begin - pSlot^.Remove(cur); - cur:=pSlot^.current; - end; -end; - -procedure TEmitVolatile.build_slot_cur(pSlot:PsrRegSlot;var old:PsrRegNode); -var - cur,prv,new:PsrRegNode; - st_cur:TsrVolatiles; - rtype:TsrDataType; -begin - cur:=RegDownSlot(pSlot^.current); - prv:=RegDownSlot(old); - if CompareReg(cur,prv) then Exit; - - cur:=pSlot^.current; - - if (cur<>nil) then - begin - rtype:=cur^.dtype; - end else - begin - rtype:=old^.dtype; - end; - - if (cur=nil) then - begin - Assert(false,'WTF'); - //cur:=pSlot^.New(rtype); //Unresolve - end; - if (old=nil) then - begin - //old:=pSlot^.New(rtype); //Unresolve - end; - - st_cur:=Default(TsrVolatiles); - - if (old<>nil) then - begin - st_cur.Push_head(NewVolatile(old)); - end; - - st_cur.Push_head(NewVolatile(cur)); - - new:=pSlot^.New(cur^.pLine,rtype); - new^.pWriter.SetParam(ntVolatile,st_cur.pHead); - new^.mark_read; - PostReg(new); - old:=new; //update snap -end; - -procedure TEmitVolatile.build_slot_old(pSlot:PsrRegSlot;var old:PsrRegNode); -var - cur,prv:PsrRegNode; - st_old:TsrVolatiles; -begin - cur:=RegDownSlot(pSlot^.current); - prv:=RegDownSlot(old); - if (prv=nil) or CompareReg(cur,prv) then Exit; - - cur:=pSlot^.current; - - if (old^.pWriter.ntype=ntVolatile) then - begin - st_old.pHead:=old^.pWriter.pData; - st_old.Push_head(NewVolatile(cur)); - Exit; - end; - - Assert(old^.pWriter.ntype=ntReg); - Assert(old^.pWriter.pData<>nil); - prv:=old^.pWriter.pData; - - st_old:=Default(TsrVolatiles); - st_old.Push_head(NewVolatile(prv)); - st_old.Push_head(NewVolatile(cur)); - - prv^.mark_unread; - old^.pWriter.SetParam(ntVolatile,st_old.pHead); -end; - -procedure TEmitVolatile.build_volatile_dis(old:PsrRegsSnapshot); -begin - FRegsStory.ForEachSnap(@build_slot_dis,old); -end; - -procedure TEmitVolatile.build_volatile_cur(old:PsrRegsSnapshot); -begin - NextVolatileID; - FRegsStory.ForEachSnap(@build_slot_cur,old); -end; - -procedure TEmitVolatile.build_volatile_old(old:PsrRegsSnapshot); -begin - NextVolatileID; - FRegsStory.ForEachSnap(@build_slot_old,old); -end; - -procedure TEmitVolatile.make_copy_slot(pSlot:PsrRegSlot); -var - cur:PsrRegNode; -begin - if (pSlot^.current<>nil) then - begin - cur:=pSlot^.current; - MakeCopy(pSlot,cur); - pSlot^.current^.pLine:=cur^.pLine; - end; -end; - -procedure TEmitVolatile.make_copy_all; -begin - FRegsStory.ForEachSlot(@make_copy_slot); -end; - -{ -function is_load_from(dst:PspirvOp;r:PsrRegNode;v:PsrVariable):Boolean; -var - src:PspirvOp; - pVar:PsrVariable; -begin - Result:=False; - src:=r^.AsOp; - if (src=nil) then Exit; - if (src^.OpId<>Op.OpLoad) then Exit; - pVar:=src^.pParam.pHead^.AsVar; - if (pVar<>v) then Exit; - Result:=IsGTFlow(src,dst); -end; -} - -function get_load_from(r:PsrRegNode):PsrVariable; -var - pOp:PspirvOp; -begin - Result:=nil; - pOp:=r^.AsOp; - if (pOp=nil) then Exit; - if (pOp^.OpId<>Op.OpLoad) then Exit; - Result:=pOp^.pParam.pHead^.AsVar; -end; - -type - TsrTypesA=array[Low(TsrDataType)..High(TsrDataType)] of DWORD; - -function calc_best_type(pSlot:PsrRegSlot;st:TsrVolatiles):TsrDataType; -var - node:PsrVolatile; - pReg:PsrRegNode; - types:TsrTypesA; - i,max_id:TsrDataType; - bonly:Boolean; -begin - Result:=dtUnknow; - - case pSlot^.rid of - 'SCC':Exit(dtBool); //only bool - end; - - types:=Default(TsrTypesA); - bonly:=true; - node:=st.pHead; - While (node<>nil) do - begin - if (node^.pReg<>nil) then - begin - pReg:=RegDown(node^.pReg); - if (pReg^.dtype<>dtBool) then bonly:=false; - Inc(types[pReg^.dtype]); - end; - node:=node^.pNext; - end; - - case pSlot^.rid of - 'VCCL', - 'VCCH', - 'EXECL', - 'EXECH':if (types[dtBool]<>0) then Exit(dtBool); //prior bool - end; - - if bonly and (types[dtBool]<>0) then - begin - Exit(dtBool); - end else - begin - //types[dtBool]:=0; - end; - - max_id:=dtUnknow; - For i:=Low(TsrDataType) to High(TsrDataType) do - begin - if (max_id=dtUnknow) and (types[i]<>0) then - begin - max_id:=i; - end else - begin - if (types[i]>types[max_id]) then max_id:=i - end; - end; - Result:=max_id; -end; - -{ -procedure MoveVolatiles(dst,src:PsrVolatiles); -var - node:PsrVolatile; -begin - repeat - node:=src^.Pop_head; - if (node=nil) then Break; - if (dst^.find_reg(node^.pReg)=nil) then - begin - //Writeln(node^.pReg^.GetName); - dst^.Push_head(node); - end else - begin - RegUnmark(node^.pReg); - end; - until false; -end; - -function TEmitVolatile._PrepVolatile(src:PsrRegNode):Integer; -var - st_tmp:TsrVolatiles; - node:PsrVolatile; - pReg:PsrRegNode; -begin - Result:=0; - if (src=nil) then Exit; - if (src^.pWriter.ntype<>ntVolatile) then Exit; - - node:=src^.pWriter.pData; - While (node<>nil) do - begin - pReg:=RegDownSlot(node^.pReg); - - if (pReg<>nil) then - begin - if (pReg^.pWriter.ntype=ntVolatile) then - begin - st_tmp.pHead:=pReg^.pWriter.pData; - Assert(st_tmp.pHead<>nil); - - MoveVolatiles(@src^.pWriter.pData,@st_tmp); - - pReg^.SetReg(src); - - node^.pReg:=nil; - Inc(Result); - end; - end; - - node:=node^.pNext; - end; -end; -} - -procedure TEmitVolatile.PrepVolatile(dst:PspirvOp;src:PsrRegNode); -var - rtype:TsrDataType; - pSlot:PsrRegSlot; - pReg,tmp:PsrRegNode; - v:PsrVariable; - node:PsrVolatile; - st,st_tmp:TsrVolatiles; - pLine:PspirvOp; -begin - if (src=nil) then Exit; - if (src^.pWriter.ntype<>ntVolatile) then Exit; - - pSlot:=src^.pSlot; - - st.pHead:=src^.pWriter.pData; - Assert(st.pHead<>nil); - - //While _PrepVolatile(src)<>0 do; - - v:=pSlot^.pVar; - if (v=nil) then - begin - rtype:=calc_best_type(pSlot,st); - - v:=NewVariable; - v^.dtype:=rtype; - - pSlot^.pVar:=v; - end else - begin - rtype:=v^.dtype; - end; - - repeat - node:=st.Pop_head; - if (node=nil) then Break; - pReg:=node^.pReg; - if (pReg=nil) then Continue; - //Assert(pReg<>nil); - //Assert(pReg^.pWriter.ntype<>ntVolatile); - tmp:=RegDownSlot(pReg); - - if (src<>tmp) and (v<>get_load_from(tmp)) then - begin - //mark_read volatile->emit_OpStore - pLine:=tmp^.pLine; - Assert(pLine<>nil); - - if (tmp^.pWriter.ntype=ntVolatile) then - begin - - begin - st_tmp.pHead:=tmp^.pWriter.pData; - Assert(st_tmp.pHead<>nil); - - st.Move_from(st_tmp); - - src^.mark_read; - tmp^.SetReg(src); - - //tmp^.pLine:=dst; - //writeln; - //PrepVolatile(pReg^.pLine,pReg); - - node^.pReg:=nil; - Continue; - end; - end; - - {Case pLine^.OpId of - OpLinks:Writeln('OpLinks'); - OpBlock:Writeln('OpBlock'); - else - Writeln(Op.GetStr(pLine^.OpId)); - end; - Writeln(HexStr(pLine^.Adr.Offdw*4,4)); - - Assert(pReg^.pWriter.ntype<>ntVolatile);} - - TSprvEmit_post(Self).PrepTypeNode(pReg,rtype,False); - - {if pLine^.Adr.Offdw*4=$AC then - begin - writeln('dst:',Op.GetStr(dst^.OpId),' ',HexStr(dst^.Adr.Offdw*4,4)); - writeln; - end;} - - _up_merge_line(pLine); - - TSprvEmit_post(Self).emit_OpStore(pLine,v,pReg); //after reg - end else - begin - node^.pReg:=nil; - RegUnmark(pReg); - //pReg^.mark_unread; - end; - - until false; - - v^.mark_read; - //src^.dtype:=rtype; //reuse - pLine:=dst; - Assert(pLine<>nil); - pLine:=pLine^.pPrev; - Assert(pLine<>nil); - - _up_merge_line(pLine); - - Assert(pLine<>nil); - - TSprvEmit_post(Self).PrepTypeDst(src,rtype); //reuse - - TSprvEmit_post(Self).emit_OpLoad(pLine,src,v); //before reg -end; - -end. - diff --git a/vulkan/vShaderExt.pas b/vulkan/vShaderExt.pas index 91dffa35..4e5423d3 100644 --- a/vulkan/vShaderExt.pas +++ b/vulkan/vShaderExt.pas @@ -21,6 +21,7 @@ uses type TvResourceType=( + vtRoot, vtBufPtr2, vtFunPtr2, vtVSharp4, @@ -279,6 +280,7 @@ end; procedure TvShaderExt.OnDataLayout(P:PChar); begin Case P[1] of + 'R':AddDataLayout(vtRoot ,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14])); 'B':AddDataLayout(vtBufPtr2,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14])); 'F':AddDataLayout(vtFunPtr2,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14])); 'V':AddDataLayout(vtVSharp4,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14])); @@ -473,12 +475,15 @@ begin pSharp:=pData; - if (Length(addr)>1) then - For i:=High(addr)-1 downto 0 do + For i:=High(addr) downto 0 do begin pData:=pData+addr[i].offset; Case addr[i].rtype of + vtRoot: + begin + pSharp:=pData; + end; vtBufPtr2: begin pData:=Pointer(PPtrUint(pData)^ and (not 3)); @@ -895,6 +900,7 @@ begin VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: Case b.addr[0].rtype of + vtRoot, vtBufPtr2: begin a:=AlignShift(P,limits.minStorageBufferOffsetAlignment); @@ -905,7 +911,8 @@ begin a:=AlignShift(Pointer(PVSharpResource4(P)^.base),limits.minStorageBufferOffsetAlignment); if (a<>b.offset) then FResult:=False; end; - else; + else + Assert(false); end; else; diff --git a/vulkan/vShaderManager.pas b/vulkan/vShaderManager.pas index 9a98dff8..be32699b 100644 --- a/vulkan/vShaderManager.pas +++ b/vulkan/vShaderManager.pas @@ -14,6 +14,8 @@ uses ps4_gpu_regs, shader_dump, + ps4_program, + vDevice, vShaderExt, @@ -163,12 +165,39 @@ begin end; end; +Procedure DumpSpv(FStage:TvShaderStage;M:TMemoryStream); +var + hash:DWORD; + F:THandle; + fname:RawByteString; +begin + hash:=FastHash(M.Memory,M.Size); + + case FStage of + vShaderStagePs:fname:='_ps_'; + vShaderStageVs:fname:='_vs_'; + vShaderStageCs:fname:='_cs_'; + else + Exit; + end; + + fname:='shader_dump\'+get_dev_progname+fname+HexStr(hash,8)+'.spv'; + + if FileExists(fname) then Exit; + + CreateDir('shader_dump'); + + F:=FileCreate(fname); + FileWrite(F,M.Memory^,M.Size); + FileClose(F); +end; + function ParseShader(FStage:TvShaderStage;pData:PDWORD;var GPU_REGS:TGPU_REGS):TMemoryStream; var SprvEmit:TSprvEmit; begin Result:=nil; - SprvEmit:=Default(TSprvEmit); + SprvEmit:=TSprvEmit.Create; case FStage of vShaderStagePs : @@ -191,37 +220,37 @@ begin Exit; end; - SprvEmit.FPrintAsm :=False; - SprvEmit.FUseVertexInput:=True; - SprvEmit.FUseTexelBuffer:=False; - SprvEmit.FUseOutput16 :=storageInputOutput16; + SprvEmit.Config.PrintAsm :=False; + SprvEmit.Config.UseVertexInput:=True; + SprvEmit.Config.UseTexelBuffer:=False; + SprvEmit.Config.UseOutput16 :=storageInputOutput16; - SprvEmit.FBuffers.cfg.maxUniformBufferRange :=0; // $FFFF - SprvEmit.FBuffers.cfg.PushConstantsOffset :=0; // 0 - SprvEmit.FBuffers.cfg.maxPushConstantsSize :=limits.maxPushConstantsSize; // 128 - SprvEmit.FBuffers.cfg.minStorageBufferOffsetAlignment:=limits.minStorageBufferOffsetAlignment; // $10 - SprvEmit.FBuffers.cfg.minUniformBufferOffsetAlignment:=limits.minUniformBufferOffsetAlignment; // $100 + SprvEmit.Config.maxUniformBufferRange :=0; // $FFFF + SprvEmit.Config.PushConstantsOffset :=0; // 0 + SprvEmit.Config.maxPushConstantsSize :=limits.maxPushConstantsSize; // 128 + SprvEmit.Config.minStorageBufferOffsetAlignment:=limits.minStorageBufferOffsetAlignment; // $10 + SprvEmit.Config.minUniformBufferOffsetAlignment:=limits.minUniformBufferOffsetAlignment; // $100 - SprvEmit.FBuffers.cfg.maxPushConstantsSize:=16*4; - SprvEmit.FBuffers.cfg.maxPushConstantsSize:=12; - //SprvEmit.FUseVertexInput:=False; + SprvEmit.Config.maxPushConstantsSize:=16*4; + SprvEmit.Config.maxPushConstantsSize:=12; + //SprvEmit.Config.UseVertexInput:=False; - if (SprvEmit.Parse(pData)>1) then + if (SprvEmit.ParseStage(pData)>1) then begin Writeln(StdErr,'Shader Parse Err'); - SprvEmit.FAllocator.Free; + SprvEmit.Free; Exit; end; - TSprvEmit_post(SprvEmit).Post; - TSprvEmit_alloc(SprvEmit).Alloc; - - //TSprvEmit_print(SprvEmit).Print; + SprvEmit.PostStage; + SprvEmit.AllocStage; Result:=TMemoryStream.Create; - TSprvEmit_bin(SprvEmit).SaveToStream(Result); + SprvEmit.SaveToStream(Result); - SprvEmit.FAllocator.Free; + SprvEmit.Free; + + //DumpSpv(FStage,Result); end; function _FetchShader(FStage:TvShaderStage;pData:PDWORD;FDescSetId:Integer;var GPU_REGS:TGPU_REGS):TvShaderExt;