diff --git a/spirv/Half16.pas b/spirv/Half16.pas new file mode 100644 index 0000000..893fa9c --- /dev/null +++ b/spirv/Half16.pas @@ -0,0 +1,62 @@ +unit Half16; + +{$mode objfpc}{$H+} + +interface + +type + PHalf16=^THalf16; + THalf16=bitpacked record + man:0..1023; + exp:0..31; + sgn:0..1; + end; + +operator := (i:THalf16):Single; +operator := (i:Single):THalf16; + +implementation + +operator := (i:THalf16):Single; +var + t1,t2,t3:DWORD; +begin + t1:=Word(i) and $7fff; // Non-sign bits + t2:=Word(i) and $8000; // Sign bit + t3:=Word(i) and $7c00; // Exponent + + t1:=t1 shl 13; // Align mantissa on MSB + t2:=t2 shl 16; // Shift sign bit into position + + t1:=t1+$38000000; // Adjust bias + + if (t3=0) then t1:=0; // Denormals-as-zero + + t1:=t1 or t2; // Re-insert sign bit + + PDWORD(@Result)^:=t1; +end; + +operator := (i:Single):THalf16; +var + t1,t2,t3:DWORD; +begin + t1:=PDWORD(@i)^ and $7fffffff; // Non-sign bits + t2:=PDWORD(@i)^ and $80000000; // Sign bit + t3:=PDWORD(@i)^ and $7f800000; // Exponent + + t1:=t1 shr 13; // Align mantissa on MSB + t2:=t2 shr 16; // Shift sign bit into position + + t1:=t1-$1c000; // Adjust bias + + if (t3<$38800000) then t1:=0; // Flush-to-zero + if (t3>$47000000) then t1:=$7bff; // Clamp-to-max + + t1:=t1 or t2; // Re-insert sign bit + + Word(Result):=Word(t1); +end; + +end. + diff --git a/spirv/SprvEmit.pas b/spirv/SprvEmit.pas new file mode 100644 index 0000000..5d10155 --- /dev/null +++ b/spirv/SprvEmit.pas @@ -0,0 +1,1749 @@ +unit SprvEmit; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + si_ci_vi_merged_registers, + ps4_pssl, + srAllocator, + srNodes, + srBitcast, + srLabel, + srCFG, + srParser, + srTypes, + srConst, + srReg, + srOp, + srOpUtils, + srCap, + srRefId, + srDecorate, + srLayout, + srVertLayout, + srFragLayout, + srBuffer, + srVariable, + srInput, + srOutput, + srUniform, + spirv; + +type + TLocalSize=packed record + x,y,z:DWORD; + 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; + + 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; + procedure _emit_DS; + procedure _emit_SOPK; + 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_VOP1, + emit_VOP2, + emit_VOP3, + emit_VOPC, + emit_MUBUF, + emit_MTBUF, + emit_EXP, + emit_VINTRP, + emit_SMRD, + emit_MIMG; + +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: //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; + +//%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; + + //OpTypeVoid + tvoid:=FSpirvTypes.Fetch(dtTypeVoid); + //OpTypeFunction + tftype:=FSpirvTypes.FetchFunction(tvoid); + + //OpFunction + node:=@FMain^.FTop.dummy; + node^.OpId:=Op.OpFunction; + node^.dst_type:=tvoid; + node^.dst.SetParam(ntFunc,FMain); //self + node^.AddLiteral(FunctionControl.None,'None'); + node^.AddParam(ntType,tftype); + + //OpLabel + node:=NewLabelOp; + FMain^.AddSpirvOp(node); + + Result:=FMain; +end; + +procedure TSprvEmit.AddCap(ID:DWORD); +begin + FSpirvCaps.Add(ID); +end; + +function TSprvEmit.AllocBlockOp:PsrOpBlock; +begin + Result:=Alloc(SizeOf(TsrOpBlock)); + Result^.Alloc:=@Alloc; + Result^.dummy.pParent:=Result; + Result^.Push_head(@Result^.dummy); +end; + +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; + +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; + +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, + 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; +begin + Result:=False; + if (FMain=nil) then Exit; + if (FMain^.pBlock=nil) then Exit; + + pOpBlock:=FMain^.pBlock; + UpdateVolMark(pOpBlock); + + pOpLabel[0]:=pOpBlock^.Labels.pBegOp; + pOpLabel[1]:=pOpBlock^.Labels.pEndOp; + pOpLabel[2]:=pOpBlock^.Labels.pMrgOp; + + Case pOpBlock^.Block.bType of + btCond: + 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; + btLoop: + 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; + else + 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; + + Case pOpBlock^.Block.bType of + btAdr: + begin + FCursor:=pOpBlock^.FCursor; + end; + btOther:; //nop + else + begin + FCursor.PopBlock; + end; + end; + + Result:=FMain^.PopBlock; +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^.pWriter.SetParam(ntReg,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; +end; + +procedure TSprvEmit.SetUserData(pData:Pointer); +begin + FDataLayouts.SetUserData(pData); +end; + +Procedure TSprvEmit.InitVs(RSRC2:TSPI_SHADER_PGM_RSRC2_VS;instance:Byte); +var + p:Byte; +begin + Init; + + FExecutionModel:=ExecutionModel.Vertex; + + //sgrp + p:=0; + if (RSRC2.USER_SGPR<>0) then + For p:=p to RSRC2.USER_SGPR-1 do + begin + AddUserdata(@FRegsStory.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); + p:=p+1; + //s_vs_state + // stream_id[1:0], is_offchip[2], + // streamout_vtx_count[6:0], + // streamout_enable[15:0]} + end; + + if (RSRC2.SO_EN<>0) then + begin + AddInput(@FRegsStory.SGRP[p],dtUint32,itWriteIndex); + p:=p+1; + //s_so_write_index + // streamout_write_index[31:0] + end; + + if (RSRC2.SO_BASE0_EN<>0) then + begin + AddInput(@FRegsStory.SGRP[p],dtUint32,itOffset,0); + p:=p+1; + //s_so_base_offset0 + // streamout_offset0[31:0] + end; + + if (RSRC2.SO_BASE1_EN<>0) then + begin + AddInput(@FRegsStory.SGRP[p],dtUint32,itOffset,1); + p:=p+1; + //s_so_base_offset1 + // streamout_offset1[31:0] + end; + + if (RSRC2.SO_BASE2_EN<>0) then + begin + AddInput(@FRegsStory.SGRP[p],dtUint32,itOffset,2); + p:=p+1; + //s_so_base_offset2 + // streamout_offset2[31:0] + end; + + if (RSRC2.SO_BASE3_EN<>0) then + begin + AddInput(@FRegsStory.SGRP[p],dtUint32,itOffset,3); + p:=p+1; + //s_so_base_offset3 + // streamout_offset3[31:0] + end; + + Assert(RSRC2.OC_LDS_EN=0); + + if (RSRC2.DISPATCH_DRAW_EN<>0) then + begin + AddInput(@FRegsStory.SGRP[p],dtUint32,itWaveId); + p:=p+1; + //s_wave_id + // wave_id [11:0] (dispatch draw term) + end; + + if (RSRC2.SCRATCH_EN<>0) then + begin + AddInput(@FRegsStory.SGRP[p],dtUint32,itScratch); + p:=p+1; + //s_scratch + // scratch offset (in bytes) + end; + + //vgrp + p:=1; + AddInput(@FRegsStory.VGRP[0],dtUint32,itVIndex); + + if (instance>=1) then + begin + AddInput(@FRegsStory.VGRP[p],dtUint32,itVInstance,1); + p:=p+1; + end; + + if (instance>=2) then + begin + AddInput(@FRegsStory.VGRP[p],dtUint32,itVInstance,2); + p:=p+1; + end; + + if (instance>=3) then + begin + AddInput(@FRegsStory.VGRP[p],dtUint32,itVInstance,0); + end; + + AddCap(Capability.Shader); + +end; + +Procedure TSprvEmit.InitPs(RSRC2:TSPI_SHADER_PGM_RSRC2_PS;ENA:TSPI_PS_INPUT_ENA); +var + p:Byte; +begin + Init; + + FExecutionModel:=ExecutionModel.Fragment; + + //sgrp + p:=0; + if (RSRC2.USER_SGPR<>0) then + For p:=p to RSRC2.USER_SGPR-1 do + begin + AddUserdata(@FRegsStory.SGRP[p],p); + end; + p:=RSRC2.USER_SGPR; + + begin + AddInput(@FRegsStory.SGRP[p],dtUint32,itPsState); + p:=p+1; + //s_ps_state + // {bc_optimize, prim_mask[14:0], + // lds_offset[15:0]} + end; + + if (RSRC2.WAVE_CNT_EN<>0) then + begin + AddInput(@FRegsStory.SGRP[p],dtUint32,itWaveCnt); + p:=p+1; + //(s_wave_cnt) + // {ps_wave_id[9:0], ps_strap_id, + // ps_pkr_id} + end; + + if (RSRC2.SCRATCH_EN<>0) then + begin + AddInput(@FRegsStory.SGRP[p],dtUint32,itScratch); + p:=p+1; + //s_scratch + // scratch offset (in bytes) + end; + + //vgrp + p:=0; + if (ENA.PERSP_SAMPLE_ENA<>0) then + begin + AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspSample,0); + p:=p+1; + AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspSample,1); + p:=p+1; + end; + + if (ENA.PERSP_CENTER_ENA<>0) then + begin + AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspCenter,0); + p:=p+1; + AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspCenter,1); + p:=p+1; + end; + + if (ENA.PERSP_CENTROID_ENA<>0) then + begin + AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspCentroid,0); + p:=p+1; + AddInput(@FRegsStory.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); + p:=p+1; + AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspW,1); + p:=p+1; + AddInput(@FRegsStory.VGRP[p],dtFloat32,itPerspW,2); + p:=p+1; + end; + + if (ENA.LINEAR_SAMPLE_ENA<>0) then + begin + AddInput(@FRegsStory.VGRP[p],dtFloat32,itLinearSample,0); + p:=p+1; + AddInput(@FRegsStory.VGRP[p],dtFloat32,itLinearSample,1); + p:=p+1; + end; + + if (ENA.LINEAR_CENTER_ENA<>0) then + begin + AddInput(@FRegsStory.VGRP[p],dtFloat32,itLinearCenter,0); + p:=p+1; + AddInput(@FRegsStory.VGRP[p],dtFloat32,itLinearCenter,1); + p:=p+1; + end; + + if (ENA.LINEAR_CENTROID_ENA<>0) then + begin + AddInput(@FRegsStory.VGRP[p],dtFloat32,itLinearCentroid,0); + p:=p+1; + AddInput(@FRegsStory.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); + p:=p+1; + end; + + if (ENA.POS_Y_FLOAT_ENA<>0) then + begin + AddVecInput(@FRegsStory.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); + p:=p+1; + end; + + if (ENA.POS_W_FLOAT_ENA<>0) then + begin + AddVecInput(@FRegsStory.VGRP[p],dtVec4f,dtFloat32,itFloatPos,3); + p:=p+1; + end; + + if (ENA.FRONT_FACE_ENA<>0) then + begin + AddInput(@FRegsStory.VGRP[p],dtUint32,itFrontFace); + p:=p+1; + end; + + if (ENA.ANCILLARY_ENA<>0) then + begin + AddInput(@FRegsStory.VGRP[p],dtUint32,itAncillary); + p:=p+1; + //Render target array index[26:16], Iterated sample number[11:8], Primitive type[1:0] + end; + + if (ENA.SAMPLE_COVERAGE_ENA<>0) then + begin + AddInput(@FRegsStory.VGRP[p],dtUint32,itSampleCoverage); + p:=p+1; + end; + + if (ENA.POS_FIXED_PT_ENA<>0) then + begin + AddInput(@FRegsStory.VGRP[p],dtUint32,itPosFixed); + p:=p+1; + //Per-pixel fixed point position Y[31:16], X[15:0] + end; + + AddCap(Capability.Shader); + +end; + +Procedure TSprvEmit.InitCs(RSRC2:TCOMPUTE_PGM_RSRC2;NTX:TCOMPUTE_NUM_THREAD_X;NTY:TCOMPUTE_NUM_THREAD_Y;NTZ:TCOMPUTE_NUM_THREAD_Z); +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); + end; + p:=RSRC2.USER_SGPR; + + if (RSRC2.TGID_X_EN<>0) then + begin + AddVecInput(@FRegsStory.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); + 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); + 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); + p:=p+1; + //(s_tg_size) //gl_NumWorkGroups ??? + {first_wave, 14’b0, + ordered_append_term[10:0], + threadgroup_size_in_waves[5:0]} //computePgmRsrc2.tg_size_en;tg_size_en(1) + end; + + if (RSRC2.SCRATCH_EN<>0) then + begin + AddInput(@FRegsStory.SGRP[p],dtUint32,itScratch); + p:=p+1; + //s_scratch + // scratch offset (in bytes) + end; + + //vgrp + p:=0; + begin + AddVecInput(@FRegsStory.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); + 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); + p:=p+1; + //(v_thread_id_z) Thread ID in group 2 //gl_LocalInvocationID + end; + + FLocalSize.x:=NTX.NUM_THREAD_FULL+NTX.NUM_THREAD_PARTIAL; + FLocalSize.y:=NTY.NUM_THREAD_FULL+NTY.NUM_THREAD_PARTIAL; + FLocalSize.z:=NTZ.NUM_THREAD_FULL+NTZ.NUM_THREAD_PARTIAL; + + if (FLocalSize.x=0) then FLocalSize.x:=1; + 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^.pWriter.SetParam(ntReg,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; +end; + +// + +function TSprvEmit.GroupingSharp(src:PPsrRegSlot;rtype:TsrResourceType):PsrDataLayout; +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^.pWriter.SetParam(ntReg,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; +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_VOP3 :Case FSPI.VOP3a.OP of + 0..255:TEmit_VOP3(Self)._emit_VOP3c; + 293..298, + 365..366:TEmit_VOP3(Self)._emit_VOP3b; + else + TEmit_VOP3(Self)._emit_VOP3a; + end; + W_DS :_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 :_emit_SOPK; + W_SOP2 :TEmit_SOP2(Self)._emit_SOP2; + W_VOP2 :TEmit_VOP2(Self)._emit_VOP2; + else + Assert(false); + end; +end; + +procedure TSprvEmit._emit_DS; +begin + Assert(false,'DS?'+IntToStr(FSPI.DS.OP)); +end; + +procedure TSprvEmit._emit_SOPK; +begin + Assert(false,'SOPK?'+IntToStr(FSPI.SOPK.OP)); +end; + +end. + diff --git a/spirv/emit_alloc.pas b/spirv/emit_alloc.pas new file mode 100644 index 0000000..57cfc8d --- /dev/null +++ b/spirv/emit_alloc.pas @@ -0,0 +1,441 @@ +unit emit_alloc; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + spirv, + srNodes, + srTypes, + srConst, + srRefId, + srReg, + srLayout, + srBuffer, + srVariable, + srOp, + srOpUtils, + SprvEmit; + +type + TSprvEmit_alloc=object(TSprvEmit) + procedure Alloc; + 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 AllocFuncId; + procedure AllocOpId(node:PSpirvOp); + procedure AllocOpBlock(pBlock:PsrOpBlock); + end; + +implementation + +procedure TSprvEmit_alloc.Alloc; +begin + AllocBinding; + AllocTypeBinding; + + AllocHeader; + + AllocSourceExtension; + AllocTypeName; + AllocVarName; + + AllocHeaderId; + + AllocTypesId; + AllocConstId; + AllocVariableId; + AllocFuncId; +end; + +procedure TSprvEmit_alloc.AllocSpirvID(P:PsrRefId); +begin + FSpirvIdAlloc.FetchSpirvID(P); +end; + +procedure TSprvEmit_alloc.AllocBinding; +var + FBinding:Integer; +begin + FInputs .AllocBinding(@FDecorates); + FOutputs .AllocBinding(@FDecorates); + FVertLayouts.AllocBinding(@FDecorates); + FFragLayouts.AllocBinding(@FDecorates); + + FBinding:=0; + FUniforms.AllocBinding(FBinding,@FDecorates); + FBuffers .AllocBinding(FBinding,@FDecorates); +end; + +procedure TSprvEmit_alloc.AllocTypeBinding; +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) then + begin + if (pField^.GetStructDecorate<>DWORD(-1)) then + begin + FDecorates.emit_decorate(ntType,node,pField^.GetStructDecorate,0); + 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 + begin + FDebugInfo.emit_name(ntType,node,pField^.pBuffer^.GetStructName); + 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; + end; +end; + +procedure TSprvEmit_alloc.AllocOpListId(node:PspirvOp); +begin + While (node<>nil) do + begin + AllocOpId(node); + node:=node^.pNext; + end; +end; + +procedure TSprvEmit_alloc.AllocEntryPoint; +var + node:PSpirvOp; +begin + node:=FHeader.AddSpirvOp(Op.OpEntryPoint); + + node^.AddLiteral(FExecutionModel,ExecutionModel.GetStr(FExecutionModel)); + + node^.AddParam(ntFunc,FMain); + node^.AddString(FMain^.name); + + FInputs .AllocEntryPoint(node); + FVertLayouts.AllocEntryPoint(node); + FFragLayouts.AllocEntryPoint(node); + FOutputs .AllocEntryPoint(node); +end; + +procedure TSprvEmit_alloc.AllocHeader; +var + node:PSpirvOp; +begin + node:=FHeader.AddSpirvOp(Op.OpMemoryModel); + node^.AddLiteral(AddressingModel.Logical,AddressingModel.GetStr(AddressingModel.Logical)); + node^.AddLiteral(MemoryModel.GLSL450,MemoryModel.GetStr(MemoryModel.GLSL450)); + + AllocEntryPoint; + + Case FExecutionModel of + ExecutionModel.Fragment: + begin + node:=FHeader.AddSpirvOp(Op.OpExecutionMode); + node^.AddParam(ntFunc,FMain); + node^.AddLiteral(ExecutionMode.OriginUpperLeft,ExecutionMode.GetStr(ExecutionMode.OriginUpperLeft)); + end; + ExecutionModel.GLCompute: + begin + node:=FHeader.AddSpirvOp(Op.OpExecutionMode); + node^.AddParam(ntFunc,FMain); + node^.AddLiteral(ExecutionMode.LocalSize,ExecutionMode.GetStr(ExecutionMode.LocalSize)); + node^.AddLiteral(FLocalSize.x); + node^.AddLiteral(FLocalSize.y); + node^.AddLiteral(FLocalSize.z); + end; + end; + +end; + +procedure TSprvEmit_alloc.AllocHeaderId; +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; + end; +end; + +procedure TSprvEmit_alloc.AllocFuncId; +var + pFunc:PSpirvFunc; +begin + pFunc:=FSpirvFuncs.FList.pHead; + While (pFunc<>nil) do + begin + AllocOpBlock(@pFunc^.FTop); + pFunc:=pFunc^.pNext; + end; +end; + +procedure TSprvEmit_alloc.AllocOpId(node:PSpirvOp); +var + Param:POpParamNode; + Info:Op.TOpInfo; +begin + if (node=nil) then Exit; + + Info:=Op.GetInfo(node^.OpId); + + if Info.result then //dst + begin + Assert(node^.dst.ntype<>ntUnknow,'AllocOp$1'); + Assert(node^.dst.pData<>nil ,'AllocOp$2'); + AllocOpSingle(node^.dst); + end else + begin //no dst + if (node^.dst.ntype<>ntUnknow) then + begin + Assert(node^.dst.pData<>nil,'AllocOp$3'); + AllocOpSingle(node^.dst); + end; + end; + + if Info.rstype then //dst type + begin + Assert(node^.dst_type<>nil,'AllocOp$4'); + end; + + Param:=node^.pParam.pHead; + While (Param<>nil) do + begin + AllocOpParamNode(Param); + Param:=Param^.pNext; + end; + +end; + +procedure TSprvEmit_alloc.AllocOpBlock(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 + AllocOpBlock(node^.dst.pData); + end; + end else + begin + AllocOpId(node); + end; + + node:=node^.pNext; + end; +end; + + +end. + diff --git a/spirv/emit_bin.pas b/spirv/emit_bin.pas new file mode 100644 index 0000000..0b7a198 --- /dev/null +++ b/spirv/emit_bin.pas @@ -0,0 +1,555 @@ +unit emit_bin; + +{$mode ObjFPC}{$H+} + +interface + +uses + SySutils, + Classes, + spirv, + srNodes, + srTypes, + srConst, + srReg, + srLayout, + srVariable, + srOp, + srOpUtils, + srCap, + srRefId, + SprvEmit; + +type + TSPIRVHeader=packed record + MAGIC:DWORD; + VERSION:packed record + MINOR:WORD; + MAJOR:WORD; + end; + TOOL_VERSION:WORD; + TOOL_ID:WORD; + BOUND:DWORD; + RESERVED:DWORD; + end; + + PSPIRVInstruction=^TSPIRVInstruction; + TSPIRVInstruction=packed record + OP:WORD; + COUNT:WORD; + end; + +type + TSVInstrBuffer=object + Data:array of DWORD; + COUNT:DWORD; + Procedure AllocData; + Procedure NewOp(OpId:WORD); + 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); + end; + + TSprvEmit_bin=object(TSprvEmit) + procedure SaveToStream(Stream:TStream); + procedure SaveHeader(Stream:TStream;var Header:TSPIRVHeader); + procedure SaveCaps(Stream:TStream); + procedure SaveOpList(Stream:TStream;node:PspirvOp); + 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 + +Procedure TSVInstrBuffer.AllocData; +begin + if (Length(Data)0,'new op not created'); + I:=COUNT; + Inc(COUNT); + AllocData; + Data[i]:=P; +end; + +procedure TSVInstrBuffer.AddString(const name:PChar); +var + I,L,D:DWORD; +begin + Assert(name<>nil); + Assert(COUNT<>0,'new op not created'); + + L:=StrLen(name); + D:=(L+SizeOf(DWORD)) div SizeOf(DWORD); + + 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'); + end; +end; + +procedure TSprvEmit_bin.SaveToStream(Stream:TStream); +var + Header:TSPIRVHeader; +begin + if (Stream=nil) then Exit; + + Header:=Default(TSPIRVHeader); + + Header.MAGIC:=spirv.MagicNumber; + DWORD(Header.VERSION):=FBuffers.cfg.SpvVersion; + Header.TOOL_VERSION:=1; + Header.BOUND:=FSpirvIdAlloc.GetSpirvIDBound; + + SaveHeader(Stream,Header); + + SaveCaps(Stream); + SaveHeaderInfo(Stream); + SaveTypes(Stream); + SaveConst(Stream); + SaveVariable(Stream); + SaveFunc(Stream); +end; + +procedure TSprvEmit_bin.SaveHeader(Stream:TStream;var Header:TSPIRVHeader); +begin + Stream.Write(Header,SizeOf(TSPIRVHeader)); +end; + +procedure TSprvEmit_bin.SaveCaps(Stream:TStream); +var + buf:TSVInstrBuffer; + node:PSpirvCap; +begin + buf:=Default(TSVInstrBuffer); + node:=FSpirvCaps.First; + While (node<>nil) do + begin + buf.NewOp(Op.OpCapability); + buf.AddParamId(node^.ID); + buf.Flush(Stream); + node:=FSpirvCaps.Next(node); + end; +end; + +procedure TSprvEmit_bin.SaveOpList(Stream:TStream;node:PspirvOp); +begin + While (node<>nil) do + begin + SaveOp(Stream,node); + node:=node^.pNext; + end; +end; + +procedure TSprvEmit_bin.SaveHeaderInfo(Stream:TStream); +begin + SaveOpList(Stream,FHeader.pHead); + SaveOpList(Stream,FDebugInfo.pHead); + SaveOpList(Stream,FDecorates.pHead); +end; + +procedure TSprvEmit_bin.SaveTypes(Stream:TStream); +var + buf:TSVInstrBuffer; + node:PsrType; + pConst:PsrConst; + i:dword; + ie:Boolean; +begin + buf:=Default(TSVInstrBuffer); + node:=FSpirvTypes.FList.pHead; + 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); + 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 + begin + For i:=0 to node^.key.count-1 do + begin + buf.AddTypeId(node^.GetCompItem(i)); + end; + end; + + buf.Flush(Stream); + + node:=node^.pNext; + 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; +begin + buf:=Default(TSVInstrBuffer); + node:=FConsts.FList.pHead; + While (node<>nil) do + begin + if (node^.key.dtype<>dtUnknow) then + begin + SaveConst(buf,node); + buf.Flush(Stream); + end; + node:=node^.pNext; + end; +end; + +procedure TSprvEmit_bin.SaveVariable(Stream:TStream); +var + buf:TSVInstrBuffer; + node:PsrVariable; +begin + buf:=Default(TSVInstrBuffer); + node:=FVariables.pHead; + 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.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; + end; +end; + +procedure TSprvEmit_bin.SaveFunc(Stream:TStream); +var + pFunc:PSpirvFunc; +begin + pFunc:=FSpirvFuncs.FList.pHead; + While (pFunc<>nil) do + begin + SaveOpBlock(Stream,@pFunc^.FTop); + pFunc:=pFunc^.pNext; + end; +end; + +procedure TSprvEmit_bin.SaveOp(Stream:TStream;node:PSpirvOp); +var + buf:TSVInstrBuffer; + Param:POpParamNode; + Info:Op.TOpInfo; +begin + if (node=nil) then Exit; + buf:=Default(TSVInstrBuffer); + + Info:=Op.GetInfo(node^.OpId); + + buf.NewOp(node^.OpId); + + if Info.rstype then //dst type + begin + Assert(node^.dst_type<>nil,'SaveOp$4'); + buf.AddTypeId(node^.dst_type); + 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); + end else + begin //no dst + if (node^.dst.ntype<>ntUnknow) then + begin + Assert(node^.dst.pData<>nil,'SaveOp$3'); + SaveOpSingle(buf,node^.dst); + end; + end; + + Param:=node^.pParam.pHead; + While (Param<>nil) do + begin + SaveOpParamNode(buf,Param); + Param:=Param^.pNext; + 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_exp.pas b/spirv/emit_exp.pas new file mode 100644 index 0000000..d4c14a1 --- /dev/null +++ b/spirv/emit_exp.pas @@ -0,0 +1,168 @@ +unit emit_EXP; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + srNodes, + srLabel, + srTypes, + srReg, + srVariable, + srOutput, + srOp, + srOpUtils, + SprvEmit, + emit_op; + +type + TEmit_EXP=object(TEmitOp) + procedure _emit_EXP; + end; + +implementation + +procedure TEmit_EXP._emit_EXP; +Var + exc:PsrRegNode; + node:PSpirvOp; + pOpBlock:PsrOpBlock; + + dout:PsrVariable; + dst:PsrRegNode; + src:array[0..3] of PsrRegNode; + rtype:TsrDataType; + f,i,p:Byte; + +begin + //if (VM<>0) and (EXEC<>0) = set pixel else (if DONE=1) discard pixel /(PS only) + + pOpBlock:=nil; + if (FSPI.EXP.VM<>0) and (FSPI.EXP.DONE<>0) then + begin + pOpBlock:=AllocBlockOp; + pOpBlock^.SetInfo(btOther,FCursor.Adr,FCursor.Adr); + PushBlockOp(line,pOpBlock,nil); + + exc:=MakeRead(@FRegsStory.EXEC[0],dtBool); + node:=AddSpirvOp(OpMakeExp); + node^.AddParam(ntReg,exc); //<-fetch read + end; + + //before + if (TpsslExportType(FSPI.EXP.TGT)=etNull) //only set kill mask + or (FSPI.EXP.EN=0) then //nop + begin + if (pOpBlock<>nil) then //is pushed + begin + FMain^.PopBlock; + end; + Exit; + end; + + pOpBlock:=AllocBlockOp; //down + pOpBlock^.SetInfo(btOther,FCursor.Adr,FCursor.Adr); + PushBlockOp(line,pOpBlock,nil); + + //output + + src[0]:=nil; + src[1]:=nil; + src[2]:=nil; + src[3]:=nil; + + f:=FSPI.EXP.EN; + + if (FSPI.EXP.COMPR=0) then //float32 + begin + + p:=PopCnt(f); + + if (p=1) then + begin + Case f of + $1:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC0,dtFloat32); + $2:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC1,dtFloat32); + $4:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC2,dtFloat32); + $8:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC3,dtFloat32); + else + Assert(false); + end; + dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),dtFloat32); //output in FSPI.EXP.TGT + emit_OpStore(line,dout,src[0]); + end else + begin + + Case p of + 0:Assert(false); + 2:rtype:=dtVec2f; + 3:rtype:=dtVec3f; + 4:rtype:=dtVec4f; + end; + + i:=0; + if (f and $1<>0) then + begin + src[i]:=fetch_vsrc8(FSPI.EXP.VSRC0,dtFloat32); + Inc(i); + end; + if (f and $2<>0) then + begin + src[i]:=fetch_vsrc8(FSPI.EXP.VSRC1,dtFloat32); + Inc(i); + end; + if (f and $4<>0) then + begin + src[i]:=fetch_vsrc8(FSPI.EXP.VSRC2,dtFloat32); + Inc(i); + end; + if (f and $8<>0) then + begin + src[i]:=fetch_vsrc8(FSPI.EXP.VSRC3,dtFloat32); + Inc(i); + end; + + dst:=emit_OpMakeVec(line,rtype,p,@src); + dst^.mark_read; + + dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),rtype); //output in FSPI.EXP.TGT + emit_OpStore(line,dout,dst); + end; + + end else + begin //half16 + Case f of + 3, + $F: + begin + fetch_vsrc8_vec2h(FSPI.EXP.VSRC0,src[0],src[1]); + fetch_vsrc8_vec2h(FSPI.EXP.VSRC1,src[2],src[3]); + end; + $C: + begin + fetch_vsrc8_vec2h(FSPI.EXP.VSRC2,src[0],src[1]); + fetch_vsrc8_vec2h(FSPI.EXP.VSRC3,src[2],src[3]); + end; + else + Assert(false); + end; + + dst:=emit_OpMakeVec(line,dtVec4h,4,@src); + dst^.mark_read; + + dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),dtVec4h); //output in FSPI.EXP.TGT + emit_OpStore(line,dout,dst); + end; + + if (pOpBlock<>nil) then //is pushed + begin + FMain^.PopBlock; + FMain^.PopBlock; + end; +end; + +end. + diff --git a/spirv/emit_mimg.pas b/spirv/emit_mimg.pas new file mode 100644 index 0000000..5274568 --- /dev/null +++ b/spirv/emit_mimg.pas @@ -0,0 +1,705 @@ +unit emit_MIMG; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + spirv, + si_ci_vi_merged_enum, + ps4_shader, + ps4_pssl, + srNodes, + srTypes, + srConst, + srReg, + srLayout, + srOp, + SprvEmit, + emit_op; + +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); + end; + +implementation + +function GetImageFormat(PT:PTSharpResource4):Byte; +begin + Result:=ImageFormat.Unknown; + if (PT=nil) then Exit; + Case PT^.nfmt of + IMG_NUM_FORMAT_UNORM, + IMG_NUM_FORMAT_SRGB: + begin //R8, Rg8,Rg16, Rgba8,Rgba16,Rgb10A2 + + Case PT^.dfmt of + + IMG_DATA_FORMAT_8 :Result:=ImageFormat.R8; + IMG_DATA_FORMAT_ETC2_R :Result:=ImageFormat.R8; + IMG_DATA_FORMAT_BC4 :Result:=ImageFormat.R8; + IMG_DATA_FORMAT_1 :Result:=ImageFormat.R8; + IMG_DATA_FORMAT_32_AS_8 :Result:=ImageFormat.R8; + + IMG_DATA_FORMAT_8_8 :Result:=ImageFormat.Rg8; + IMG_DATA_FORMAT_16_16 :Result:=ImageFormat.Rg16; + IMG_DATA_FORMAT_ETC2_RG :Result:=ImageFormat.Rg8; + IMG_DATA_FORMAT_BC5 :Result:=ImageFormat.Rg8; + IMG_DATA_FORMAT_4_4 :Result:=ImageFormat.Rg8; + IMG_DATA_FORMAT_32_AS_8_8 :Result:=ImageFormat.Rg8; + + IMG_DATA_FORMAT_10_11_11 :Result:=ImageFormat.Rgb10A2; + IMG_DATA_FORMAT_11_11_10 :Result:=ImageFormat.Rgb10A2; + IMG_DATA_FORMAT_5_6_5 :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_ETC2_RGB :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_GB_GR :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_BG_RG :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_BC1 :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_BC6 :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_6_5_5 :Result:=ImageFormat.Rgba8; + + IMG_DATA_FORMAT_10_10_10_2 :Result:=ImageFormat.Rgb10A2; + IMG_DATA_FORMAT_2_10_10_10 :Result:=ImageFormat.Rgb10A2; + IMG_DATA_FORMAT_8_8_8_8 :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_1_5_5_5 :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_5_5_5_1 :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_4_4_4_4 :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_ETC2_RGBA :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_ETC2_RGBA1 :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_5_9_9_9 :Result:=ImageFormat.Rgba16; + IMG_DATA_FORMAT_BC2 :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_BC3 :Result:=ImageFormat.Rgba8; + IMG_DATA_FORMAT_BC7 :Result:=ImageFormat.Rgba8; + + else; + end; + + end; + + IMG_NUM_FORMAT_SNORM: + begin //R8Snorm, Rg8Snorm,Rg16Snorm, Rgba8Snorm,Rgba16Snorm + + Case PT^.dfmt of + + IMG_DATA_FORMAT_8 :Result:=ImageFormat.R8Snorm; + IMG_DATA_FORMAT_ETC2_R :Result:=ImageFormat.R8Snorm; + IMG_DATA_FORMAT_BC4 :Result:=ImageFormat.R8Snorm; + IMG_DATA_FORMAT_1 :Result:=ImageFormat.R8Snorm; + IMG_DATA_FORMAT_32_AS_8 :Result:=ImageFormat.R8Snorm; + + IMG_DATA_FORMAT_8_8 :Result:=ImageFormat.Rg8Snorm; + IMG_DATA_FORMAT_16_16 :Result:=ImageFormat.Rg16Snorm; + IMG_DATA_FORMAT_ETC2_RG :Result:=ImageFormat.Rg8Snorm; + IMG_DATA_FORMAT_BC5 :Result:=ImageFormat.Rg8Snorm; + IMG_DATA_FORMAT_4_4 :Result:=ImageFormat.Rg8Snorm; + IMG_DATA_FORMAT_32_AS_8_8 :Result:=ImageFormat.Rg8Snorm; + + IMG_DATA_FORMAT_10_11_11 :Result:=ImageFormat.Rgba16Snorm; + IMG_DATA_FORMAT_11_11_10 :Result:=ImageFormat.Rgba16Snorm; + IMG_DATA_FORMAT_5_6_5 :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_ETC2_RGB :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_GB_GR :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_BG_RG :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_BC1 :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_BC6 :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_6_5_5 :Result:=ImageFormat.Rgba8Snorm; + + IMG_DATA_FORMAT_10_10_10_2 :Result:=ImageFormat.Rgba16Snorm; + IMG_DATA_FORMAT_2_10_10_10 :Result:=ImageFormat.Rgba16Snorm; + IMG_DATA_FORMAT_8_8_8_8 :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_1_5_5_5 :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_5_5_5_1 :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_4_4_4_4 :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_ETC2_RGBA :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_ETC2_RGBA1 :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_5_9_9_9 :Result:=ImageFormat.Rgba16Snorm; + IMG_DATA_FORMAT_BC2 :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_BC3 :Result:=ImageFormat.Rgba8Snorm; + IMG_DATA_FORMAT_BC7 :Result:=ImageFormat.Rgba8Snorm; + + else; + end; + + end; + + IMG_NUM_FORMAT_UINT: + begin //R8ui,R16ui,R32ui, Rg8ui,Rg16ui,Rg32ui, Rgba8ui,Rgba16ui,Rgba32ui,Rgb10a2ui + + Case PT^.dfmt of + + IMG_DATA_FORMAT_8 :Result:=ImageFormat.R8ui; + IMG_DATA_FORMAT_16 :Result:=ImageFormat.R16ui; + IMG_DATA_FORMAT_32 :Result:=ImageFormat.R32ui; + IMG_DATA_FORMAT_ETC2_R :Result:=ImageFormat.R8ui; + IMG_DATA_FORMAT_BC4 :Result:=ImageFormat.R8ui; + IMG_DATA_FORMAT_1 :Result:=ImageFormat.R8ui; + IMG_DATA_FORMAT_32_AS_8 :Result:=ImageFormat.R8ui; + + IMG_DATA_FORMAT_8_8 :Result:=ImageFormat.Rg8ui; + IMG_DATA_FORMAT_16_16 :Result:=ImageFormat.Rg16ui; + IMG_DATA_FORMAT_32_32 :Result:=ImageFormat.Rg32ui; + IMG_DATA_FORMAT_8_24 :Result:=ImageFormat.Rg32ui; + IMG_DATA_FORMAT_24_8 :Result:=ImageFormat.Rg32ui; + IMG_DATA_FORMAT_X24_8_32 :Result:=ImageFormat.Rg32ui; + IMG_DATA_FORMAT_ETC2_RG :Result:=ImageFormat.Rg8ui; + IMG_DATA_FORMAT_BC5 :Result:=ImageFormat.Rg8ui; + IMG_DATA_FORMAT_4_4 :Result:=ImageFormat.Rg8ui; + IMG_DATA_FORMAT_32_AS_8_8 :Result:=ImageFormat.Rg8ui; + + IMG_DATA_FORMAT_10_11_11 :Result:=ImageFormat.Rgb10a2ui; + IMG_DATA_FORMAT_11_11_10 :Result:=ImageFormat.Rgb10a2ui; + IMG_DATA_FORMAT_32_32_32 :Result:=ImageFormat.Rgba32ui; + IMG_DATA_FORMAT_5_6_5 :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_ETC2_RGB :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_GB_GR :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_BG_RG :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_BC1 :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_BC6 :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_6_5_5 :Result:=ImageFormat.Rgba8ui; + + IMG_DATA_FORMAT_10_10_10_2 :Result:=ImageFormat.Rgb10a2ui; + IMG_DATA_FORMAT_2_10_10_10 :Result:=ImageFormat.Rgb10a2ui; + IMG_DATA_FORMAT_8_8_8_8 :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_16_16_16_16 :Result:=ImageFormat.Rgba16ui; + IMG_DATA_FORMAT_32_32_32_32 :Result:=ImageFormat.Rgba32ui; + IMG_DATA_FORMAT_1_5_5_5 :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_5_5_5_1 :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_4_4_4_4 :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_ETC2_RGBA :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_ETC2_RGBA1 :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_5_9_9_9 :Result:=ImageFormat.Rgba16ui; + IMG_DATA_FORMAT_BC2 :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_BC3 :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_BC7 :Result:=ImageFormat.Rgba8ui; + IMG_DATA_FORMAT_32_AS_32_32_32_32:Result:=ImageFormat.Rgba32ui; + + IMG_DATA_FORMAT_FMASK8_S2_F1 :Result:=ImageFormat.R8ui; + IMG_DATA_FORMAT_FMASK8_S4_F1 :Result:=ImageFormat.R8ui; + IMG_DATA_FORMAT_FMASK8_S8_F1 :Result:=ImageFormat.R8ui; + IMG_DATA_FORMAT_FMASK8_S2_F2 :Result:=ImageFormat.R8ui; + IMG_DATA_FORMAT_FMASK8_S4_F2 :Result:=ImageFormat.R8ui; + IMG_DATA_FORMAT_FMASK8_S4_F4 :Result:=ImageFormat.R8ui; + + IMG_DATA_FORMAT_FMASK16_S16_F1 :Result:=ImageFormat.R16ui; + IMG_DATA_FORMAT_FMASK16_S8_F2 :Result:=ImageFormat.R16ui; + + IMG_DATA_FORMAT_FMASK32_S16_F2 :Result:=ImageFormat.R32ui; + IMG_DATA_FORMAT_FMASK32_S8_F4 :Result:=ImageFormat.R32ui; + IMG_DATA_FORMAT_FMASK32_S8_F8 :Result:=ImageFormat.R32ui; + + IMG_DATA_FORMAT_FMASK64_S16_F4 :Result:=ImageFormat.R64ui; + IMG_DATA_FORMAT_FMASK64_S16_F8 :Result:=ImageFormat.R64ui; + + else; + end; + + end; + + IMG_NUM_FORMAT_SINT: + begin //R8i,R16i,R32i, Rg8i,Rg16i,Rg32i, Rgba8i,Rgba16i,Rgba32i + + Case PT^.dfmt of + + IMG_DATA_FORMAT_8 :Result:=ImageFormat.R8i; + IMG_DATA_FORMAT_16 :Result:=ImageFormat.R16i; + IMG_DATA_FORMAT_32 :Result:=ImageFormat.R32i; + IMG_DATA_FORMAT_ETC2_R :Result:=ImageFormat.R8i; + IMG_DATA_FORMAT_BC4 :Result:=ImageFormat.R8i; + IMG_DATA_FORMAT_1 :Result:=ImageFormat.R8i; + IMG_DATA_FORMAT_32_AS_8 :Result:=ImageFormat.R8i; + + IMG_DATA_FORMAT_8_8 :Result:=ImageFormat.Rg8i; + IMG_DATA_FORMAT_16_16 :Result:=ImageFormat.Rg16i; + IMG_DATA_FORMAT_32_32 :Result:=ImageFormat.Rg32i; + IMG_DATA_FORMAT_8_24 :Result:=ImageFormat.Rg32i; + IMG_DATA_FORMAT_24_8 :Result:=ImageFormat.Rg32i; + IMG_DATA_FORMAT_X24_8_32 :Result:=ImageFormat.Rg32i; + IMG_DATA_FORMAT_ETC2_RG :Result:=ImageFormat.Rg8i; + IMG_DATA_FORMAT_BC5 :Result:=ImageFormat.Rg8i; + IMG_DATA_FORMAT_4_4 :Result:=ImageFormat.Rg8i; + IMG_DATA_FORMAT_32_AS_8_8 :Result:=ImageFormat.Rg8i; + + IMG_DATA_FORMAT_10_11_11 :Result:=ImageFormat.Rgba16i; + IMG_DATA_FORMAT_11_11_10 :Result:=ImageFormat.Rgba16i; + IMG_DATA_FORMAT_32_32_32 :Result:=ImageFormat.Rgba32i; + IMG_DATA_FORMAT_5_6_5 :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_ETC2_RGB :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_GB_GR :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_BG_RG :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_BC1 :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_BC6 :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_6_5_5 :Result:=ImageFormat.Rgba8i; + + IMG_DATA_FORMAT_10_10_10_2 :Result:=ImageFormat.Rgba16i; + IMG_DATA_FORMAT_2_10_10_10 :Result:=ImageFormat.Rgba16i; + IMG_DATA_FORMAT_8_8_8_8 :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_16_16_16_16 :Result:=ImageFormat.Rgba16i; + IMG_DATA_FORMAT_32_32_32_32 :Result:=ImageFormat.Rgba32i; + IMG_DATA_FORMAT_1_5_5_5 :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_5_5_5_1 :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_4_4_4_4 :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_ETC2_RGBA :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_ETC2_RGBA1 :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_5_9_9_9 :Result:=ImageFormat.Rgba16i; + IMG_DATA_FORMAT_BC2 :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_BC3 :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_BC7 :Result:=ImageFormat.Rgba8i; + IMG_DATA_FORMAT_32_AS_32_32_32_32:Result:=ImageFormat.Rgba32i; + + IMG_DATA_FORMAT_FMASK8_S2_F1 :Result:=ImageFormat.R8i; + IMG_DATA_FORMAT_FMASK8_S4_F1 :Result:=ImageFormat.R8i; + IMG_DATA_FORMAT_FMASK8_S8_F1 :Result:=ImageFormat.R8i; + IMG_DATA_FORMAT_FMASK8_S2_F2 :Result:=ImageFormat.R8i; + IMG_DATA_FORMAT_FMASK8_S4_F2 :Result:=ImageFormat.R8i; + IMG_DATA_FORMAT_FMASK8_S4_F4 :Result:=ImageFormat.R8i; + + IMG_DATA_FORMAT_FMASK16_S16_F1 :Result:=ImageFormat.R16i; + IMG_DATA_FORMAT_FMASK16_S8_F2 :Result:=ImageFormat.R16i; + + IMG_DATA_FORMAT_FMASK32_S16_F2 :Result:=ImageFormat.R32i; + IMG_DATA_FORMAT_FMASK32_S8_F4 :Result:=ImageFormat.R32i; + IMG_DATA_FORMAT_FMASK32_S8_F8 :Result:=ImageFormat.R32i; + + IMG_DATA_FORMAT_FMASK64_S16_F4 :Result:=ImageFormat.R64i; + IMG_DATA_FORMAT_FMASK64_S16_F8 :Result:=ImageFormat.R64i; + + else; + end; + + end; + + IMG_NUM_FORMAT_USCALED, + IMG_NUM_FORMAT_SSCALED, + IMG_NUM_FORMAT_FLOAT: + begin //R16f,R32f, Rg16f,Rg32f, R11fG11fB10f, Rgba16f,Rgba32f + + Case PT^.dfmt of + + IMG_DATA_FORMAT_16 :Result:=ImageFormat.R16f; + IMG_DATA_FORMAT_32 :Result:=ImageFormat.R32f; + IMG_DATA_FORMAT_ETC2_R :Result:=ImageFormat.R16f; + IMG_DATA_FORMAT_BC4 :Result:=ImageFormat.R16f; + + IMG_DATA_FORMAT_16_16 :Result:=ImageFormat.Rg16f; + IMG_DATA_FORMAT_32_32 :Result:=ImageFormat.Rg32f; + IMG_DATA_FORMAT_8_24 :Result:=ImageFormat.Rg32f; + IMG_DATA_FORMAT_24_8 :Result:=ImageFormat.Rg32f; + IMG_DATA_FORMAT_X24_8_32 :Result:=ImageFormat.Rg32f; + IMG_DATA_FORMAT_ETC2_RG :Result:=ImageFormat.Rg16f; + IMG_DATA_FORMAT_BC5 :Result:=ImageFormat.Rg16f; + + IMG_DATA_FORMAT_10_11_11 :Result:=ImageFormat.R11fG11fB10f; + IMG_DATA_FORMAT_11_11_10 :Result:=ImageFormat.R11fG11fB10f; + IMG_DATA_FORMAT_32_32_32 :Result:=ImageFormat.Rgba32f; + IMG_DATA_FORMAT_ETC2_RGB :Result:=ImageFormat.Rgba16f; + IMG_DATA_FORMAT_BC1 :Result:=ImageFormat.Rgba16f; + IMG_DATA_FORMAT_BC6 :Result:=ImageFormat.Rgba16f; + + IMG_DATA_FORMAT_10_10_10_2 :Result:=ImageFormat.Rgba16f; + IMG_DATA_FORMAT_2_10_10_10 :Result:=ImageFormat.Rgba16f; + IMG_DATA_FORMAT_16_16_16_16 :Result:=ImageFormat.Rgba16f; + IMG_DATA_FORMAT_32_32_32_32 :Result:=ImageFormat.Rgba32f; + IMG_DATA_FORMAT_ETC2_RGBA :Result:=ImageFormat.Rgba16f; + IMG_DATA_FORMAT_ETC2_RGBA1 :Result:=ImageFormat.Rgba16f; + IMG_DATA_FORMAT_BC2 :Result:=ImageFormat.Rgba16f; + IMG_DATA_FORMAT_BC3 :Result:=ImageFormat.Rgba16f; + IMG_DATA_FORMAT_BC7 :Result:=ImageFormat.Rgba16f; + IMG_DATA_FORMAT_32_AS_32_32_32_32:Result:=ImageFormat.Rgba32f; + + else; + end; + + end; + + else; + end; +end; + +function GetDimType(PT:PTSharpResource4):Byte; +begin + Result:=0; + if (PT=nil) then Exit; + Case PT^._type of + SQ_RSRC_IMG_1D, + SQ_RSRC_IMG_1D_ARRAY :Result:=Dim.Dim1D; + SQ_RSRC_IMG_2D, + SQ_RSRC_IMG_2D_ARRAY, + SQ_RSRC_IMG_2D_MSAA, + SQ_RSRC_IMG_2D_MSAA_ARRAY:Result:=Dim.Dim2D; + SQ_RSRC_IMG_3D :Result:=Dim.Dim3D; + SQ_RSRC_IMG_CUBE :Result:=Dim.Cube; + else; + end; +end; + +function GetElemType(PT:PTSharpResource4):TsrDataType; +begin + Result:=dtFloat32; + if (PT=nil) then Exit; + Case PT^.nfmt of + IMG_NUM_FORMAT_UINT:Result:=dtUint32; + IMG_NUM_FORMAT_SINT:Result:=dtInt32; + else; + end; +end; + +function GetDimCount(b:Byte):Byte; +begin + Result:=1; + Case b of + Dim.Dim2D:Result:=2; + Dim.Dim3D:Result:=3; + Dim.Cube :Result:=3; + end; +end; + +function GetImageInfo(PT:PTSharpResource4):TsrImageInfo; +begin + Result:=Default(TsrImageInfo); + Result.dtype:=GetElemType(PT); + + Result.tinfo.Dim :=GetDimType(PT); + Result.tinfo.Depth :=2; + Result.tinfo.Arrayed:=GetArrayedType(PT); + Result.tinfo.MS :=GetMsType(PT); + Result.tinfo.Format :=GetImageFormat(PT); +end; + +procedure TEmit_MIMG._DistribDmask(dst:PsrRegNode;telem:TsrDataType); //result +var + pSlot:PsrRegSlot; + i,d:Byte; +begin + d:=0; + 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); + Assert(pSlot<>nil); + dst^.mark_read; + emit_OpCompExtract(line,pSlot^.New(line,telem),dst,i); + end; +end; + +Function TEmit_MIMG._GatherCoord_f(var offset:DWORD;dim_id:Byte):PsrRegNode; //src +var + src:array[0..3] of PsrRegNode; + i,count:Byte; +begin + Result:=nil; + + count:=GetDimCount(dim_id); + if (FSPI.MIMG.DA<>0) then Inc(count); //slice + + if (dim_id=Dim.Cube) then + begin + //x,y,slice,(face_id+slice*8) + + if (FSPI.MIMG.DA<>0) then //slice + begin + src[0]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+0,dtFloat32); //x + src[1]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+1,dtFloat32); //y + src[2]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+3,dtFloat32); //face TODO: face-slice*8 + src[3]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+2,dtFloat32); //slice + end else + begin + src[0]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+0,dtFloat32); //x + src[1]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+1,dtFloat32); //y + src[2]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+2,dtFloat32); //face + end; + + Result:=emit_OpMakeCube(line,GetVecType(dtFloat32,count),count,@src); + Result^.mark_read; + + end else + begin + + For i:=0 to count-1 do + begin + src[i]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+i,dtFloat32); + end; + + if (count=1) then + begin + Result:=src[0]; + end else + begin + Result:=emit_OpMakeVec(line,GetVecType(dtFloat32,count),count,@src); + Result^.mark_read; + end; + + end; + + offset:=offset+count; +end; + +Function TEmit_MIMG._GatherCoord_u(var offset:DWORD;dim_id:Byte):PsrRegNode; //src +var + src:array[0..3] of PsrRegNode; + i,count:Byte; +begin + Result:=nil; + + count:=GetDimCount(dim_id); + if (FSPI.MIMG.DA<>0) then Inc(count); //slice + + if (dim_id=Dim.Cube) then + begin + //x,y,slice,(face_id+slice*8) + + if (FSPI.MIMG.DA<>0) then //slice + begin + src[0]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+0,dtInt32); //x + src[1]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+1,dtInt32); //y + src[2]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+3,dtInt32); //face TODO: face-slice*8 + src[3]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+2,dtInt32); //slice + end else + begin + src[0]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+0,dtInt32); //x + src[1]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+1,dtInt32); //y + src[2]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+2,dtInt32); //face + end; + + Result:=emit_OpMakeCube(line,GetVecType(dtInt32,count),count,@src); + Result^.mark_read; + + end else + begin + + For i:=0 to count-1 do + begin + src[i]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+i,dtInt32); + end; + + if (count=1) then + begin + Result:=src[0]; + end else + begin + Result:=emit_OpMakeVec(line,GetVecType(dtInt32,count),count,@src); + Result^.mark_read; + end; + + end; + + offset:=offset+count; +end; + +Function TEmit_MIMG._Gather_packed_offset(var offset:DWORD;dim:Byte):PsrRegNode; +var + src:PsrRegNode; +begin + Result:=nil; + + src:=fetch_vsrc8(FSPI.MIMG.VADDR+offset,dtUint32); + 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); + else + Assert(False); + end; + + Result^.mark_read; +end; + +procedure TEmit_MIMG._emit_image_sample(Tgrp:PsrRegNode;info:PsrImageInfo); +var + src:array[0..3] of PsrRegSlot; + + pLayout:PsrDataLayout; + Sgrp:PsrRegNode; + + dst,cmb,coord,lod,offset:PsrRegNode; + + roffset:DWORD; + + node:PSpirvOp; + +begin + if not FRegsStory.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; + + dst:=NewReg(GetVecType(info^.dtype,4)); + + roffset:=0; + + Case FSPI.MIMG.OP of + IMAGE_SAMPLE: + begin + coord:=_GatherCoord_f(roffset,info^.tinfo.Dim); + + if (FExecutionModel=ExecutionModel.Fragment) then + begin + node:=emit_OpImageSampleImplicitLod(line,dst,cmb,coord); + end else + begin + node:=emit_OpImageSampleExplicitLod(line,dst,cmb,coord); + end; + + end; + + IMAGE_SAMPLE_LZ: + begin + coord:=_GatherCoord_f(roffset,info^.tinfo.Dim); + + node:=emit_OpImageSampleExplicitLod(line,dst,cmb,coord); + + node^.AddLiteral(ImageOperands.Lod,'Lod'); + + //0 + lod:=FetchReg(FConsts.Fetchf(dtFloat32,0)); + node^.AddParam(ntReg,lod); + end; + + IMAGE_SAMPLE_LZ_O: + begin + offset:=_Gather_packed_offset(roffset,GetDimCount(info^.tinfo.Dim)); + + coord:=_GatherCoord_f(roffset,info^.tinfo.Dim); + + node:=emit_OpImageSampleExplicitLod(line,dst,cmb,coord); + + node^.AddLiteral(ImageOperands.Lod or ImageOperands.ConstOffset,'Lod|ConstOffset'); + + //0 + lod:=FetchReg(FConsts.Fetchf(dtFloat32,0)); + node^.AddParam(ntReg,lod); + + //1 + node^.AddParam(ntReg,offset); + end; + + else + Assert(false); + end; + + _DistribDmask(dst,info^.dtype); +end; + +procedure TEmit_MIMG._emit_image_load(Tgrp:PsrRegNode;info:PsrImageInfo); +var + dst,coord,lod:PsrRegNode; + + roffset:DWORD; + + node:PSpirvOp; +begin + + dst:=NewReg(GetVecType(info^.dtype,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); + + //fragid T# 2D MSAA + if (info^.tinfo.MS=1) then + begin + Assert(false,'TODO'); + end; + + end; + IMAGE_LOAD_MIP: //All except MSAA + begin + coord:=_GatherCoord_u(roffset,info^.tinfo.Dim); + node:=emit_OpImageFetch(line,Tgrp,dst,coord); + + lod:=fetch_vsrc8(FSPI.MIMG.VADDR+roffset,dtUint32); + Inc(roffset); + node^.AddLiteral(ImageOperands.Lod,'Lod'); + node^.AddParam(ntReg,lod); + end; + else + Assert(false); + end; + + _DistribDmask(dst,info^.dtype); +end; + +procedure TEmit_MIMG._emit_MIMG; +var + src:array[0..7] of PsrRegSlot; + + pLayout:PsrDataLayout; + info:TsrImageInfo; + + Tgrp:PsrRegNode; + +begin + + Assert(FSPI.MIMG.UNRM=0,'FSPI.MIMG.UNRM'); + + pLayout:=nil; + + Case FSPI.MIMG.R128 of + 0: + begin + if not FRegsStory.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); + pLayout:=GroupingSharp(src,rtTSharp8); + //print_tsharp8(pLayout^.pData); + //Tgrp:=GroupingSharp(@src,rtTSharp4); + end; + end; + + info:=GetImageInfo(pLayout^.pData); + + Case FSPI.MIMG.OP of + IMAGE_SAMPLE..IMAGE_SAMPLE_C_LZ_O: //sampled + begin + info.tinfo.Sampled:=1; + Tgrp:=FetchImage(pLayout,info.dtype,info.tinfo); + + _emit_image_sample(Tgrp,@info); + end; + + IMAGE_LOAD..IMAGE_LOAD_MIP_PCK_SGN: //loaded + begin + info.tinfo.Sampled:=1; + Tgrp:=FetchImage(pLayout,info.dtype,info.tinfo); + + _emit_image_load(Tgrp,@info); + end + + else + Assert(false,'MIMG?'+IntToStr(FSPI.MIMG.OP)); + end; + + //Writeln('DMASK=',FSPI.MIMG.DMASK); + //Writeln('VADDR=',FSPI.MIMG.VADDR); + //Writeln('VDATA=',FSPI.MIMG.VDATA); + //Writeln('SRSRC=',FSPI.MIMG.SRSRC); //T# + //Writeln('SSAMP=',FSPI.MIMG.SSAMP); //S# + //writeln; +end; + +end. + + + + diff --git a/spirv/emit_mtbuf.pas b/spirv/emit_mtbuf.pas new file mode 100644 index 0000000..6137130 --- /dev/null +++ b/spirv/emit_mtbuf.pas @@ -0,0 +1,99 @@ +unit emit_MTBUF; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + srReg, + srLayout, + SprvEmit, + srVBufInfo, + emit_vbuf_load, + emit_vbuf_store, + emit_op; + +type + TEmit_MTBUF=object(TEmitOp) + 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); +var + src:array[0..3] of PsrRegSlot; + + grp:PsrDataLayout; + +begin + if not FRegsStory.get_srsrc(FSPI.MTBUF.SRSRC,4,@src) then Assert(false); + + grp:=GroupingSharp(@src,rtVSharp4); + + TEmit_vbuf_load(Self).buf_load( + Buf_info(grp, + dst_sel_identity, + FSPI.MTBUF.DFMT, + FSPI.MTBUF.NFMT, + count) + ); + +end; + +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); + + grp:=GroupingSharp(@src,rtVSharp4); + + TEmit_vbuf_store(Self).buf_store( + Buf_info(grp, + dst_sel_identity, + FSPI.MTBUF.DFMT, + FSPI.MTBUF.NFMT, + count) + ); + +end; + +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_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. + //OFFEN:bit1; //enable offset in VADDR + //IDXEN:bit1; //enable index in VADDR + //GLC:bit1; //globally coherent. + // + //VADDR:Byte; //VGPR address source. + //VDATA:Byte; //Vector GPR to read/write result to. + //SRSRC:bit5; //Scalar GPR that specifies the resource constant, in units of four SGPRs + //SLC:bit1; //System Level Coherent. + //TFE:bit1; //Texture Fail Enable + //SOFFSET:Byte; + +end; + +end. + diff --git a/spirv/emit_mubuf.pas b/spirv/emit_mubuf.pas new file mode 100644 index 0000000..edc4cbc --- /dev/null +++ b/spirv/emit_mubuf.pas @@ -0,0 +1,237 @@ +unit emit_MUBUF; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + ps4_shader, + ps4_pssl, + srTypes, + srReg, + srLayout, + srInput, + spirv, + SprvEmit, + srVBufInfo, + emit_vbuf_load, + emit_vbuf_store, + emit_op; + +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); + end; + +implementation + +procedure TEmit_MUBUF._make_load_zero(dst:PsrRegSlot); +begin + SetConst(dst,FConsts.Fetchi(dtFloat32,0)); +end; + +procedure TEmit_MUBUF._make_load_one(dst:PsrRegSlot); +begin + SetConst(dst,FConsts.Fetchf(dtFloat32,1)); +end; + +procedure TEmit_MUBUF._make_load_comp(dst:PsrRegSlot;rsl:PsrRegNode;i:Byte); +begin + dst^.New(line,dtFloat32); + rsl^.mark_read; + emit_OpCompExtract(line,dst^.current,rsl,i); +end; + +function TEmit_MUBUF._emit_BUFFER_LOAD_VA(src:PPsrRegSlot;count:Byte):Boolean; +var + dst:PsrRegSlot; + + grp:PsrDataLayout; + PV:PVSharpResource4; + + idx:PsrRegNode; + rsl:PsrRegNode; + + inp_idx:PsrInput; + + dsel:Tdst_sel; + + i,d,elem_count:Byte; + +begin + Result:=False; + + idx:=FRegsStory.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 + 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); + + elem_count:=GetElemCount(PV^.dfmt); + + For i:=0 to count-1 do + begin + dst:=FRegsStory.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 + 0:begin //0 + _make_load_zero(dst); + end; + 1:begin //1 + _make_load_one(dst); + end; + 4..7: + begin //RGBA + d:=dsel[i]-4; + + if (dnil); + node^.dst_type:=dtype; + node^.SetDstReg(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); + emit_OpLoad(pLine,dtype,dst,p); +end; + +procedure TEmitOp.emit_OpStore(pLine:PspirvOp;dst:TOpParamSingle;src:PsrRegNode); +Var + node:PSpirvOp; +begin + node:=AddSpirvOp(pLine,Op.OpStore); + node^.dst:=dst; + node^.AddParam(ntReg,src); +end; + +procedure TEmitOp.emit_OpStore(pLine:PspirvOp;dst:PsrVariable;src:PsrRegNode); +Var + p:TOpParamSingle; +begin + dst^.mark_write; + p.SetParam(ntVar,dst); + emit_OpStore(pLine,p,src); +end; + +function TEmitOp.emit_OpCompExtract(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^.AddLiteral(id); + Result:=node; +end; + +function TEmitOp.emit_OpCompConstruct(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); + Result:=node; +end; + +function TEmitOp.emit_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; + + Result:=node; +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; +Var + node:PSpirvOp; +begin + node:=AddSpirvOp(pLine,Op.OpSelectionMerge); + node^.AddParam(ntRefId,pLabel^.dst.AsRefId); + node^.AddLiteral(SelectionControl.None,'None'); + Result:=node; +end; + +function TEmitOp.emit_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^.AddLiteral(LoopControl.None,'None'); + Result:=node; +end; + +function TEmitOp.emit_OpBranch(pLine,pLabel:PspirvOp):PSpirvOp; +Var + node:PSpirvOp; +begin + node:=AddSpirvOp(pLine,Op.OpBranch); + node^.AddParam(ntRefId,pLabel^.dst.AsRefId); + Result:=node; +end; + +function TEmitOp.emit_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); + Result:=node; +end; + +function TEmitOp.emit_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); + 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_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); +begin + //vdst = vsrc0.f * vsrc1.f + vdst.f -> fma + //NoContraction decoration + emit_OpExt3(GlslOp.Fma,dtFloat32,dst,src0,src1,src2); +end; + +procedure TEmitOp.emit_OpFmaI32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode); +var + mul,sum:PsrRegNode; +begin + //vdst = vsrc0.i * vsrc1.i + vdst.i + mul:=NewReg(dtInt32); + sum:=dst^.New(line,dtInt32); + + _emit_OpIMul(line,mul,src0,src1); + + mul^.mark_read; + _emit_OpIAdd(line,sum,mul,src2); +end; + +procedure TEmitOp.emit_OpFmaU32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode); +var + mul,sum:PsrRegNode; +begin + //vdst = vsrc0.u * vsrc1.u + vdst.u + mul:=NewReg(dtUInt32); + sum:=dst^.New(line,dtUInt32); + + _emit_OpIMul(line,mul,src0,src1); + + mul^.mark_read; + _emit_OpIAdd(line,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; +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); +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); +Var + node:PSpirvOp; + rsl:PsrRegNode; +begin + node:=AddSpirvOp(pLine,Op.OpIAddCarry); //need first + + rsl:=NewReg(dtStruct2u); + + node^.dst_type:=FSpirvTypes.Fetch(dtStruct2u); + node^.SetDstReg(rsl); + + node^.AddParam(ntReg,src0); + node^.AddParam(ntReg,src1); + + rsl^.mark_read; + rsl^.mark_read; + + pLine:=node; + pLine:=emit_OpCompExtract(pLine,dst,rsl,0); + pLine:=emit_OpCompExtract(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); +Var + node:PSpirvOp; +begin + node:=AddSpirvOp(OpIAddExt); //need first + + dst^.New(line,dtUint32); //alloc + car^.New(line,dtUint32); //alloc + + 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); +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); +Var + node:PSpirvOp; + rsl:PsrRegNode; +begin + node:=AddSpirvOp(pLine,Op.OpISubBorrow); //need first + + rsl:=NewReg(dtStruct2u); + + node^.dst_type:=FSpirvTypes.Fetch(dtStruct2u); + node^.SetDstReg(rsl); + + node^.AddParam(ntReg,src0); + node^.AddParam(ntReg,src1); + + rsl^.mark_read; + rsl^.mark_read; + + pLine:=node; + pLine:=emit_OpCompExtract(pLine,dst,rsl,0); + pLine:=emit_OpCompExtract(pLine,bor,rsl,1); +end; + +function TEmitOp._emit_OpISub(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.OpISub,dst,src0,src1); +end; + +function TEmitOp._emit_OpAbsDiff(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +begin + Result:=_emit_Op2(pLine,OpAbsDiff,dst,src0,src1); +end; + +function TEmitOp._emit_OpIMul(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.OpIMul,dst,src0,src1); +end; + +function TEmitOp._emit_OpUDiv(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +begin + Result:=_emit_Op2(pLine,Op.OpUDiv,dst,src0,src1); +end; + +function TEmitOp._emit_OpSDiv(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +begin + Result:=_emit_Op2(pLine,Op.OpSDiv,dst,src0,src1); +end; + +function TEmitOp._emit_OpShr(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +begin + Result:=_emit_Op2(pLine,Op.OpShiftRightLogical,dst,src0,src1); +end; + +function TEmitOp._emit_OpShrA(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +begin + Result:=_emit_Op2(pLine,Op.OpShiftRightArithmetic,dst,src0,src1); +end; + +function TEmitOp._emit_OpShl(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp; +begin + Result:=_emit_Op2(pLine,Op.OpShiftLeftLogical,dst,src0,src1); +end; + +procedure TEmitOp.emit_WQM_32(dst:PsrRegSlot;src:PsrRegNode); +begin + emit_Op1(OpWQM32,dtUnknow,dst,src); +end; + +procedure TEmitOp.emit_MED3F(dst:PsrRegSlot;src0,src1,src2:PsrRegNode); +var + min:PsrRegNode; + max:PsrRegNode; + tmp:PsrRegNode; + ret:PsrRegNode; +begin + //emit_Op3(OpMED3F,dtFloat32,dst,src0,src1,src2); + + 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)) +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^.pWriter.SetParam(ntReg,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; +Var + p:PsrCacheOp; + node:PSpirvOp; +begin + Assert((count>0) and (count<=3)); + + pLine:=GetMaxPlace(pLine,1,@src); + + p:=FCacheOps.Fetch(pLine^.pParent,OpPackOfs,rtype,1,@src); + Result:=p^.pReg; + if (Result=nil) then + begin + node:=AddSpirvOp(pLine,OpPackOfs); //need first + + Result:=NewReg(rtype); + + node^.SetDstReg(Result); + node^.AddLiteral(ord(rtype)); + node^.AddLiteral(count); + node^.AddParam(ntReg,src); + + p^.pReg:=Result; //save + end else + begin + //deref + src^.mark_unread; + end; +end; + +function TEmitOp.emit_OpSampledImage(pLine:PspirvOp;Tgrp,Sgrp:PsrRegNode;dtype:TsrDataType;info:TsrTypeImageInfo):PsrRegNode; +Var + src:array[0..1] of PsrRegNode; + pType:PsrType; + p:PsrCacheOp; + 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 + begin + Tgrp^.mark_read; + Sgrp^.mark_read; + + Result:=NewReg(dtTypeSampledImage); + + node:=AddSpirvOp(pLine,Op.OpSampledImage); + + pType:=FSpirvTypes.FetchImage(FSpirvTypes.Fetch(dtype),info); + node^.dst_type:=FSpirvTypes.FetchSampledImage(pType); + node^.SetDstReg(Result); + + node^.AddParam(ntReg,Tgrp); + node^.AddParam(ntReg,Sgrp); + + p^.pReg:=Result; //save + 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); +begin + if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then + begin + emit_Op2(Op.OpIAdd,dtInt32,dst,src0,src1); + end else + begin + emit_Op2(Op.OpIAdd,dtUInt32,dst,src0,src1); + end; +end; + +procedure TEmitOp.emit_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); + end else + begin + emit_Op2(Op.OpISub,dtUInt32,dst,src0,src1); + end; +end; + +procedure TEmitOp.emit_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); + end else + begin + emit_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_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; +Var + node:PSpirvOp; +begin + node:=AddSpirvOp(pLine,Op.OpImageSampleImplicitLod); + node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); + node^.SetDstReg(dst); + + node^.AddParam(ntReg,cmb); + node^.AddParam(ntReg,coord); + + Result:=node; +end; + +function TEmitOp.emit_OpImageSampleExplicitLod(pLine:PspirvOp;dst,cmb,coord:PsrRegNode):PSpirvOp; +Var + node:PSpirvOp; +begin + node:=AddSpirvOp(pLine,Op.OpImageSampleExplicitLod); + node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); + node^.SetDstReg(dst); + + node^.AddParam(ntReg,cmb); + node^.AddParam(ntReg,coord); + + Result:=node; +end; + +function TEmitOp.emit_OpImageFetch(pLine:PspirvOp;Tgrp,dst,coord:PsrRegNode):PSpirvOp; +Var + node:PSpirvOp; +begin + Tgrp^.mark_read; + + node:=AddSpirvOp(pLine,Op.OpImageFetch); + node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); + node^.SetDstReg(dst); + + node^.AddParam(ntReg,Tgrp); + node^.AddParam(ntReg,coord); + + Result:=node; +end; + +function TEmitOp.emit_OpImageRead(pLine:PspirvOp;Tgrp,dst,idx:PsrRegNode):PspirvOp; +Var + node:PSpirvOp; +begin + Tgrp^.mark_read; + + node:=AddSpirvOp(pLine,Op.OpImageRead); + node^.dst_type:=FSpirvTypes.Fetch(dst^.dtype); + node^.SetDstReg(dst); + + node^.AddParam(ntReg,Tgrp); + + if (idx<>nil) then + begin + node^.AddParam(ntReg,idx); + end else + begin + node^.AddParam(ntConst,FConsts.Fetchi(dtUint32,0)); + end; + + Result:=node; +end; + +function TEmitOp.emit_OpImageWrite(pLine:PspirvOp;Tgrp,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); + + if (idx<>nil) then + begin + node^.AddParam(ntReg,idx); + end else + begin + node^.AddParam(ntConst,FConsts.Fetchi(dtUint32,0)); + end; + + node^.AddParam(ntReg,src); + + Result:=node; +end; + + +end. + diff --git a/spirv/emit_post.pas b/spirv/emit_post.pas new file mode 100644 index 0000000..35ab951 --- /dev/null +++ b/spirv/emit_post.pas @@ -0,0 +1,1298 @@ +unit emit_post; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + spirv, + srNodes, + srTypes, + srConst, + srReg, + srVariable, + srVolatile, + srLayout, + srBuffer, + srOp, + srOpUtils, + SprvEmit, + emit_op; + +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; + + function RegFindCond(pLine:PspirvOp;var node:PsrRegNode):Integer; + function RegCollapse({%H-}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 NodeOpStrict(node:PSpirvOp):Integer; + + function OnOpStep1(node:PSpirvOp):Integer; //backward + function OnOpStep2(node:PSpirvOp):Integer; //forward + function OnOpStep3(node:PSpirvOp):Integer; //forward + function OnOpStep4(node:PSpirvOp):Integer; //forward + function OnOpStep5(node:PSpirvOp):Integer; //backward + + function PostFuncAnalize:Integer; + + function EnumChain(p:PsrDataLayout;cb:TChainCb):Integer; + function EnumChain(cb:TChainCb):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; + 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; +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; +end; + +function EnumLineRegs(cb:TRegsCb;pLine:PSpirvOp):Integer; +var + node:POpParamNode; +begin + Result:=0; + if (cb=nil) or (pLine=nil) then Exit; + node:=pLine^.pParam.pHead; + While (node<>nil) do + begin + Case node^.ntype of + ntReg: + begin + Result:=Result+cb(pLine,node^.pData); + end + else; + end; + node:=node^.pNext; + end; +end; + +function EnumBlockOpForward(cb:TPostCb;pBlock:PsrOpBlock):Integer; +var + node:PSpirvOp; +begin + Result:=0; + if (pBlock=nil) or (cb=nil) then Exit; + node:=pBlock^.pHead; + repeat + While (node<>nil) do + 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; + 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; + +function EnumBlockOpBackward(cb:TPostCb;pBlock:PsrOpBlock):Integer; +var + node:PSpirvOp; +begin + Result:=0; + if (pBlock=nil) or (cb=nil) then Exit; + node:=pBlock^.pTail; + repeat + While (node<>nil) do + 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; + 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; + +function TSprvEmit_post.RegFindCond(pLine:PspirvOp;var node:PsrRegNode):Integer; +var + pBlock:PsrOpBlock; + tmp:PsrOpBlock; + src:PsrRegNode; + p:PspirvOp; + n:Boolean; +begin + Result:=0; + if (node=nil) then Exit; + + pBlock:=pLine^.pParent; + src:=RegDown(node); + n:=false; + + repeat + if src^.is_const then Exit; + + tmp:=pBlock^.FindUpCond(src); + 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)); + Exit(1); + end; + + p:=src^.AsOp; + if (p=nil) then Exit; + + Case p^.OpId of + Op.OpLogicalNot:; + Op.OpNot:; + else + Exit; + end; + + src:=p^.ParamNode(0)^.AsReg; + if (src=nil) then Exit; + src:=RegDown(src); + n:=not n; + + until false; +end; + +function TSprvEmit_post.RegCollapse(pLine:PspirvOp;var node:PsrRegNode):Integer; +var + new,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; + else + Break; + end; + end; + + 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^.pWriter.SetParam(ntReg,old); + end; + end; +end; + +function TSprvEmit_post.RegTypecast(pLine:PspirvOp;var node:PsrRegNode):Integer; +var + new,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; + end; + end; + + 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 //bitcast + old^.mark_unread; + node:=FBitcast.FetchCast(node^.dtype,old); + Inc(Result); + end; + end; +end; + +function TSprvEmit_post.RegSTStrict(pLine:PspirvOp;var node:PsrRegNode):Integer; +var + dtype:TsrDataType; + dst,old:PsrRegNode; +begin + Result:=0; + if (node^.dtype=dtBool) then Exit; + dst:=pLine^.dst.AsReg; + 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); + Inc(Result); + end; +end; + +function TSprvEmit_post.RegVTStrict(pLine:PspirvOp;var node:PsrRegNode):Integer; +var + dtype:TsrDataType; + dst,old:PsrRegNode; +begin + Result:=0; + dst:=pLine^.dst.AsReg; + if (dst=nil) then Exit; + dtype:=GetVecChild(dst^.dtype); + 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; + Inc(Result); + end; +end; + +function TSprvEmit_post.NodeOpSameOp(node:PSpirvOp):Integer; +var + tmp:PspirvOp; + dst,src:PsrRegNode; +begin + Result:=0; + if (node^.dst.ntype<>ntReg) then Exit; //is reg + + Case node^.OpId of + Op.OpLoad:; + Op.OpCompositeConstruct:; + OpMakeExp:; + OpMakeVec:; + OpPackOfs:; + else + Exit; + end; + + tmp:=FindUpSameOp(node^.pPrev,node); + if (tmp=nil) then Exit; + + src:=tmp^.dst.AsReg; + dst:=node^.dst.AsReg; + + if (src=nil) or (dst=nil) then Exit; + + src^.mark_read; + dst^.pWriter.SetParam(ntReg,src); + + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + + Result:=1; +end; + +function TSprvEmit_post.NodeOpStrict(node:PSpirvOp):Integer; +begin + Result:=0; + if (node^.dst.ntype<>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); + else; + end; + +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; + 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; + 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; + 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; + 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; + end; +end; + +function TSprvEmit_post.PostFuncAnalize:Integer; +var + pFunc:PSpirvFunc; + data_layout:Boolean; + i:Integer; +begin + Result:=0; + data_layout:=false; + //backward analize + pFunc:=FSpirvFuncs.FList.pTail; + While (pFunc<>nil) do + begin + + data_layout:=(FMain=pFunc); + + repeat + + repeat + + repeat + i:=EnumBlockOpBackward(@OnOpStep1,@pFunc^.FTop); + if (i=0) then Break; + Result:=Result+i; + until false; + + i:=EnumBlockOpForward(@OnOpStep2,@pFunc^.FTop); + if (i=0) then Break; + Result:=Result+i; + until false; + + i:=EnumBlockOpForward (@OnOpStep3,@pFunc^.FTop); + if (i=0) then Break; + Result:=Result+i; + until false; + + if data_layout then + begin + Result:=Result+PostDataLayoutAnalize; + data_layout:=false; + end; + + 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; + end; +end; + +function TSprvEmit_post.EnumChain(p:PsrDataLayout;cb:TChainCb):Integer; +var + node:PsrChain; +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; +end; + +function TSprvEmit_post.PostDataLayoutAnalize:Integer; +begin + Result:=0; + + FDataLayouts.AllocID; + + Result:=Result+EnumChain(@OnChainField); + + FBuffers.ApplyBufferType; + FBuffers.AlignOffset; + FBuffers.FillSpace; + FBuffers.AllocID; + FBuffers.EnumAllField(@OnFieldType); + + Result:=Result+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; + fset_index:Boolean; +begin + _count:=0; + _stride:=0; + + if (pChain^.key.ext.pIndex<>nil) then + begin + //RuntimeArray + + buf:=FBuffers.Fetch(pChain^.parent,0); + repeat + + _offset:=pChain^.key.offset; + F:=buf^.FTop.FetchRuntimeArray(_offset,pChain^.key.ext.stride); + repeat + + Case F.fValue of + frNotFit :Break; + frIdent :Exit(F.pField); + frVectorAsValue:Exit(F.pField); + frValueInVector:_offset:=_offset-F.pField^.offset; + frValueInArray :_offset:=_offset-F.pField^.offset; + end; + F:=F.pField^.FetchValue(_offset,pChain^.key.size,dtype); + + until (F.fValue<>frNotFit); + if (F.fValue<>frNotFit) then Break; + + buf:=FBuffers.NextCast(buf); + until false; + + end else + begin + //Value/Vector + + buf:=FBuffers.Fetch(pChain^.parent,0); + fset_index:=False; + repeat + + _offset:=pChain^.key.offset; + F.pField:=@buf^.FTop; + repeat + + F:=F.pField^.FetchValue(_offset,pChain^.key.size,dtype); + Case F.fValue of + frNotFit :Break; + frIdent, + frVectorAsValue: + begin + if fset_index then + begin + Assert(pChain^.key.ext.pIndex=nil); + + ext:=Default(TsrChainExt); + ext.pIndex:=FetchReg(FConsts.Fetchi(dtUint32,_count)); + ext.stride:=_stride; + pNew:=pChain^.parent^.Fetch(_offset,pChain^.key.size,@ext); + + pNew^.read_count :=pChain^.read_count ; + pNew^.write_count:=pChain^.write_count; + pNew^.rSlot :=pChain^.rSlot ; + + pChain^.read_count :=0; + pChain^.write_count:=0; + pChain^.rSlot :=Default(TsrRegSlot); + + pChain:=pNew; + end; + Exit(F.pField); + end; + frValueInVector:_offset:=_offset-F.pField^.offset; + frValueInArray : + begin + Assert(not fset_index); + _offset:=_offset-F.pField^.offset; + _stride:=F.pField^.stride; + _count :=_offset div _stride; + _offset:=_offset mod _stride; + fset_index:=true; + end; + end; + + until (F.fValue<>frNotFit); + if (F.fValue<>frNotFit) then Break; + + buf:=FBuffers.NextCast(buf); + fset_index:=False; + until false; + + end; + + 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; + //Writeln('OnChainsField:',dtype,':',node^.key.offset); + pField:=FetchField(node,dtype); + node^.pField:=pField; + if (pField^.dtype<>dtype) then + begin + dtype:=pField^.dtype; + SetLoadType(node,dtype); + + //Writeln(pField^.dtype,'<>',dtype); + //Assert(false,'TODO'); + end; + FBuffers.UpdateStorage(node,pField^.pBuffer); +end; + +procedure TSprvEmit_post.OnFieldType(node:PsrField); +var + count:PtrUint; + sType,pType:PsrType; + child:PsrField; +begin + if (node^.pType<>nil) then Exit; + + if (node^.dtype in [dtTypeStruct,dtTypeArray,dtTypeRuntimeArray]) then + begin + if node^.IsStructNotUsed then + begin + child:=node^.First; + 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); + + count:=0; + child:=node^.First; + While (child<>nil) do + begin + Assert(child^.pType<>nil); + child^.pType^.mark_read; + sType^.SetCompItem(count,child^.pType); + Inc(count); + child:=node^.Next(child); + end; + + sType:=FSpirvTypes.FetchStructNode(sType,count,node); + end; + + Case node^.dtype of + dtTypeArray: + begin + count:=node^.size div node^.stride; + pType:=FSpirvTypes.FetchArray(sType,count,node^.stride); + end; + dtTypeRuntimeArray: + begin + pType:=FSpirvTypes.FetchRuntimeArray(sType,node^.stride); + end; + else + begin + pType:=sType; + end; + end; + + node^.pType:=pType; + + if (node^.parent=nil) then + begin + AllocBufferVar(node^.pBuffer); + end; + + end else + begin + node^.pType:=FSpirvTypes.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; + pIndex:PsrRegNode; + pReg:PsrRegNode; + pField:PsrField; + Parent:PsrField; + src:PsrVariable; + pParam:POpParamNode; + //dtype:TsrDataType; +begin + Result:=1; + + pIndex:=RegDown(node^.key.ext.pIndex); + if (pIndex=nil) or (pIndex^.is_const) then + begin + pLine:=init_line; + end else + begin + pLine:=node^.rSlot.first^.pLine; + Assert(pLine<>nil); + pLine:=pLine^.pPrev; + 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); + + //dtype:=node^.GetRegType; + //if (pField^.dtype<>dtype) then + //begin + // Writeln(pField^.dtype,'<>',dtype); + // Assert(false,'TODO'); + //end; + + pParam:=pLine^.pParam.pTail; + repeat + + Parent:=pField^.parent; + if (Parent<>nil) then + Case Parent^.dtype of + dtTypeStruct: + begin + pReg:=FetchReg(FConsts.Fetchi(dtUint32,pField^.FID)); + pLine^.AddParamAfter(pParam,ntReg,pReg); + end; + dtTypeArray, + dtTypeRuntimeArray: + begin + if not Parent^.IsStructNotUsed then + begin + pReg:=FetchReg(FConsts.Fetchi(dtUint32,pField^.FID)); + pLine^.AddParamAfter(pParam,ntReg,pReg); + end; + Assert(pIndex<>nil); + pIndex^.mark_read; + pLine^.AddParamAfter(pParam,ntReg,pIndex); + end; + else + if IsVector(Parent^.dtype) then + begin + pReg:=FetchReg(FConsts.Fetchi(dtUint32,pField^.FID)); + pLine^.AddParamAfter(pParam,ntReg,pReg); + end; + end; + + pField:=Parent; + until (pField=nil); + +end; + +function TSprvEmit_post.PostConstAnalize:Integer; +var + node:PsrConst; +begin + Result:=0; + node:=FConsts.FList.pTail; + While (node<>nil) do + begin + if (node^.read_count=0) then + begin + node^.Clear; //delete links + FConsts.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; + end; +end; + +function TSprvEmit_post.PostVariableAnalize:Integer; +var + node:PsrVariable; + pType:PsrType; +begin + Result:=0; + node:=FVariables.pTail; + While (node<>nil) do + begin + if (node^.read_count=0) and (node^.write_count=0) then + begin + node^.Clear; //delete links + FVariables.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); + end; + node:=node^.pPrev; + end; +end; + +function TSprvEmit_post.PostTypeAnalize(first:Boolean):Integer; +var + node:PsrType; +begin + Result:=0; + node:=FSpirvTypes.FList.pTail; + While (node<>nil) do + begin + if (node^.read_count=0) then + begin + node^.Clear; //delete links + FSpirvTypes.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; + end; +end; + +end. + diff --git a/spirv/emit_post_op.pas b/spirv/emit_post_op.pas new file mode 100644 index 0000000..175505b --- /dev/null +++ b/spirv/emit_post_op.pas @@ -0,0 +1,2306 @@ +unit emit_post_op; + +{$mode ObjFPC}{$H+} + +interface + +uses + sysutils, + bittype, + Half16, + srLabel, + srNodes, + srTypes, + srRefId, + srConst, + srReg, + srOp, + srOpUtils, + spirv, + SprvEmit, + emit_op, + emit_post; + +type + TEmitPostOp=object(TSprvEmit_post) + function PostForward1(node:PSpirvOp):Integer; + function PostForward2(node:PSpirvOp):Integer; + // + function OpConvert1(node:PSpirvOp):Integer; + function OnCompositeExtract1(node:PSpirvOp):Integer; + function OnIAdd1(node:PSpirvOp):Integer; + function OnISub1(node:PSpirvOp):Integer; + function OnShr1(node:PSpirvOp):Integer; + function _OnShr_ext1(node,pOp:PSpirvOp;pShrVal:PsrConst):Integer; + function _OnShr_ext_and(node:PSpirvOp;pShrVal,pAndVal:PsrConst):Integer; + function _OnShr_ext_add(node,pOp0,pOp1:PSpirvOp;pShrVal:PsrConst):Integer; + function OnAbsDiff1(node:PSpirvOp):Integer; + function OnWQM32__1(node:PSpirvOp):Integer; + function OnPackOfs1(node:PSpirvOp):Integer; + function OnMakeCM1(node:PSpirvOp):Integer; + // + function OnBitwiseAnd1(node:PSpirvOp):Integer; + function OnLogicalAnd1(node:PSpirvOp):Integer; + function OnBitwiseOr1(node:PSpirvOp):Integer; + function OnLogicalOr1(node:PSpirvOp):Integer; + function OnNot1(node:PSpirvOp):Integer; + function OnBranchConditional1(node:PSpirvOp):Integer; + // + function OnSelect1(node:PSpirvOp):Integer; + // + procedure MakeVecConst(rtype:TsrDataType;dst:PsrRegNode;count:Byte;src:PPsrRegNode); + procedure MakeVecOne(dst:PsrRegNode;src:PPsrRegNode); + function MakeVecComp(pLine:PSpirvOp;rtype:TsrDataType;dst:PsrRegNode;count:Byte;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; + end; + +implementation + +function TEmitPostOp.PostForward1(node:PSpirvOp):Integer; +begin + Result:=0; + + Case node^.OpId of + + Op.OpFConvert, + Op.OpConvertFToU, + Op.OpConvertFToS, + Op.OpConvertSToF, + Op.OpConvertUToF :Result:=OpConvert1(node); + + Op.OpCompositeExtract :Result:=OnCompositeExtract1(node); + + Op.OpIAdd :Result:=OnIAdd1(node); + Op.OpISub :Result:=OnISub1(node); + Op.OpShiftRightLogical, + Op.OpShiftRightArithmetic:Result:=OnShr1(node); + + OpAbsDiff :Result:=OnAbsDiff1(node); + OpWQM32 :Result:=OnWQM32__1(node); + OpPackOfs :Result:=OnPackOfs1(node); + OpMakeCM :Result:=OnMakeCM1(node); + + Op.OpSelect :Result:=Result+OnSelect1(node); + + Op.OpBitwiseAnd :Result:=OnBitwiseAnd1(node); + Op.OpLogicalAnd :Result:=OnLogicalAnd1(node); + Op.OpBitwiseOr :Result:=OnBitwiseOr1(node); + Op.OpLogicalOr :Result:=OnLogicalOr1(node); + + Op.OpNot :Result:=OnNot1(node); + + Op.OpBranchConditional:Result:=OnBranchConditional1(node); + + else; + end; +end; + +function TEmitPostOp.PostForward2(node:PSpirvOp):Integer; +begin + Result:=0; + + Case node^.OpId of + + //Op.OpIAdd :Result:=OnIAdd1(node); + //Op.OpISub :Result:=OnISub1(node); + + OpIAddExt:Result:=OnIAddExt2(node); + OpISubExt:Result:=OnISubExt2(node); + OpMakeVec:Result:=OnMakeVec2(node); + //OpMED3F :Result:=OpMED3F__2(node); + + Op.OpReturn:Result:=OnReturn_2(node); + OpMakeExp :Result:=OnMakeExp2(node); + + OpCUBEID:Assert(False,'TODO'); + OpCUBESC:Assert(False,'TODO'); + OpCUBETC:Assert(False,'TODO'); + OpCUBEMA:Assert(False,'TODO'); + + end; + +end; + +function _classif_const(dtype:TsrDataType;value:QWORD):Integer; +begin + if (value=0) then //always false + begin + Result:=0; + end else + if (value=GetTypeHigh(dtype)) then //always true + begin + Result:=1; + end else + begin + Result:=-1; + end; +end; + +function _classif_const(p:PsrConst):Integer; +begin + Result:=_classif_const(p^.key.dtype,p^.GetData); +end; + +function BinType(t:TsrDataType):TsrDataType; +begin + Case t of + dtBool :Result:=dtBool; + dtInt32, + dtUint32:Result:=dtUint32; + else + Result:=dtUnknow; + end; +end; + +function TEmitPostOp.OnBitwiseAnd1(node:PSpirvOp):Integer; +var + dtype:TsrDataType; + dst:PsrRegNode; + src:array[0..1] of PsrRegNode; + data:array[0..1] of QWORD; + + procedure _SetConst(dtype:TsrDataType;value:QWORD); + begin + dst^.SetConst(FConsts.Fetch(dtype,value)); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + Inc(Result); + end; + + procedure _SetReg(src:PsrRegNode); + begin + src^.mark_read; + dst^.pWriter.SetParam(ntReg,src); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + Inc(Result); + end; + + procedure _SetOpType(OpId:DWORD;dtype:TsrDataType); + begin + Result:=0; + if (node^.OpId<>OpId) then + begin + node^.OpId:=OpId; + Inc(Result); + end; + Result:=Result+PrepTypeDst(node^.dst.pData,dtype); + dst:=node^.dst.pData; + // + dtype:=dst^.dtype; + if (node^.dst_type<>nil) then + begin + node^.dst_type^.mark_unread; + end; + node^.dst_type:=FSpirvTypes.Fetch(dtype); + end; + + procedure _SetType(dtype:TsrDataType); + begin + Result:=Result+PrepTypeDst(node^.dst.pData,dtype); + dst:=node^.dst.pData; + // + dtype:=dst^.dtype; + if (node^.dst_type<>nil) then + begin + node^.dst_type^.mark_unread; + end; + node^.dst_type:=FSpirvTypes.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]); + + if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; + + if src[0]^.is_const and src[1]^.is_const then + begin + //need a const calc + data[0]:=src[0]^.AsConst^.GetData; + data[1]:=src[1]^.AsConst^.GetData; + + dtype:=LazyType3(dst^.dtype,src[0]^.dtype,src[1]^.dtype); + _SetConst(dtype,data[0] and data[1]); + Exit; + end; + + if (dst^.is_bool) or ((src[0]^.is_bool_or_const_bool) and (src[1]^.is_bool_or_const_bool)) then + begin + + if (src[0]^.is_const) then + begin + Case src[0]^.AsConst^.AsBool of + True :_SetReg(node^.ParamNode(1)^.pData); + False:_SetConst(dtBool,0); + end; + Exit; + end; + if (src[1]^.is_const) then + begin + Case src[1]^.AsConst^.AsBool of + True :_SetReg(node^.ParamNode(0)^.pData); + False:_SetConst(dtBool,0); + end; + Exit; + end; + + _SetOpType(Op.OpLogicalAnd,dtBool); + end else + begin + dtype:=LazyType3(BinType(dst^.dtype),BinType(src[0]^.dtype),BinType(src[1]^.dtype)); + dtype:=LazyType2(dtype,dtUint32); + + if (src[0]^.is_const) then + begin + case _classif_const(src[0]^.AsConst) of + 0:_SetConst(dtype,0); //always false + 1:_SetReg(node^.ParamNode(1)^.pData); //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 + end; + end; + + if (Result<>0) then Exit; //_SetConst/_SetReg + _SetType(dtype); + end; + + Result:=Result+PrepTypeParam(node^.ParamNode(0),dst^.dtype); + Result:=Result+PrepTypeParam(node^.ParamNode(1),dst^.dtype); +end; + +Function _FindNest_LAnd(node,src:PsrRegNode):Boolean; +var + p:PSpirvOp; + tmp:PsrRegNode; +begin + Result:=False; + if (node=nil) or (src=nil) then Exit; + + repeat + + p:=node^.AsOp; + if (p<>nil) then + if (p^.OpId=Op.OpLogicalAnd) then + begin + tmp:=p^.ParamNode(0)^.AsReg; + tmp:=RegDown(tmp); + 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); + if (tmp=src) then Exit(True); + node:=tmp; + Continue; //cycle + end; + Exit; + + until false; + +end; + +function TEmitPostOp.OnLogicalAnd1(node:PSpirvOp):Integer; +var + dst:PsrRegNode; + src:array[0..1] of PsrRegNode; + data:array[0..1] of QWORD; + + procedure _SetConst(dtype:TsrDataType;value:QWORD); + begin + dst^.SetConst(FConsts.Fetch(dtype,value)); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + Inc(Result); + end; + + procedure _SetReg(src:PsrRegNode); + begin + src^.mark_read; + dst^.pWriter.SetParam(ntReg,src); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + 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]); + + if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; + + if src[0]^.is_const and src[1]^.is_const then + begin + //need a const calc + data[0]:=src[0]^.AsConst^.GetData; + data[1]:=src[1]^.AsConst^.GetData; + + _SetConst(dtBool,data[0] and data[1]); + Exit; + end; + + if (src[0]^.is_const) then + begin + Case src[0]^.AsConst^.AsBool of + True :_SetReg(node^.ParamNode(1)^.pData); + False:_SetConst(dtBool,0); + end; + Exit; + end; + if (src[1]^.is_const) then + begin + Case src[1]^.AsConst^.AsBool of + True :_SetReg(node^.ParamNode(0)^.pData); + False:_SetConst(dtBool,0); + end; + Exit; + end; + + if _FindNest_LAnd(src[1],src[0]) then //Find src[0] in src[1] + begin + _SetReg(node^.ParamNode(1)^.pData); + Exit; + end; + + if _FindNest_LAnd(src[0],src[1]) then //Find src[1] in src[0] + begin + _SetReg(node^.ParamNode(0)^.pData); + Exit; + end; + + Result:=Result+PrepTypeParam(node^.ParamNode(0),dtBool); + Result:=Result+PrepTypeParam(node^.ParamNode(1),dtBool); +end; + +// + +function TEmitPostOp.OnBitwiseOr1(node:PSpirvOp):Integer; +var + dtype:TsrDataType; + dst:PsrRegNode; + src:array[0..1] of PsrRegNode; + data:array[0..1] of QWORD; + + procedure _SetConst(dtype:TsrDataType;value:QWORD); + begin + dst^.SetConst(FConsts.Fetch(dtype,value)); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + Inc(Result); + end; + + procedure _SetReg(src:PsrRegNode); + begin + src^.mark_read; + dst^.pWriter.SetParam(ntReg,src); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + Inc(Result); + end; + + procedure _SetOpType(OpId:DWORD;dtype:TsrDataType); + begin + Result:=0; + if (node^.OpId<>OpId) then + begin + node^.OpId:=OpId; + Inc(Result); + end; + Result:=Result+PrepTypeDst(node^.dst.pData,dtype); + dst:=node^.dst.pData; + // + dtype:=dst^.dtype; + if (node^.dst_type<>nil) then + begin + node^.dst_type^.mark_unread; + end; + node^.dst_type:=FSpirvTypes.Fetch(dtype); + end; + + procedure _SetType(dtype:TsrDataType); + begin + Result:=Result+PrepTypeDst(node^.dst.pData,dtype); + dst:=node^.dst.pData; + // + dtype:=dst^.dtype; + if (node^.dst_type<>nil) then + begin + node^.dst_type^.mark_unread; + end; + node^.dst_type:=FSpirvTypes.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]); + + if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; + + if src[0]^.is_const and src[1]^.is_const then + begin + //need a const calc + data[0]:=src[0]^.AsConst^.GetData; + data[1]:=src[1]^.AsConst^.GetData; + + dtype:=LazyType3(dst^.dtype,src[0]^.dtype,src[1]^.dtype); + _SetConst(dtype,data[0] or data[1]); + Exit; + end; + + if (dst^.is_bool) or ((src[0]^.is_bool_or_const_bool) and (src[1]^.is_bool_or_const_bool)) then + begin + + if (src[0]^.is_const) then + begin + Case src[0]^.AsConst^.AsBool of + True :_SetConst(dtBool,1); + False:_SetReg(node^.ParamNode(1)^.pData); + end; + Exit; + end; + if (src[1]^.is_const) then + begin + Case src[1]^.AsConst^.AsBool of + True :_SetConst(dtBool,1); + False:_SetReg(node^.ParamNode(0)^.pData); + end; + Exit; + end; + + _SetOpType(Op.OpLogicalOr,dtBool); + end else + begin + dtype:=LazyType3(BinType(dst^.dtype),BinType(src[0]^.dtype),BinType(src[1]^.dtype)); + dtype:=LazyType2(dtype,dtUint32); + + 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 + 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 + end; + end; + + if (Result<>0) then Exit; //_SetConst/_SetReg + _SetType(dtype); + end; + + Result:=Result+PrepTypeParam(node^.ParamNode(0),dst^.dtype); + Result:=Result+PrepTypeParam(node^.ParamNode(1),dst^.dtype); +end; + +function TEmitPostOp.OnLogicalOr1(node:PSpirvOp):Integer; +var + dst:PsrRegNode; + src:array[0..1] of PsrRegNode; + data:array[0..1] of QWORD; + + procedure _SetConst(dtype:TsrDataType;value:QWORD); + begin + dst^.SetConst(FConsts.Fetch(dtype,value)); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + Inc(Result); + end; + + procedure _SetReg(src:PsrRegNode); + begin + src^.mark_read; + dst^.pWriter.SetParam(ntReg,src); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + 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]); + + if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; + + if src[0]^.is_const and src[1]^.is_const then + begin + //need a const calc + data[0]:=src[0]^.AsConst^.GetData; + data[1]:=src[1]^.AsConst^.GetData; + + _SetConst(dtBool,data[0] or data[1]); + Exit; + end; + + if (src[0]^.is_const) then + begin + Case src[0]^.AsConst^.AsBool of + True :_SetConst(dtBool,1); + False:_SetReg(node^.ParamNode(1)^.pData); + end; + Exit; + end; + if (src[1]^.is_const) then + begin + Case src[1]^.AsConst^.AsBool of + True :_SetConst(dtBool,1); + False:_SetReg(node^.ParamNode(0)^.pData); + end; + Exit; + end; + + Result:=Result+PrepTypeParam(node^.ParamNode(0),dtBool); + Result:=Result+PrepTypeParam(node^.ParamNode(1),dtBool); +end; + +function TEmitPostOp.OnNot1(node:PSpirvOp):Integer; +var + dtype:TsrDataType; + dst:PsrRegNode; + src:PsrRegNode; + data:array[0..1] of QWORD; + + procedure _SetConst(dtype:TsrDataType;value:QWORD); + begin + dst^.SetConst(FConsts.Fetch(dtype,value)); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + Inc(Result); + end; + + procedure _SetOpType(OpId:DWORD;dtype:TsrDataType); + begin + Result:=0; + if (node^.OpId<>OpId) then + begin + node^.OpId:=OpId; + Inc(Result); + end; + Result:=Result+PrepTypeDst(node^.dst.pData,dtype); + dst:=node^.dst.pData; + // + dtype:=dst^.dtype; + if (node^.dst_type<>nil) then + begin + node^.dst_type^.mark_unread; + end; + node^.dst_type:=FSpirvTypes.Fetch(dtype); + end; + + procedure _SetType(dtype:TsrDataType); + begin + Result:=Result+PrepTypeDst(node^.dst.pData,dtype); + dst:=node^.dst.pData; + // + dtype:=dst^.dtype; + if (node^.dst_type<>nil) then + begin + node^.dst_type^.mark_unread; + end; + node^.dst_type:=FSpirvTypes.Fetch(dtype); + end; + +begin + Result:=0; + dst:=node^.dst.AsReg; + src:=node^.ParamNode(0)^.AsReg; + src:=RegDown(src); + if (dst=nil) or (src=nil) then Exit; + + if src^.is_const then + begin + dtype:=LazyType2(dst^.dtype,src^.dtype); + + //need a const calc + data[0]:=src^.AsConst^.GetData; + data[1]:=GetTypeHigh(dtype); + + _SetConst(dtype,(not data[0]) and data[1]); + Exit; + end; + + if (dst^.is_bool) or (src^.is_bool_or_const_bool) then + begin + + if (src^.is_const) then + begin + Case src^.AsConst^.AsBool of + True :_SetConst(dtBool,0); + False:_SetConst(dtBool,1); + end; + Exit; + end; + + _SetOpType(Op.OpLogicalNot,dtBool); + end else + begin + dtype:=LazyType2(BinType(dst^.dtype),BinType(src^.dtype)); + dtype:=LazyType2(dtype,dtUint32); + _SetType(dtype); + end; + + Result:=Result+PrepTypeParam(node^.ParamNode(0),dst^.dtype); +end; + +function TEmitPostOp.OnBranchConditional1(node:PSpirvOp):Integer; +var + cur,src,prv:PsrRegNode; + pOp:PSpirvOp; + pLabel:array[0..1] of PsrRefId; +begin + Result:=0; + cur:=node^.ParamNode(0)^.AsReg; + if (cur=nil) then Exit; + src:=RegDown(cur); + + pOp:=src^.AsOp; + if (pOp=nil) then Exit; + + Case pOp^.OpId of + Op.OpLogicalNot:; + //Op.OpNot:; + else + Exit; + end; + + prv:=pOp^.ParamNode(0)^.AsReg; + if (prv=nil) then Exit; + + node^.ParamNode(0)^.pData:=prv; //set new + + pLabel[0]:=node^.ParamNode(1)^.pData; //read + pLabel[1]:=node^.ParamNode(2)^.pData; //read + + node^.ParamNode(1)^.pData:=pLabel[1]; //swap + node^.ParamNode(2)^.pData:=pLabel[0]; //swap + + prv^.mark_read; + RegUnmark(cur); + + Inc(Result); +end; + +function TEmitPostOp.OpConvert1(node:PSpirvOp):Integer; +var + dst,src:PsrRegNode; + pc:PsrConst; + + procedure _SetConst(dtype:TsrDataType;value:QWORD); + begin + dst^.SetConst(FConsts.Fetch(dtype,value)); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + Inc(Result); + end; + + procedure _SetConst(dtype:TsrDataType;value:double); + 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); + Inc(Result); + end; + + function minz(i:Int64):QWORD; + begin + if (i>0) then Result:=i else Result:=0; + end; + +begin + Result:=0; + dst:=node^.dst.AsReg; + src:=node^.ParamNode(0)^.AsReg; + src:=RegDown(src); + if (dst=nil) or (src=nil) then Exit; + + if src^.is_const then + begin + pc:=src^.AsConst; + Case node^.OpId of + + Op.OpFConvert: + case src^.dtype of + dtFloat32: + case dst^.dtype of + dtHalf16:_SetConst(dst^.dtype,WORD(THalf16(pc^.AsFloat32))); + else; + end; + else; + end; + + Op.OpConvertFToU: + case src^.dtype of + dtFloat32:_SetConst(dst^.dtype,minz(Trunc(pc^.AsFloat32))); + else; + end; + + Op.OpConvertFToS: + case src^.dtype of + dtFloat32:_SetConst(dst^.dtype,Trunc(pc^.AsFloat32)); + else; + end; + + Op.OpConvertSToF: + case src^.dtype of + dtInt32 :_SetConst(dst^.dtype,double(pc^.AsInt)); + dtUint32:_SetConst(dst^.dtype,double(pc^.AsInt)); + + dtInt64 :_SetConst(dst^.dtype,double(pc^.AsInt64)); + dtUint64:_SetConst(dst^.dtype,double(pc^.AsInt64)); + else; + end; + + Op.OpConvertUToF: + case src^.dtype of + dtInt32 :_SetConst(dst^.dtype,double(pc^.AsUint)); + dtUint32:_SetConst(dst^.dtype,double(pc^.AsUint)); + + dtInt64 :_SetConst(dst^.dtype,double(pc^.AsUint64)); + dtUint64:_SetConst(dst^.dtype,double(pc^.AsUint64)); + else; + end; + + end; + end; +end; + +function TEmitPostOp.OnCompositeExtract1(node:PSpirvOp):Integer; +var + pc:PsrConst; + dst,src:PsrRegNode; + pos:DWORD; +begin + Result:=0; + dst:=node^.dst.AsReg; + src:=node^.ParamNode(0)^.AsReg; + src:=RegDown(src); + 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 (pos=ShrVal); + Delta:=data-ShrVal; + end; + + end; + + 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]); + + if (src[0]=nil) or (src[1]=nil) then Exit; + + if (src[1]^.is_const) then + begin + data:=src[1]^.AsConst^.GetData; + + Result:=(data>=ShrVal); + Delta:=data-ShrVal; + end; + + end; + + else; + end; +end; + +function _GetShrOptReg(pOp:PSpirvOp):PsrRegNode; +var + src:array[0..1] of PsrRegNode; +begin + Result:=nil; + if (pOp=nil) then Exit; + + 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]); + + if (src[0]=nil) or (src[1]=nil) 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; + + 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]); + + if (src[0]=nil) or (src[1]=nil) then Exit; + + Result:=src[0]; + end; + + else; + end; +end; + +function TEmitPostOp._OnShr_ext_add(node,pOp0,pOp1:PSpirvOp;pShrVal:PsrConst):Integer; +var + dst,src:PsrRegNode; + dst_shr:array[0..1] of PsrRegNode; + data:array[0..1] of QWORD; + + procedure _SetReg(src:PsrRegNode); + begin + src^.mark_read; + dst^.pWriter.SetParam(ntReg,src); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + Inc(Result); + end; + + +begin + Result:=0; + data[0]:=0; + data[1]:=0; + + if (not _OpCanBeShrOpt(pOp0,pShrVal^.GetData,data[0])) and + (not _OpCanBeShrOpt(pOp1,pShrVal^.GetData,data[1])) then Exit; + + if (data[0]=0) then + begin + dst_shr[0]:=_GetShrOptReg(pOp0); + end else + begin + dst:=pOp0^.dst.AsReg; + dst_shr[0]:=NewReg(dst^.dtype); + src:=_GetShrOptReg(pOp0); + src^.mark_read; + _emit_OpShl(pOp0,dst_shr[0],src,FetchReg(FConsts.Fetch(dst^.dtype,data[0]))); + end; + + if (data[1]=0) then + begin + dst_shr[1]:=_GetShrOptReg(pOp1); + end else + begin + dst:=pOp1^.dst.AsReg; + dst_shr[1]:=NewReg(dst^.dtype); + src:=_GetShrOptReg(pOp1); + src^.mark_read; + _emit_OpShl(pOp1,dst_shr[1],src,FetchReg(FConsts.Fetch(dst^.dtype,data[1]))); + end; + + dst:=node^.dst.AsReg; + pOp0:=dst^.AsOp; //OpIAdd + src:=NewReg(dst^.dtype); + + dst_shr[0]^.mark_read; + dst_shr[1]^.mark_read; + _emit_OpIAdd(pOp0,src,dst_shr[0],dst_shr[1]); + + _SetReg(src); + + //Writeln(data[0],' ',data[1]); + //writeln; + Result:=1; +end; + +function TEmitPostOp.OnAbsDiff1(node:PSpirvOp):Integer; +var + dst:PsrRegNode; + src:array[0..1] of PsrRegNode; + data:array[0..1] of QWORD; + rmax,rmin:PsrRegNode; + + procedure _SetConst(dtype:TsrDataType;value:QWORD); + begin + dst^.SetConst(FConsts.Fetch(dtype,value)); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + 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]); + + if (dst=nil) or (src[0]=nil) or (src[1]=nil) then Exit; + + if src[0]^.is_const and src[1]^.is_const then + begin + //need a const calc + data[0]:=src[0]^.AsConst^.GetData; + data[1]:=src[1]^.AsConst^.GetData; + + if (data[0]>data[1]) then + _SetConst(dst^.dtype,data[0]-data[1]) + else + _SetConst(dst^.dtype,data[1]-data[0]); + end else + 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); + end; +end; + +function F_WQM_32(D:DWORD):DWORD; +var + i:Byte; +begin + Result:=0; + if (D=0) then Exit; + For i:=0 to 7 do + begin + if (((D shr (i*4)) and 15)<>0) then + begin + Result:=Result or ($F shl (i*4)); + end; + end; +end; + +function TEmitPostOp.OnWQM32__1(node:PSpirvOp):Integer; +var + dst:PsrRegNode; + src:PsrRegNode; + data:QWORD; + + procedure _SetConst(dtype:TsrDataType;value:QWORD); + begin + dst^.SetConst(FConsts.Fetch(dtype,value)); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + Inc(Result); + end; + +begin + Result:=0; + dst:=node^.dst.AsReg; + src:=node^.ParamNode(0)^.AsReg; + src:=RegDown(src); + if (dst=nil) or (src=nil) then Exit; + + if src^.is_const then + begin + //need a const calc + data:=src^.AsConst^.GetData; + data:=F_WQM_32(data); + _SetConst(dst^.dtype,data); + end else + begin + Assert(false,'TODO') + end; +end; + +type + Ppacked_offset=^Tpacked_offset; + Tpacked_offset=bitpacked record + x:bit6; //0..5 (int6) + a1:bit2; + y:bit6; //8..13 (int6) + a2:bit2; + z:bit6; //16..21 (int6) + a3:bit10; + end; + +function int6(b:Byte):Integer; inline; +const + shift=BitSizeOf(Integer)-6; +begin + Result:=SarLongint((Integer(b) shl shift),shift); +end; + +function TEmitPostOp.OnPackOfs1(node:PSpirvOp):Integer; +var + dst:PsrRegNode; + src:PsrRegNode; + data:QWORD; + P:Ppacked_offset; + + rtype:TsrDataType; + count:DWORD; + + ret:PsrConst; + vec:array[0..2] of PsrConst; + +begin + Result:=0; + dst:=node^.dst.AsReg; + 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:=node^.ParamNode(2)^.AsReg; + src:=RegDown(src); + if (src=nil) then Exit; + + if src^.is_const then + begin + //need a const calc + data:=src^.AsConst^.GetData; + P:=@data; + + ret:=nil; + Case count of + 1: + begin + ret:=FConsts.Fetchi(dtInt32,int6(P^.x)); + end; + 2: + begin + vec[0]:=FConsts.Fetchi(dtInt32,int6(P^.x)); + vec[1]:=FConsts.Fetchi(dtInt32,int6(P^.y)); + + ret:=FConsts.Fetch_vec(dtVec2i,2,@vec); + 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)); + + ret:=FConsts.Fetch_vec(dtVec3i,3,@vec); + end; + else + Assert(False); + end; + + dst^.SetConst(ret); + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + Inc(Result); + end else + begin + Assert(false,'TODO'); + end; +end; + +function _IsFma(node:PSpirvOp):Boolean; +var + OpId:DWORD; +begin + Result:=False; + if (node=nil) then Exit; + if (node^.OpId<>Op.OpExtInst) then Exit; + OpId:=0; + node^.ParamNode(1)^.TryGetValue(OpId); + if (OpId<>GlslOp.Fma) then Exit; + Result:=True; +end; + +function _IsOp(node:PSpirvOp;OpId:DWORD):Boolean; +begin + Result:=False; + if (node=nil) then Exit; + Result:=(node^.OpId=OpId); +end; + +function _IsConstFloat_1_0(pReg:PsrRegNode):Boolean; +var + pCon: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); +end; + +function _IsConstFloat_1_5(pReg:PsrRegNode):Boolean; +var + pCon: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); +end; + +function _Fetch_FAbs_Value(node:PSpirvOp):PSpirvOp; +var + OpId:DWORD; + pReg:PsrRegNode; +begin + Result:=nil; + if (node=nil) then Exit; + if (node^.OpId<>Op.OpExtInst) then Exit; + OpId:=0; + node^.ParamNode(1)^.TryGetValue(OpId); + if (OpId<>GlslOp.FAbs) then Exit; + pReg:=node^.ParamNode(2)^.AsReg; + if (pReg=nil) then Exit; + Result:=pReg^.AsOp; +end; + +function _cmp_src_cube_op3(node0,node1:PSpirvOp):Boolean; +var + src0:PsrRegNode; + src1:PsrRegNode; + i:Byte; +begin + Result:=False; + if (node0=nil) or (node1=nil) then Exit; + For i:=0 to 2 do + begin + src0:=RegDown(node0^.ParamNode(i)^.AsReg); + src1:=RegDown(node1^.ParamNode(i)^.AsReg); + if (src0<>src1) then Exit(False); + end; + Result:=True; +end; + +function TEmitPostOp.OnMakeCM1(node:PSpirvOp):Integer; +var + dst:PsrRegNode; + src:array[0..2] of PsrRegNode; + + m_CUBE_SC:PspirvOp; + m_CUBE_TC:PspirvOp; + m_CUBE_ID:PspirvOp; + + m_x_CUBE_MA:PspirvOp; + m_y_CUBE_MA:PspirvOp; + + m_x,m_y,m_f:PspirvOp; + + pReg:PsrRegNode; + pOp:PspirvOp; + + rtype:TsrDataType; + i,count:DWORD; + +begin + Result:=0; + dst:=node^.dst.AsReg; + if (dst=nil) then Exit; + + count:=0; + if not node^.ParamNode(0)^.TryGetValue(count) then Exit; + rtype:=TsrDataType(count); + + if GetVecChild(rtype)<>dtFloat32 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 + + if not _IsFma(m_x) then Exit; + if not _IsFma(m_y) then Exit; + if not _IsOp(m_f,OpCUBEID) then Exit; + + m_CUBE_ID:=m_f; + + //m_x + pReg:=RegDown(m_x^.ParamNode(2)^.AsReg); //param1 + pOp:=pReg^.AsOp; + if not _IsOp(pOp,OpCUBESC) then Exit; + m_CUBE_SC:=pOp; + + pReg:=RegDown(m_x^.ParamNode(3)^.AsReg); //param2 + pOp:=pReg^.AsOp; + 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); + if not _IsOp(pOp,OpCUBEMA) then Exit; + m_x_CUBE_MA:=pOp; + + pReg:=RegDown(m_x^.ParamNode(4)^.AsReg); //param3 + if not _IsConstFloat_1_5(pReg) then Exit; //1.5 + + //m_y + pReg:=RegDown(m_y^.ParamNode(2)^.AsReg); //param1 + pOp:=pReg^.AsOp; + if not _IsOp(pOp,OpCUBETC) then Exit; + m_CUBE_TC:=pOp; + + pReg:=RegDown(m_x^.ParamNode(3)^.AsReg); //param2 + pOp:=pReg^.AsOp; + 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); + if not _IsOp(pOp,OpCUBEMA) then Exit; + m_y_CUBE_MA:=pOp; + + pReg:=RegDown(m_y^.ParamNode(4)^.AsReg); //param3 + if not _IsConstFloat_1_5(pReg) then Exit; //1.5 + + // + + 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; + + For i:=0 to 2 do + begin + src[i]:=RegDown(m_CUBE_SC^.ParamNode(i)^.AsReg); + end; + + MakeVecComp(node,dtVec3f,dst,3,@src); + + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + Result:=1; + + { + For i:=0 to count-1 do + begin + pOp[i]:=src[i]^.AsOp; + + Case pOp[i]^.OpId of + OpCUBEID:Writeln('OpCUBEID'); + OpCUBESC:Writeln('OpCUBESC'); + OpCUBETC:Writeln('OpCUBETC'); + OpCUBEMA:Writeln('OpCUBEMA'); + else + Writeln(Op.GetStr(pOp[i]^.OpId)); + end; + + end; + } + +end; + +// + +function is_all_const(src:PPsrRegNode;count:byte):Boolean; +var + i:Byte; +begin + Result:=True; + For i:=0 to count-1 do + if not src[i]^.is_const then Exit(false); +end; + +function is_all_in_one_comp(src:PPsrRegNode;rtype:TsrDataType;count:byte):Boolean; +var + i:Byte; + pos:DWORD; + pLine:PspirvOp; + pReg,tmp:PsrRegNode; +begin + pReg:=nil; + Result:=True; + For i:=0 to count-1 do + begin + pLine:=src[i]^.AsOp; + if (pLine=nil) then Exit(false); + if (pLine^.OpId<>Op.OpCompositeExtract) then Exit(false); + + pos:=0; + if not pLine^.ParamNode(1)^.TryGetValue(pos) then Exit; + if (pos<>i) then Exit(false); + + tmp:=pLine^.ParamNode(0)^.AsReg; + if (tmp=nil) then Exit(false); + if (tmp^.dtype<>rtype) then Exit(false); + + if (i=0) then + begin + pReg:=tmp; + end else + begin + if (pReg<>tmp) then Exit(false); + end; + + end; +end; + +function try_get_comp_bridge(var src:PsrRegNode):Integer; +var + pLine:PspirvOp; + pos:DWORD; + pReg:PsrRegNode; +begin + Result:=0; + pLine:=src^.AsOp; + 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; + if (pReg=nil) then Exit; + + pLine:=pReg^.AsOp; + if (pLine=nil) then Exit; + if (pLine^.OpId<>Op.OpCompositeConstruct) then Exit; + + pReg:=pLine^.ParamNode(pos)^.AsReg; + if (pReg=nil) then Exit; + src:=pReg; + Result:=1; +end; + +procedure TEmitPostOp.MakeVecConst(rtype:TsrDataType;dst:PsrRegNode;count:Byte;src:PPsrRegNode); +var + nodes:array[0..3] of PsrConst; + h:PsrConst; + i:Byte; +begin + For i:=0 to count-1 do + begin + nodes[i]:=src[i]^.AsConst; + end; + + h:=FConsts.Fetch_vec(rtype,count,@nodes); + dst^.pWriter.SetParam(ntConst,h); +end; + +procedure TEmitPostOp.MakeVecOne(dst:PsrRegNode;src:PPsrRegNode); +var + pLine:PspirvOp; + rsrc:PsrRegNode; +begin + pLine:=src[0]^.AsOp; + rsrc:=pLine^.ParamNode(0)^.AsReg; + rsrc^.mark_read; + dst^.pWriter.SetParam(ntReg,rsrc); +end; + +function TEmitPostOp.MakeVecComp(pLine:PSpirvOp;rtype:TsrDataType;dst:PsrRegNode;count:Byte;src:PPsrRegNode):PSpirvOp; +var + r:Integer; + i:Byte; +begin + Result:=pLine; + + repeat + r:=0; + For i:=0 to count-1 do + begin + r:=r+try_get_comp_bridge(src[i]); + end; + + if is_all_const(src,count) then + begin + MakeVecConst(rtype,dst,count,src); + Exit; // + end; + + if is_all_in_one_comp(src,rtype,count) then + begin + MakeVecOne(dst,src); + Exit; // + end; + + 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); +end; + +function TEmitPostOp.OnMakeVec2(node:PSpirvOp):Integer; +var + pParam:POpParamNode; + dst:PsrRegNode; + src:array[0..3] of PsrRegNode; + rtype:TsrDataType; + i,count:DWORD; +begin + Result:=1; + + dst:=node^.dst.AsReg; + if (dst=nil) then Exit; + + pParam:=node^.pParam.pHead; + + count:=0; + if not pParam^.TryGetValue(count) then Exit; + rtype:=TsrDataType(count); + + pParam:=pParam^.pNext; + count:=0; + if not pParam^.TryGetValue(count) then Exit; + + For i:=0 to count-1 do + begin + pParam:=pParam^.pNext; + src[i]:=pParam^.AsReg; + if (src[i]=nil) then Assert(false,'OnMakeVec2'); + end; + + MakeVecComp(node,rtype,dst,count,@src); + + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); +end; + +function TEmitPostOp.OnReturn_2(node:PSpirvOp):Integer; +begin + Result:=0; + + if is_term_op(node^.pPrev) then + begin + node^.OpId:=OpLinks; //mark remove + Inc(Result); + end; + +end; + +function TEmitPostOp.OnMakeExp2(node:PSpirvOp):Integer; +var + pLine:PspirvOp; + pOpBlock:PsrOpBlock; + pChild:PsrOpBlock; + pOpLabel:array[0..2] of PspirvOp; + exc,tmp:PsrRegNode; + b_adr:TSrcAdr; +begin + Result:=1; + + pOpBlock:=node^.pParent; + + exc:=node^.ParamNode(0)^.AsReg; + if (exc=nil) then Exit; + + tmp:=RegDown(exc); + if tmp^.is_const then + begin + node^.OpId:=OpLinks; + //node^.OpId:=Op.OpNop; + //NodeOpClear(node); //clear + + Case tmp^.AsConst^.AsBool of + True : //is always store + begin + pLine:=node^.pNext; + if (pLine<>nil) then + begin + pChild:=pLine^.dst.AsBlock; + if (pChild<>nil) then + begin + Dec(pChild^.FLevel); //up + end; + end; + end; + False: //is always kill + begin + pOpBlock^.dummy.OpId:=Op.OpKill; //add kill + //clear all + node:=pOpBlock^.pHead; + 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 + end; + node:=node^.pNext; + end; + end; + end; + Exit; + end else + begin + node^.OpId:=OpLinks; //mark remove + + exc^.mark_read; + b_adr:=pOpBlock^.Block.b_adr; + + pLine:=node^.pNext; + if (pLine=nil) then //kill or nop + begin + + pOpLabel[0]:=NewLabelOp; //current + pOpLabel[1]:=NewLabelOp; //end + + pOpLabel[0]^.Adr:=b_adr; + pOpLabel[1]^.Adr:=b_adr; + + pOpBlock^.SetLabels(pOpLabel[0],pOpLabel[1],nil); + pOpBlock^.Block.bType:=btCond; + pOpBlock^.SetCond(nil,true); + + pLine:=node; + pLine:=emit_OpCondMerge(pLine,pOpLabel[1]); + pLine:=emit_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; + pLine:=InsertBlockOp(pLine,pChild); + + //emit_OpBranch not need from kill + pLine:=emit_OpBranch(pLine,pOpLabel[1]); + pLine:=AddSpirvOp(pLine,pOpLabel[1]); + + end else + begin //kill or store + Assert(pLine^.OpId=OpBlock); + + pOpLabel[0]:=NewLabelOp; //current + pOpLabel[1]:=NewLabelOp; //else + pOpLabel[2]:=NewLabelOp; //end + + pOpLabel[0]^.Adr:=b_adr; + pOpLabel[1]^.Adr:=b_adr; + pOpLabel[2]^.Adr:=b_adr; + + pOpBlock^.SetLabels(pOpLabel[0],pOpLabel[2],pOpLabel[1]); + pOpBlock^.Block.bType:=btCond; + pOpBlock^.SetCond(nil,true); + + pLine:=node; + pLine:=emit_OpCondMerge(pLine,pOpLabel[2]); + pLine:=emit_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; + pLine:=InsertBlockOp(pLine,pChild); + + //emit_OpBranch not need from kill + pLine:=AddSpirvOp(pLine,pOpLabel[1]); + + //OpStore child + + pLine:=pOpBlock^.pTail; + pLine:=emit_OpBranch(pLine,pOpLabel[2]); + pLine:=AddSpirvOp(pLine,pOpLabel[2]); //end + + end; + + end; + +end; + +function TEmitPostOp.OnIAddExt2(node:PSpirvOp):Integer; +var + dst,car:PsrRegNode; + src:array[0..1] of PsrRegNode; +begin + Result:=1; + dst:=node^.dst.AsReg; + car:=node^.ParamNode(0)^.AsReg; + if (dst=nil) or (car=nil) then Exit; + + src[0]:=node^.ParamNode(1)^.AsReg; + src[1]:=node^.ParamNode(2)^.AsReg; + if (src[0]=nil) or (src[1]=nil) then Exit; + + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + + if (car^.read_count>1) 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]); + end else + begin + src[0]^.mark_read; + src[1]^.mark_read; + _emit_OpIAdd(node,dst,src[0],src[1]); + end; +end; + +function TEmitPostOp.OnISubExt2(node:PSpirvOp):Integer; +var + dst,bor:PsrRegNode; + src:array[0..1] of PsrRegNode; +begin + Result:=1; + dst:=node^.dst.AsReg; + bor:=node^.ParamNode(0)^.AsReg; + if (dst=nil) or (bor=nil) then Exit; + + src[0]:=node^.ParamNode(1)^.AsReg; + src[1]:=node^.ParamNode(2)^.AsReg; + if (src[0]=nil) or (src[1]=nil) then Exit; + + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + + if (bor^.read_count>1) 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]); + end else + begin + src[0]^.mark_read; + src[1]^.mark_read; + _emit_OpISub(node,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; +var + dst:PsrRegNode; + vec:PsrRegNode; + src:array[0..2] of PsrRegNode; + pFunc:PSpirvFunc; +begin + Result:=1; + + dst:=node^.dst.pData; + src[0]:=node^.ParamNode(0)^.pData; + src[1]:=node^.ParamNode(1)^.pData; + src[2]:=node^.ParamNode(2)^.pData; + + node^.OpId:=OpLinks; //mark remove + node^.dst:=Default(TOpParamSingle); + + //build vec + vec:=NewReg(dtVec3f); + node:=MakeVecComp(node,dtVec3f,vec,3,@src); + + pFunc:=NewMED3F; + + 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 + +end; +} + +// + +end. + diff --git a/spirv/emit_print.pas b/spirv/emit_print.pas new file mode 100644 index 0000000..79e27b0 --- /dev/null +++ b/spirv/emit_print.pas @@ -0,0 +1,772 @@ +unit emit_print; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + spirv, + srNodes, + srTypes, + srConst, + srReg, + srLayout, + srVariable, + srOp, + srOpUtils, + srCap, + srRefId, + Half16, + SprvEmit; + +type + TSprvEmit_print=object(TSprvEmit) + procedure Print; + procedure PrintCaps; + procedure PrintOpList(node:PspirvOp); + 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 + +procedure TSprvEmit_print.Print; +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); +var + s:Single; + i:Int64; + u:QWORD; +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 + begin + n:=P^.GetName; + if (n<>'') then + begin + Write('%',n); + end else + begin + Write('%v',P^.ID.ID); + end; + 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'); + end; +end; + +procedure TSprvEmit_print.PrintCaps; +var + node:PSpirvCap; +begin + node:=FSpirvCaps.First; + While (node<>nil) do + begin + Writeln(Op.GetStr(Op.OpCapability),' ',Capability.GetStr(node^.ID)); + node:=FSpirvCaps.Next(node); + end; +end; + +procedure TSprvEmit_print.PrintOpList(node:PspirvOp); +begin + While (node<>nil) do + begin + PrintOp(node,false); + node:=node^.pNext; + 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; +end; + +procedure TSprvEmit_print.PrintTypes; +var + node:PsrType; + pConst:PsrConst; + i:dword; + ie:Boolean; +begin + node:=FSpirvTypes.FList.pHead; + 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 + begin + For i:=0 to node^.key.count-1 do + begin + Write(' '); + PrintTypeId(node^.GetCompItem(i)); + end; + end; + + Writeln; + + node:=node^.pNext; + 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; +begin + node:=FConsts.FList.pHead; + While (node<>nil) do + begin + + //if not node^.is_first then + //begin + if (node^.key.dtype=dtUnknow) 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; + end; +end; + +procedure TSprvEmit_print.PrintVariable; +var + node:PsrVariable; +begin + node:=FVariables.pHead; + While (node<>nil) do + begin + if (node^.pType<>nil) then + begin + PrintVar(node); + Write(' = ',Op.GetStr(Op.OpVariable),' '); + PrintTypeId(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; + end; +end; + +procedure TSprvEmit_print.PrintFunc; +var + pFunc:PSpirvFunc; +begin + pFunc:=FSpirvFuncs.FList.pHead; + While (pFunc<>nil) do + begin + Writeln; + PrintOpBlock(@pFunc^.FTop); + pFunc:=pFunc^.pNext; + end; +end; + +procedure TSprvEmit_print.PrintOp(node:PSpirvOp;print_offset:Boolean); +var + Param:POpParamNode; + Info:Op.TOpInfo; +begin + if (node=nil) then Exit; + + Info:=Op.GetInfo(node^.OpId); + + if Info.result then //dst + begin + Assert(node^.dst.ntype<>ntUnknow,'PrintOp$1'); + Assert(node^.dst.pData<>nil,'PrintOp$2'); + PrintOpParamSingle(node^.dst); + Write(' = '); + Write(Op.GetStr(node^.OpId)); + end else + begin //no dst + Write(Op.GetStr(node^.OpId)); + if (node^.dst.ntype<>ntUnknow) then + begin + Assert(node^.dst.pData<>nil,'PrintOp$3'); + Write(' '); + PrintOpParamSingle(node^.dst); + end; + end; + + if Info.rstype then //dst type + begin + Assert(node^.dst_type<>nil,'PrintOp$4'); + Write(' '); + PrintTypeId(node^.dst_type); + end; + + Param:=node^.pParam.pHead; + While (Param<>nil) do + begin + Write(' '); + PrintOpParamNode(Param); + Param:=Param^.pNext; + end; + + if (node^.OpId=Op.OpLabel) then + begin + print_offset:=true; + end; + + Case print_offset of + True :Writeln(' ;0x',HexStr(Node^.Adr.Offdw*4,4)); + False:Writeln; + 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 new file mode 100644 index 0000000..d13df3b --- /dev/null +++ b/spirv/emit_smrd.pas @@ -0,0 +1,155 @@ +unit emit_SMRD; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + srTypes, + srReg, + srLayout, + SprvEmit, + emit_op; + +type + TEmit_SMRD=object(TEmitOp) + 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); +var + dst:PsrRegSlot; + + ofs_r,idx_r:PsrRegNode; + dtype:TsrDataType; + + ext:TsrChainExt; + + i:Byte; + +begin + + if (FSPI.SMRD.IMM<>0) then + begin + For i:=0 to count-1 do + begin + dst:=FRegsStory.get_sdst7(FSPI.SMRD.SDST+i); + Assert(dst<>nil); + MakeChain(dst,grp,(FSPI.SMRD.OFFSET+i)*4,4,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))); + + For i:=0 to count-1 do + begin + dst:=FRegsStory.get_sdst7(FSPI.SMRD.SDST+i); + Assert(dst<>nil); + + if (i=0) then + 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))); + end; + + ofs_r^.mark_read; + + ext:=Default(TsrChainExt); + ext.pIndex:=ofs_r; + ext.stride:=4; + MakeChain(dst,grp,0,4,@ext); + end; + end; + +end; + +procedure TEmit_SMRD.emit_LOAD_DWORDX(count:Byte); +var + src:array[0..3] of PsrRegSlot; + grp:PsrDataLayout; +begin + if not FRegsStory.get_sbase(FSPI.SMRD.SBASE,2,@src) then Assert(false); + grp:=GroupingSharp(@src,rtBufPtr2); + _emit_LOAD_DWORDX(grp,count); +end; + +procedure TEmit_SMRD.emit_BUFFER_LOAD_DWORDX(count:Byte); +var + src:array[0..3] of PsrRegSlot; + grp:PsrDataLayout; +begin + if not FRegsStory.get_sbase(FSPI.SMRD.SBASE,4,@src) then Assert(false); + grp:=GroupingSharp(@src,rtVSharp4); + _emit_LOAD_DWORDX(grp,count); +end; + +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_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; + + else + Assert(false,'SMRD?'+IntToStr(FSPI.SMRD.OP)); + end; + +end; + +end. + diff --git a/spirv/emit_sop1.pas b/spirv/emit_sop1.pas new file mode 100644 index 0000000..decd8c5 --- /dev/null +++ b/spirv/emit_sop1.pas @@ -0,0 +1,245 @@ +unit emit_SOP1; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + srLabel, + srTypes, + srConst, + srReg, + srLayout, + SprvEmit, + emit_op; + +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; + end; + +implementation + +Function TEmit_SOP1._GetFuncPtr(src:PPsrRegSlot):Pointer; +var + chain:TsrChains; + pLayout:PsrDataLayout; + +begin + Result:=nil; + + chain:=Default(TsrChains); + chain[0]:=GetChainRegNode(src[0]^.current); + chain[1]:=GetChainRegNode(src[1]^.current); + + pLayout:=FDataLayouts.Grouping(chain,rtFunPtr2); + Result:=pLayout^.pData; + + Assert(Result<>nil); +end; + +procedure TEmit_SOP1._emit_S_MOV_B32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.get_sdst7(FSPI.SOP1.SDST); + src:=fetch_ssrc9(FSPI.SOP1.SSRC,dtUnknow); + _MakeCopy(dst,src); +end; + +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); + + 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]); +end; + +procedure TEmit_SOP1._emit_S_SWAPPC_B64; +Var + dst:array[0..1] of PsrRegSlot; + src:array[0..1] of PsrRegSlot; + + oldptr,newptr:Pointer; + +begin + if not FRegsStory.get_sdst7_pair(FSPI.SOP1.SDST,@dst) then Assert(false); + + Assert(not is_const_ssrc9(FSPI.SOP1.SSRC)); + + if not FRegsStory.get_ssrc9_pair(FSPI.SOP1.SSRC,@src) then Assert(false); + + newptr:=_GetFuncPtr(@src); + Assert(newptr<>nil); + + oldptr:=FCursor.Adr.get_pc; + + SetConst(dst[0],dtUint32,{%H-}QWORD(oldptr)); + SetConst(dst[1],dtUint32,{%H-}QWORD(oldptr) shr 32); + + SetPtr(newptr,btSetpc); +end; + +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; + + newptr:Pointer; + +begin + Assert(not is_const_ssrc9(FSPI.SOP1.SSRC)); + if not FRegsStory.get_ssrc9_pair(FSPI.SOP1.SSRC,@src) 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; + +end; + +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 + + dst[0]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+0); + dst[1]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+1); + + 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; + + 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]); + + //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) + + //SCC = (sdst != 0) SCC = ((exc[0] != 0) or ((exc[1] != 0)) +end; + +procedure TEmit_SOP1._emit_S_WQM_B64; +Var + dst:array[0..1] of PsrRegSlot; + src:array[0..1] of PsrRegNode; + +begin + //S_WQM_B64 EXEC_LO, EXEC_LO //sdst.du = wholeQuadMode(ssrc.du); SCC = (sdst.du != 0) + //dst[q*4+3:q*4].du = (ssrc[4*q+3:4*q].du != 0) ? 0xF : 0 + //dst[3:0].du = (ssrc[3:0].du != 0) ? 0xF : 0 + //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); + + Assert(dst[0]<>nil); + Assert(dst[1]<>nil); + + 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]); +end; + +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; + + else + Assert(false,'SOP1?'+IntToStr(FSPI.SOP1.OP)); + end; + +end; + + +end. + + + + + diff --git a/spirv/emit_sop2.pas b/spirv/emit_sop2.pas new file mode 100644 index 0000000..58afd44 --- /dev/null +++ b/spirv/emit_sop2.pas @@ -0,0 +1,345 @@ +unit emit_SOP2; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + srTypes, + srConst, + srReg, + SprvEmit, + emit_op; + + +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_BFE_U32; + end; + +implementation + +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; + + src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtInt32); + src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtInt32); + + emit_OpIAddExt(dst,car,src[0],src[1]); +end; + +procedure TEmit_SOP2._emit_S_MUL_I32; +Var + dst:PsrRegSlot; + src:array[0..1] of PsrRegNode; +begin + dst:=FRegsStory.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]); +end; + +procedure TEmit_SOP2._emit_S_LSHL_B32; //SCC = (sdst.u != 0) +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_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); +end; + +procedure TEmit_SOP2._emit_S_LSHR_B32; //SCC = (sdst.u != 0) +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; + src:array[0..1] of PsrRegNode; +begin + dst:=FRegsStory.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]); + + tmp:=@FRegsStory.SCC; + MakeCopy(tmp,dst^.current); + tmp^.current^.dtype:=dtBool; +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 fetch_ssrc9_pair(@src0,FSPI.SOP2.SSRC0,dtUInt32) then Assert(False); + if not fetch_ssrc9_pair(@src1,FSPI.SOP2.SSRC1,dtUInt32) then Assert(False); + + 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_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) +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 fetch_ssrc9_pair(@src0,FSPI.SOP2.SSRC0,dtUInt32) then Assert(False); + if not fetch_ssrc9_pair(@src1,FSPI.SOP2.SSRC1,dtUInt32) then Assert(False); + + emit_OpBitwiseOr(dst[0],src0[0],src1[0]); + emit_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_OpLogicalOr(@FRegsStory.SCC,src2[0],src2[1]); //implict cast (int != 0) +end; + +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 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); + + emit_OpBitwiseOr(dst[0],src0[0],src1[0]); + emit_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) +end; + +procedure TEmit_SOP2._emit_S_CSELECT_B32; //sdst = SCC ? ssrc0 : ssrc1 +Var + dst:PsrRegSlot; + src:array[0..2] of PsrRegNode; +begin + dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST); + + src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUnknow); + src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUnknow); + src[2]:=MakeRead(@FRegsStory.SCC,dtBool); + + emit_OpSelect(dst,src[0],src[1],src[2]); +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) +Var + dst,tmp: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; + + src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUint32); + src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUint32); + + num_31:=FetchReg(FConsts.Fetch(dtUInt32,31)); + + emit_OpBitwiseAnd(tmp,src[1],num_31); + offset:=MakeRead(tmp,dtUInt32); + + 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; +end; + +procedure TEmit_SOP2._emit_SOP2; +begin + + Case FSPI.SOP2.OP of + + S_ADD_I32: + begin + _emit_S_ADD_I32; + end; + + S_MUL_I32: //& 0xFFFFFFFF + begin + _emit_S_MUL_I32; + end; + + S_LSHL_B32: //SCC = (sdst.u != 0) + begin + _emit_S_LSHL_B32; + end; + + S_LSHR_B32: + begin + _emit_S_LSHR_B32; + end; + + S_AND_B32: + begin + _emit_S_AND_B32; + end; + + S_AND_B64: + begin + _emit_S_AND_B64; + end; + + S_ANDN2_B64: + begin + _emit_S_ANDN2_B64; + end; + + 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_BFE_U32: + begin + _emit_S_BFE_U32; + end; + + else + Assert(False,'SOP2?'+IntToStr(FSPI.SOP2.OP)); + end; + +end; + +end. + diff --git a/spirv/emit_sopc.pas b/spirv/emit_sopc.pas new file mode 100644 index 0000000..03d1cc4 --- /dev/null +++ b/spirv/emit_sopc.pas @@ -0,0 +1,66 @@ +unit emit_SOPC; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + spirv, + ps4_pssl, + srTypes, + srReg, + SprvEmit, + emit_op; + +type + TEmit_SOPC=object(TEmitOp) + 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); +Var + dst:PsrRegSlot; + src:array[0..1] of PsrRegNode; +begin + dst:=@FRegsStory.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]); +end; + +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_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:; + //S_BITCMP0_B64:; + //S_BITCMP1_B64:; + //S_SETVSKIP :; + else + Assert(false,'SOPC?'+IntToStr(FSPI.SOPC.OP)); + end; + +end; + +end. + diff --git a/spirv/emit_sopp.pas b/spirv/emit_sopp.pas new file mode 100644 index 0000000..8d8ed99 --- /dev/null +++ b/spirv/emit_sopp.pas @@ -0,0 +1,300 @@ +unit emit_SOPP; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + srTypes, + srParser, + srLabel, + srCFG, + srReg, + srOp, + srOpUtils, + spirv, + SprvEmit, + emit_op; + +type + TEmit_SOPP=object(TEmitOp) + procedure _emit_SOPP; + procedure _emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean); + procedure _emit_S_BRANCH; + function IsBegLoop(Adr:TSrcAdr):Boolean; + function IsEndLoop(Adr:TSrcAdr):Boolean; + procedure emit_cond_block(pSlot:PsrRegSlot;n:Boolean;adr:TSrcAdr); + procedure UpBuildVol(last:PsrOpBlock); + procedure emit_loop(adr:TSrcAdr); + end; + +implementation + +uses + srVolatile; + +procedure TEmit_SOPP.emit_cond_block(pSlot:PsrRegSlot;n:Boolean;adr:TSrcAdr); +var + src:PsrRegNode; + pOpBlock:PsrOpBlock; + pOpChild:PsrOpBlock; + pOpLabel:array[0..1] of PspirvOp; + pLBlock:PsrCFGBlock; + Info:array[0..1] of TsrBlockInfo; +begin + src:=MakeRead(pSlot,dtBool); //get before OpBranchConditional + + pOpLabel[0]:=NewLabelOp; + pOpLabel[1]:=NewLabelOp; + + pLBlock:=FCursor.pCode^.FTop.DownBlock(adr); + Assert(pLBlock<>@FCursor.pCode^.FTop,'not found'); + + Info[0]:=Default(TsrBlockInfo); + Info[1]:=Default(TsrBlockInfo); + + Case pLBlock^.bType of + btAdr: //set new adr + begin + Info[0].b_adr:=FCursor.Adr; + Info[0].e_adr:=FCursor.Adr; + Info[0].bType:=btCond; + // + Info[1].b_adr:=pLBlock^.pBLabel^.Adr; + Info[1].e_adr:=pLBlock^.pELabel^.Adr; + Info[1].bType:=btAdr; + end; + btCond: //normal cond + begin + Info[0].b_adr:=pLBlock^.pBLabel^.Adr; + Info[0].e_adr:=pLBlock^.pELabel^.Adr; + Info[0].bType:=btCond; + // + Info[1].b_adr:=Info[0].b_adr; + Info[1].e_adr:=Info[0].e_adr; + Info[1].bType:=btOther; + end; + else + Assert(false,'emit_cond_block'); + end; + + pOpLabel[0]^.Adr:=Info[0].b_adr; + pOpLabel[1]^.Adr:=Info[0].e_adr; + + pOpBlock:=NewBlockOp(FRegsStory.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]); + + Case n of + True :emit_OpBranchCond(line,pOpLabel[1],pOpLabel[0],src); + False:emit_OpBranchCond(line,pOpLabel[0],pOpLabel[1],src); + end; + + AddSpirvOp(line,pOpLabel[0]); + + //down group + pOpChild:=AllocBlockOp; + pOpChild^.SetInfo(Info[1]); + PushBlockOp(line,pOpChild,nil); + + if (pLBlock^.bType=btAdr) then //set new adr + begin + SetPtr(adr.get_pc,btAdr); + end; +end; + +procedure TEmit_SOPP.UpBuildVol(last:PsrOpBlock); +var + node:PsrOpBlock; +begin + node:=FMain^.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); + else; + end; + + if (node=last) then Break; + node:=node^.pParent; + end; +end; + +procedure TEmit_SOPP.emit_loop(adr:TSrcAdr); +var + node,pOpBlock:PsrOpBlock; + pOpLabel:array[0..1] of PspirvOp; + FVolMark:TsrVolMark; + bnew:Boolean; +begin + + node:=FMain^.pBlock; + pOpBlock:=node^.FindUpLoop; + Assert(pOpBlock<>nil,'not found'); + + pOpLabel[0]:=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 + 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; + FVolMark:=vmBreak; + end else + begin + Assert(false,'emit_loop'); + end; + + Assert(pOpLabel[0]<>nil); + + bnew:=true; + if FCursor.pBlock^.IsEndOf(FCursor.Adr) then //is last + begin + Assert(node^.Block.e_adr.get_pc=FCursor.Adr.get_pc); + Case node^.Block.bType of + btSetpc:; + else + begin + bnew:=false; + end; + end; + end; + + UpBuildVol(pOpBlock); + node^.Regs.FVolMark:=FVolMark; //mark end of + + emit_OpBranch(line,pOpLabel[0]); + if bnew then + begin + pOpLabel[1]:=NewLabelOp; + AddSpirvOp(line,pOpLabel[1]); + end; +end; + +function TEmit_SOPP.IsBegLoop(Adr:TSrcAdr):Boolean; +var + node:PsrCFGBlock; +begin + Result:=false; + node:=FCursor.pBlock^.FindUpLoop; + if (node<>nil) then + begin + Result:=node^.pBLabel^.Adr.get_pc=Adr.get_pc; + end; +end; + +function TEmit_SOPP.IsEndLoop(Adr:TSrcAdr):Boolean; +var + node:PsrCFGBlock; +begin + Result:=false; + node:=FCursor.pBlock^.FindUpLoop; + if (node<>nil) then + begin + Result:=node^.pELabel^.Adr.get_pc=Adr.get_pc; + end; +end; + +procedure TEmit_SOPP._emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean); +var + c_adr,b_adr:TSrcAdr; + pLabel:PsrLabel; + +begin + c_adr:=FCursor.Adr; + b_adr:=c_adr; + b_adr.Offdw:=get_branch_offset(FSPI); + + pLabel:=FindLabel(b_adr); + Assert(pLabel<>nil); + Assert(not pLabel^.IsType(ltUnknow)); + + if pLabel^.IsType(ltBegAdr) then //adr + begin + emit_cond_block(pSlot,n,b_adr); + end else + if (SmallInt(FSPI.SOPP.SIMM)<0) then //up + begin //continue? + if not IsBegLoop(b_adr) then Assert(false,'Unknow'); + Assert(false,'TODO'); + end else + begin //down + if FCursor.pBlock^.IsBigOf(b_adr) then + begin //break? + if not IsEndLoop(b_adr) then Assert(false,'Unknow'); + Assert(false,'TODO'); + end else + begin //cond + emit_cond_block(pSlot,n,c_adr); + end; + end; + +end; + +procedure TEmit_SOPP._emit_S_BRANCH; +var + c_adr,b_adr:TSrcAdr; + +begin + c_adr:=FCursor.Adr; + b_adr:=c_adr; + b_adr.Offdw:=get_branch_offset(FSPI); + + + if (SmallInt(FSPI.SOPP.SIMM)<0) then //up + begin //continue? + if not IsBegLoop(b_adr) then Assert(false,'Unknow'); + emit_loop(b_adr); + end else //down + begin //break? + if not IsEndLoop(b_adr) then Assert(false,'Unknow'); + emit_loop(b_adr); + end; + +end; + +procedure TEmit_SOPP._emit_SOPP; +begin + Case FSPI.SOPP.OP of + S_NOP, + S_WAITCNT:; + + S_ENDPGM: + begin + if not is_term_op(line) then + begin + AddSpirvOp(Op.OpReturn); + end; + FMain^.pBlock^.Regs.FVolMark:=vmEnd; //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_BRANCH :_emit_S_BRANCH; + + else + Assert(false,'SOPP?'+IntToStr(FSPI.SOPP.OP)); + end; +end; + +end. + diff --git a/spirv/emit_vbuf_chain.pas b/spirv/emit_vbuf_chain.pas new file mode 100644 index 0000000..875616c --- /dev/null +++ b/spirv/emit_vbuf_chain.pas @@ -0,0 +1,417 @@ +unit emit_vbuf_chain; + +{$mode ObjFPC}{$H+} + +interface + +uses + sysutils, + ps4_shader, + ps4_pssl, + srTypes, + srConst, + srReg, + srLayout, + SprvEmit, + emit_op, + srVBufInfo; + +type + TBuf_adr=packed record + stride,align,fsize,csize:PtrInt; + soffset,ioffset,voffset:PtrInt; + sof,ofs,idx:PsrRegNode; + end; + + TvcType=(vcInvalid,vcChainVector,vcChainElement,vcUniformVector,vcUniformElement); + + TvarChain=record + vType:TvcType; + 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; + 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; + function get_idx_fmt(var adr:TBuf_adr):PsrRegNode; + function get_chain(info:TBuf_info):TvarChain; + end; + +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; +begin + if is_const_soffset(FSPI.MUBUF.SOFFSET) then + begin + adr.soffset:=get_soffset_const_int(FSPI.MUBUF.SOFFSET); + end else + begin + ofs:=FRegsStory.get_ssrc8(FSPI.MUBUF.SOFFSET); + if (ofs<>nil) then + begin + adr.sof:=ofs^.current; + if (adr.sof<>nil) then + begin + if (adr.sof^.is_const) then + begin + adr.soffset:=adr.sof^.AsConst^.AsInt; + adr.sof:=nil; + end else + begin + Assert(false,'FSPI.MUBUF.SOFFSET'); + end; + end; + end; + end; + + ofs:=nil; + if (FSPI.MUBUF.IDXEN=1) then + 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); + end; + end else + if (FSPI.MUBUF.OFFEN=1) then + begin + ofs:=FRegsStory.get_vsrc8(FSPI.MUBUF.VADDR+0); + end; + + if (ofs<>nil) then + begin + adr.ofs:=ofs^.current; + if (adr.ofs<>nil) then + begin + if (adr.ofs^.is_const) then + begin + adr.voffset:=adr.ofs^.AsConst^.AsInt; + adr.ofs:=nil; + end else + begin + adr.ofs:=MakeRead(ofs,dtInt32); + end; + end; + end; +end; + +function TEmit_vbuf_chain.get_sum_ofs(var adr:TBuf_adr):PsrRegNode; +var + foffset:PtrInt; + + sum_d,ofs_d,idx_m:PsrRegNode; + +begin + foffset:=adr.soffset+adr.ioffset+adr.voffset; + + if (foffset mod adr.align=0) and //const offset is align + ((adr.idx=nil) or //no index or + (adr.stride mod adr.align=0)) then //stride is align + begin + + //(foffset is Align) + //(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 + + 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); + end; + + end else + begin + + //result=(foffset+ofs+idx*stride)/Align in elem + + adr.ofs^.mark_unread; + sum_d:=OpAddTo(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); + end; + + sum_d:=OpDivTo(sum_d,adr.align); // sum/Align + end; + + Result:=sum_d; +end; + +function TEmit_vbuf_chain.get_idx_elm(var adr:TBuf_adr):PsrRegNode; +var + foffset:PtrInt; + + sum_d,idx_m:PsrRegNode; + +begin + //result=(foffset/Align+idx*(stride/Align)) in elem + + foffset:=adr.soffset+adr.ioffset+adr.voffset; + foffset:=foffset div adr.align; + + if (adr.idx=nil) then + begin + sum_d:=FetchReg(FConsts.Fetchi(dtUint32,foffset)); + sum_d^.mark_unread; + 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); + end; + + Result:=sum_d; +end; + +function TEmit_vbuf_chain.get_idx_fmt(var adr:TBuf_adr):PsrRegNode; +var + foffset:PtrInt; + + sum_d,idx_m:PsrRegNode; + +begin + //result=(foffset/size+idx*(stride/size)) in format + + foffset:=adr.soffset+adr.ioffset+adr.voffset; + foffset:=foffset div adr.fsize; + + if (adr.idx=nil) then + begin + sum_d:=FetchReg(FConsts.Fetchi(dtUint32,foffset)); + sum_d^.mark_unread; + 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); + end; + + Result:=sum_d; +end; + +function Min(a,b:PtrInt):PtrInt; inline; +begin + if (a=0,'WTF'); + + if (adr.ofs=nil) and (adr.idx=nil) then //simple + begin + + Result.vType :=vcChainVector; + Result.data[0]:=info.grp^.Fetch(foffset,adr.csize,nil); + + Exit; + end; + + //result=Align(foffset+ofs+idx*stride) in byte + + if (adr.ofs<>nil) then + begin + sum_d:=get_sum_ofs(adr); + + //minTexelBufferOffsetAlignment + if FUseTexelBuffer then + if (info.IsComp) and + (adr.stride div adr.align=0) then + begin + //is uniform buffer per element + + img:=info.GetImageInfoElement; + + Result.vType :=vcUniformElement; + Result.data[0]:=FetchImage(info.grp,img.dtype,img.tinfo); + Result.data[1]:=sum_d; + + Exit; + end; + + sum_d^.mark_read; + ext:=Default(TsrChainExt); + ext.pIndex:=sum_d; + ext.stride:=adr.align; + + 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 (info.IsComp) and + (adr.stride mod adr.fsize=0) and + (foffset mod adr.fsize=0) then + begin + //is uniform buffer per format + + sum_d:=get_idx_fmt(adr); + + img:=info.GetImageInfo; + + Result.vType :=vcUniformVector; + Result.data[0]:=FetchImage(info.grp,img.dtype,img.tinfo); + Result.data[1]:=sum_d; + + Exit; + end; + + //minTexelBufferOffsetAlignment + if FUseTexelBuffer then + if (info.IsComp) and + (adr.stride div adr.align=0) then + begin + //is uniform buffer per element + + sum_d:=get_idx_elm(adr); + + img:=info.GetImageInfoElement; + + Result.vType :=vcUniformElement; + Result.data[0]:=FetchImage(info.grp,img.dtype,img.tinfo); + Result.data[1]:=sum_d; + + Exit; + end; + + //adr.idx^.mark_read; + ext:=Default(TsrChainExt); + ext.pIndex:=adr.idx; + ext.stride:=adr.stride; + + Result.vType :=vcChainVector; + Result.data[0]:=info.grp^.Fetch(foffset,adr.csize,@ext); + + Exit; + end; + +end; + +end. + diff --git a/spirv/emit_vbuf_load.pas b/spirv/emit_vbuf_load.pas new file mode 100644 index 0000000..5c59915 --- /dev/null +++ b/spirv/emit_vbuf_load.pas @@ -0,0 +1,394 @@ +unit emit_vbuf_load; + +{$mode ObjFPC}{$H+} + +interface + +uses + sysutils, + spirv, + ps4_pssl, + srTypes, + srConst, + srReg, + srLayout, + SprvEmit, + emit_op, + srVBufInfo, + emit_vbuf_chain; + +type + Tload_cache=record + info:TBuf_info; + v:TvarChain; + dst:PsrRegSlot; + elem_orig:TsrDataType; + elem_resl:TsrDataType; + elem_count:ptruint; + rsl:PsrRegNode; + elm:array[0..3] of PsrRegNode; + end; + + TEmit_vbuf_load=object(TEmitOp) + 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); + procedure buf_load_cv(info:TBuf_info;v:TvarChain); + end; + +implementation + +procedure TEmit_vbuf_load.buf_load(info:TBuf_info); +var + v:TvarChain; +begin + v:=TEmit_vbuf_chain(Self).get_chain(info); + + if (v.vType=vcUniformVector) then + begin + //reset dst sel + info.dsel:=dst_sel_identity; + end; + + buf_load_cv(info,v); +end; + +function TEmit_vbuf_load.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; +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 + begin + idx:=orig^.key.ext.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); + end else + begin + new:=lc.info.grp^.Fetch(orig^.key.offset,csize,nil); + end; + orig:=new; + end; + + FetchStore(orig,rsl); +end; + +procedure TEmit_vbuf_store._make_store_ce(var lc:Tstore_cache); +var + orig,elm:PsrChain; + sum_d:PsrRegNode; + ext:TsrChainExt; + i:Byte; +begin + orig:=lc.v.data[0]; + sum_d:=orig^.key.ext.pIndex; + + For i:=0 to lc.elem_count-1 do + if (lc.elm[i]<>nil) then + begin + + if (i=0) then + begin + elm:=orig; + end else + begin + sum_d:=TEmit_vbuf_chain(Self).OpAddTo(sum_d,i); + + sum_d^.mark_read; + ext:=Default(TsrChainExt); + ext.pIndex:=sum_d; + ext.stride:=orig^.key.ext.stride; + + elm:=lc.info.grp^.Fetch(0,orig^.key.size,@ext); + end; + + Assert(lc.elem_resl=lc.elem_orig,'TODO CONVERT'); + + FetchStore(elm,lc.elm[i]); + + end; + +end; + +procedure TEmit_vbuf_store._make_store_uv(var lc:Tstore_cache); +var + rsl,idx:PsrRegNode; + i:Byte; +begin + + For i:=0 to lc.elem_count-1 do //fill + if (lc.elm[i]=nil) then + begin + Case lc.info.dsel[i] of + 1:lc.elm[i]:=_fetch_one(lc); + else + lc.elm[i]:=_fetch_zero(lc); + end; + end; + + Case lc.elem_count of + 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; + end; + end; + + idx:=lc.v.data[1]; + idx^.mark_read; + rsl^.mark_read; + emit_OpImageWrite(line,lc.v.data[0],idx,rsl); +end; + +procedure TEmit_vbuf_store._make_store_ue(var lc:Tstore_cache); +var + sum_d,idx,rsl:PsrRegNode; + i:Byte; +begin + idx:=lc.v.data[1]; + + For i:=0 to lc.elem_count-1 do + if (lc.elm[i]<>nil) then + begin + rsl:=lc.elm[i]; + + if (i=0) then + begin + sum_d:=idx; + end else + begin + sum_d:=TEmit_vbuf_chain(Self).OpAddTo(idx,i); + end; + + sum_d^.mark_read; + rsl^.mark_read; + emit_OpImageWrite(line,lc.v.data[0],sum_d,rsl); + + end; +end; + +procedure TEmit_vbuf_store.buf_store_cv(info:TBuf_info;v:TvarChain); +var + lc:Tstore_cache; + + i:Byte; +begin + + Case v.vType of + vcInvalid:Exit; + else; + end; + + if info.IsExtFormat then Assert(false,'TODO'); + + lc:=Default(Tstore_cache); + lc.info :=info; + lc.v :=v; + lc.elem_resl :=info.GetResultType; + lc.elem_orig :=info.GetElemType; + lc.elem_count:=info.GetElemCount; + + For i:=0 to lc.elem_count-1 do + begin + lc.elm[i]:=nil; + Case lc.info.dsel[i] of + 4..7: + begin //RGBA + lc.elm[i]:=_fetch_id(lc,lc.info.dsel[i]-4); + end; + else; + end; + end; + + While (lc.elem_count<>0) do //trim count + begin + i:=lc.elem_count-1; + if (lc.elm[i]<>nil) then Break; + Dec(lc.elem_count); + end; + + 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) + else; + end; + +end; + +end. + diff --git a/spirv/emit_vintrp.pas b/spirv/emit_vintrp.pas new file mode 100644 index 0000000..a57f3b7 --- /dev/null +++ b/spirv/emit_vintrp.pas @@ -0,0 +1,110 @@ +unit emit_VINTRP; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + srTypes, + srInput, + srReg, + spirv, + SprvEmit, + emit_op; + +type + TEmit_VINTRP=object(TEmitOp) + procedure _emit_VINTRP; + end; + +implementation + +procedure TEmit_VINTRP._emit_VINTRP; +var + inp_M0:PsrInput; + + src:PsrRegSlot; + dst:PsrRegSlot; + + inp_SRC:PsrInput; + + rsl:PsrRegNode; + +begin + Assert(FExecutionModel=ExecutionModel.Fragment); //only pixel shader + + dst:=FRegsStory.get_vdst8(FSPI.VINTRP.VDST); + + inp_M0:=GetInputRegNode(FRegsStory.M0.current); + + Assert(inp_M0<>nil); + Assert(inp_M0^.key.itype=itPsState); + + Case FSPI.VINTRP.OP of + V_INTERP_P1_F32: + begin + src:=FRegsStory.get_vsrc8(FSPI.VINTRP.VSRC); + + inp_SRC:=GetInputRegNode(src^.current); + + Assert(inp_SRC<>nil); + + Case inp_SRC^.key.itype of + itPerspSample, + itPerspCenter, //barycentrics with perspective interpolation + itPerspCentroid, + itLinearSample, + itLinearCenter, + itLinearCentroid:; + else + Assert(false); + end; + + Assert(inp_SRC^.key.typeid=0); //I + + rsl:=AddFragLayout(inp_SRC^.key.itype,dtVec4f,FSPI.VINTRP.ATTR); + rsl^.mark_read; + + dst^.New(line,dtFloat32); + emit_OpCompExtract(line,dst^.current,rsl,FSPI.VINTRP.ATTRCHAN); + + end; + V_INTERP_P2_F32: + begin + src:=FRegsStory.get_vsrc8(FSPI.VINTRP.VSRC); + + inp_SRC:=GetInputRegNode(src^.current); + + Assert(inp_SRC<>nil); + + Case inp_SRC^.key.itype of + itPerspSample, + itPerspCenter, //barycentrics with perspective interpolation + itPerspCentroid, + itLinearSample, + itLinearCenter, + itLinearCentroid:; + else + Assert(false); + end; + + Assert(inp_SRC^.key.typeid=1); //J + + rsl:=AddFragLayout(inp_SRC^.key.itype,dtVec4f,FSPI.VINTRP.ATTR); + rsl^.mark_read; + + dst^.New(line,dtFloat32); + emit_OpCompExtract(line,dst^.current,rsl,FSPI.VINTRP.ATTRCHAN); + + end; + + else + Assert(False,'VINTRP?'+IntToStr(FSPI.VINTRP.OP)); + end; + +end; + +end. + diff --git a/spirv/emit_vop1.pas b/spirv/emit_vop1.pas new file mode 100644 index 0000000..86d0bde --- /dev/null +++ b/spirv/emit_vop1.pas @@ -0,0 +1,273 @@ +unit emit_VOP1; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + srTypes, + srReg, + spirv, + SprvEmit, + emit_op; + +type + TEmit_VOP1=object(TEmitOp) + procedure _emit_VOP1; + procedure _emit_V_MOV_B32; + procedure _emit_V_CVT_F32_I32; + procedure _emit_V_CVT_U32_F32; + procedure _emit_V_CVT_I32_F32; + procedure _emit_V_CVT_F32_U32; + procedure _emit_V_CVT_OFF_F32_I4; + procedure _emit_V_SQRT_F32; + procedure _emit_V_RSQ_F32; + procedure _emit_V_FLOOR_F32; + procedure _emit_V_FRACT_F32; + procedure _emit_V_EXP_F32; + procedure _emit_V_RCP_F32; + procedure _emit_V_SIN_F32; + end; + +implementation + +procedure TEmit_VOP1._emit_V_MOV_B32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUnknow); + _MakeCopy(dst,src); +end; + +procedure TEmit_VOP1._emit_V_CVT_F32_I32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtInt32); + emit_Op1(Op.OpConvertSToF,dtFloat32,dst,src); +end; + +procedure TEmit_VOP1._emit_V_CVT_I32_F32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32); + emit_Op1(Op.OpConvertFToS,dtInt32,dst,src); +end; + +procedure TEmit_VOP1._emit_V_CVT_U32_F32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32); + emit_Op1(Op.OpConvertFToU,dtUInt32,dst,src); +end; + +procedure TEmit_VOP1._emit_V_CVT_F32_U32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUInt32); + emit_Op1(Op.OpConvertUToF,dtFloat32,dst,src); +end; + +//V_CVT_OFF_F32_I4 +//([0..3]-8)/16 +procedure TEmit_VOP1._emit_V_CVT_OFF_F32_I4; +Var + dst,tmp:PsrRegSlot; + src:PsrRegNode; + num_8:PsrRegNode; + num_15:PsrRegNode; + num_16:PsrRegNode; + subi,subf:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUInt32); + + tmp:=@FRegsStory.FUnattach; + num_15:=FetchReg(FConsts.Fetch(dtUInt32,15)); + + emit_OpBitwiseAnd(tmp,src,num_15); + src:=MakeRead(tmp,dtUInt32); + + num_8:=FetchReg(FConsts.Fetch(dtInt32,8)); + subi:=dst^.New(line,dtInt32); + + _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); +end; + +procedure TEmit_VOP1._emit_V_SQRT_F32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32); + emit_OpSqrt(dst,src); +end; + +procedure TEmit_VOP1._emit_V_RSQ_F32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32); + emit_OpInverseSqrt(dst,src); +end; + +procedure TEmit_VOP1._emit_V_FLOOR_F32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32); + emit_OpFloor(dst,src); +end; + +procedure TEmit_VOP1._emit_V_FRACT_F32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32); + emit_OpFract(dst,src); +end; + +procedure TEmit_VOP1._emit_V_EXP_F32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32); + emit_OpExp2(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); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32); + + one:=FetchReg(FConsts.Fetchf(dtFloat32,1)); + + emit_OpFDiv(dst,one,src); +end; + +procedure TEmit_VOP1._emit_V_SIN_F32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST); + src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32); + emit_OpSin(dst,src); +end; + +procedure TEmit_VOP1._emit_VOP1; +begin + + Case FSPI.VOP1.OP of + + V_MOV_B32: + begin + _emit_V_MOV_B32; + end; + + V_CVT_F32_I32: + begin + _emit_V_CVT_F32_I32; + end; + + V_CVT_I32_F32: + begin + _emit_V_CVT_I32_F32; + end; + + V_CVT_U32_F32: + begin + _emit_V_CVT_U32_F32; + end; + + V_CVT_F32_U32: + begin + _emit_V_CVT_F32_U32; + end; + + V_CVT_OFF_F32_I4: + begin + _emit_V_CVT_OFF_F32_I4; + end; + + V_SQRT_F32: + begin + _emit_V_SQRT_F32; + end; + + V_RSQ_F32: + begin + _emit_V_RSQ_F32; + end; + + V_FLOOR_F32: + begin + _emit_V_FLOOR_F32; + end; + + V_FRACT_F32: + begin + _emit_V_FRACT_F32; + end; + + V_EXP_F32: + begin + _emit_V_EXP_F32; + end; + + V_RCP_F32: + begin + _emit_V_RCP_F32; + end; + + V_SIN_F32: + begin + _emit_V_SIN_F32; + end; + + else + Assert(false,'VOP1?'+IntToStr(FSPI.VOP1.OP)); + end; + +end; + +end. + diff --git a/spirv/emit_vop2.pas b/spirv/emit_vop2.pas new file mode 100644 index 0000000..2c17d60 --- /dev/null +++ b/spirv/emit_vop2.pas @@ -0,0 +1,511 @@ +unit emit_VOP2; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + srTypes, + srConst, + srReg, + SprvEmit, + emit_op; + +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_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_F32; + procedure _emit_V_MAX_F32; + end; + +implementation + +procedure TEmit_VOP2._emit_V_CNDMASK_B32; +Var + dst:PsrRegSlot; + src:array[0..2] of PsrRegNode; +begin + dst:=FRegsStory.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); + + emit_OpSelect(dst,src[0],src[1],src[2]); +end; + +procedure TEmit_VOP2._emit_V_AND_B32; +Var + dst:PsrRegSlot; + src:array[0..1] of PsrRegNode; +begin + dst:=FRegsStory.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]); +end; + +procedure TEmit_VOP2._emit_V_OR_B32; +Var + dst:PsrRegSlot; + src:array[0..1] of PsrRegNode; +begin + dst:=FRegsStory.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]); +end; + +procedure TEmit_VOP2._emit_V_LSHL_B32; +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,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]); +end; + +procedure TEmit_VOP2._emit_V_LSHLREV_B32; +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,dtUint32); + + src[2]:=FetchReg(FConsts.Fetch(dtUInt32,31)); + emit_OpBitwiseAnd(tmp,src[0],src[2]); + src[0]:=MakeRead(tmp,dtUInt32); + + emit_OpShl(dst,src[1],src[0]); +end; + +procedure TEmit_VOP2._emit_V_LSHR_B32; +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,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]); +end; + +procedure TEmit_VOP2._emit_V_LSHRREV_B32; +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,dtUint32); + + 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]); +end; + +procedure TEmit_VOP2._emit_V_ASHR_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 ,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); + + emit_OpShrA(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,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; +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_OpFAdd(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 +Var + dst:PsrRegSlot; + src:array[0..2] 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); + src[2]:=MakeRead(dst,dtFloat32); + + emit_OpFmaF32(dst,src[0],src[1],src[2]); +end; + +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); + + src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32); + src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32); + src[2]:=FetchReg(FConsts.Fetch(dtFloat32,FSPI.INLINE32)); + + emit_OpFmaF32(dst,src[0],src[1],src[2]); +end; + +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); + + src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32); + src[1]:=FetchReg(FConsts.Fetch(dtFloat32,FSPI.INLINE32)); + src[2]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32); + + emit_OpFmaF32(dst,src[0],src[1],src[2]); +end; + +procedure TEmit_VOP2._emit_V_MIN_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_OpFMin(dst,src[0],src[1]); +end; + +procedure TEmit_VOP2._emit_V_MAX_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_OpFMax(dst,src[0],src[1]); +end; + +procedure TEmit_VOP2._emit_VOP2; +begin + + Case FSPI.VOP2.OP of + + V_CNDMASK_B32: + begin + _emit_V_CNDMASK_B32; + end; + + V_AND_B32: + begin + _emit_V_AND_B32; + end; + + V_OR_B32: + begin + _emit_V_OR_B32; + end; + + V_LSHL_B32: + begin + _emit_V_LSHL_B32; + end; + + V_LSHLREV_B32: + begin + _emit_V_LSHLREV_B32; + end; + + V_LSHR_B32: + begin + _emit_V_LSHR_B32; + end; + + V_LSHRREV_B32: + begin + _emit_V_LSHRREV_B32 + end; + + V_ASHR_I32: + begin + _emit_V_ASHR_I32; + end; + + V_ASHRREV_I32: + begin + _emit_V_ASHRREV_I32 + end; + + 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_SUB_I32: + begin + _emit_V_SUB_I32; + end; + + 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_F32: + begin + _emit_V_MIN_F32; + end; + + V_MAX_F32: + begin + _emit_V_MAX_F32; + end; + + else + Assert(false,'VOP2?'+IntToStr(FSPI.VOP2.OP)); + end; + +end; + +end. + diff --git a/spirv/emit_vop3.pas b/spirv/emit_vop3.pas new file mode 100644 index 0000000..7a2629e --- /dev/null +++ b/spirv/emit_vop3.pas @@ -0,0 +1,995 @@ +unit emit_VOP3; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + spirv, + srTypes, + srReg, + srOpUtils, + SprvEmit, + emit_op; + +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); + + 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_F32; + procedure _emit_V_MAX_F32; + procedure _emit_V_MUL_LO_I32; + procedure _emit_V_MUL_F32; + procedure _emit_V_MUL_I32_I24; + procedure _emit_V_MAC_F32; + + procedure _emit_V_BFE_U32; + 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_SQRT_F32; + procedure _emit_V_RCP_F32; + end; + +implementation + +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); + + Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); + Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP'); + + 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_OpCmpV(OpId,dst[0],src[0],src[1]); + + SetConst(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 + end; +end; + +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); + + 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 + + if x then + begin + MakeCopy(@FRegsStory.EXEC[0],dst[0]^.current); + SetConst(@FRegsStory.EXEC[1],dtUnknow,0); //set zero + end; +end; + +procedure TEmit_VOP3._emit_src_neg_bit(src:PPsrRegNode;count:Byte); +var + i:Byte; + dst:PsrRegNode; +begin + if (FSPI.VOP3a.NEG=0) then Exit; + + For i:=0 to count-1 do + if Byte(FSPI.VOP3a.NEG).TestBit(i) then + begin + dst:=NewReg(dtFloat32); + dst^.mark_read; + _emit_OpFNegate(line,dst,src[i]); + src[i]:=dst; + end; +end; + +procedure TEmit_VOP3._emit_src_abs(src:PPsrRegNode); +var + dst:PsrRegNode; +begin + dst:=NewReg(dtFloat32); + dst^.mark_read; + _emit_OpFAbs(line,dst,src^); + src^:=dst; +end; + +procedure TEmit_VOP3._emit_src_abs_bit(src:PPsrRegNode;count:Byte); +var + i:Byte; +begin + if (FSPI.VOP3a.ABS=0) then Exit; + + For i:=0 to count-1 do + if Byte(FSPI.VOP3a.ABS).TestBit(i) then + begin + _emit_src_abs(@src[i]); + end; +end; + +procedure TEmit_VOP3._emit_dst_omod_f(dst:PsrRegSlot); +var + src,tmp:PsrRegNode; +begin + + 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); + end; + 2: // *4 + begin + src:=dst^.current; + src^.mark_read; + tmp:=FetchReg(FConsts.Fetchf(dtFloat32,4)); + emit_OpFMul(dst,src,tmp); + end; + 3: // /2 + begin + src:=dst^.current; + src^.mark_read; + tmp:=FetchReg(FConsts.Fetchf(dtFloat32,2)); + emit_OpFDiv(dst,src,tmp); + end; + end; + +end; + +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)); + + emit_OpFClamp(dst,src,min,max); +end; + +procedure TEmit_VOP3._emit_V_CNDMASK_B32; +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.CLAMP=0,'FSPI.VOP3a.CLAMP'); + + src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtUnknow); + 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_OpSelect(dst,src[0],src[1],src[2]); +end; + +procedure TEmit_VOP3._emit_V_ADD_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_OpFAdd(dst,src[0],src[1]); + + _emit_dst_omod_f(dst); + _emit_dst_clamp_f(dst); +end; + +procedure TEmit_VOP3._emit_V_SUB_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); + + Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); + Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP'); + + 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_ConvFloatToHalf(dst,src[0],src[1]); +end; + +procedure TEmit_VOP3._emit_V_MIN_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_OpFMin(dst,src[0],src[1]); + + _emit_dst_omod_f(dst); + _emit_dst_clamp_f(dst); +end; + +procedure TEmit_VOP3._emit_V_MAX_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_OpFMax(dst,src[0],src[1]); + + _emit_dst_omod_f(dst); + _emit_dst_clamp_f(dst); +end; + +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); + + 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,dtInt32); + src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtInt32); + + emit_OpIMul(dst,src[0],src[1]); +end; + +procedure TEmit_VOP3._emit_V_MUL_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_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:PsrRegSlot; + src:array[0..1] 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,dtInt32); + src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtInt32); + + //24bit mask TODO + emit_OpIMul(dst,src[0],src[1]); +end; + +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); + + 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_OpFmaF32(dst,src[0],src[1],src[2]); + + _emit_dst_omod_f(dst); + _emit_dst_clamp_f(dst); +end; + +procedure TEmit_VOP3._emit_V_BFE_U32; +Var + dst,tmp:PsrRegSlot; + src:array[0..2] of PsrRegNode; + num_31:PsrRegNode; + offset,count:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + tmp:=@FRegsStory.FUnattach; + + 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,dtUint32); + 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); +end; + +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); + + 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_OpFmaF32(dst,src[0],src[1],src[2]); + + _emit_dst_omod_f(dst); + _emit_dst_clamp_f(dst); +end; + +procedure TEmit_VOP3._emit_V_MAD_I32_I24; +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,dtInt32); + src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtInt32); + src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtInt32); + + emit_OpFmaI32(dst,src[0],src[1],src[2]); +end; + +procedure TEmit_VOP3._emit_V_MAD_U32_U24; +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,dtUInt32); + src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtUInt32); + src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtUInt32); + + emit_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 +Var + dst:PsrRegSlot; + src:array[0..2] of PsrRegNode; + rdif,rvac:PsrRegNode; + //msk: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,dtUInt32); + 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]); + + //msk:=FetchReg(FConsts.Fetch(dtUInt32,$FFFF)); mask need? + //emit_OpBitwiseAnd(tmp,src[2],msk); + //rvac:=tmp^.current; + rvac:=src[2]; + + rdif^.mark_read; + rvac^.mark_read; + emit_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; +Var + dst:PsrRegSlot; + src:array[0..2] 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_OpFmaF32(dst,src[0],src[1],src[2]); + + _emit_dst_omod_f(dst); + _emit_dst_clamp_f(dst); +end; + +{ +procedure TEmit_VOP3._emit_V_CUBEMA_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:=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_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]); +end; + +procedure TEmit_VOP3._emit_V_MOV_B32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + + Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD'); + Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP'); + + if (Byte(FSPI.VOP3a.ABS).TestBit(0)) or + (Byte(FSPI.VOP3a.NEG).TestBit(0)) then + begin + src:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); + + _emit_src_abs_bit(@src,1); + _emit_src_neg_bit(@src,1); + + _MakeCopy(dst,src); + end else + begin + src:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtUnknow); + + _MakeCopy(dst,src); + end; + +end; + +procedure TEmit_VOP3._emit_V_SQRT_F32; +Var + dst:PsrRegSlot; + src:PsrRegNode; +begin + dst:=FRegsStory.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_OpSqrt(dst,src); + + _emit_dst_omod_f(dst); + _emit_dst_clamp_f(dst); +end; + +procedure TEmit_VOP3._emit_V_RCP_F32; +Var + dst:PsrRegSlot; + src:PsrRegNode; + one:PsrRegNode; +begin + dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST); + + src:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32); + + _emit_src_abs_bit(@src,1); + _emit_src_neg_bit(@src,1); + + one:=FetchReg(FConsts.Fetchf(dtFloat32,1)); + + emit_OpFDiv(dst,one,src); + + _emit_dst_omod_f(dst); + _emit_dst_clamp_f(dst); +end; + +procedure TEmit_VOP3._emit_VOP3c; +begin + Case FSPI.VOP3a.OP of + + V_CMP_F_F32, + V_CMP_F_F64, + V_CMP_F_I32, + V_CMP_F_I64, + V_CMP_F_U32, + V_CMP_F_U64, + V_CMPS_F_F32, + V_CMPS_F_F64:_emit_V_CMP_C(false,false); + + V_CMP_T_F32, + V_CMP_T_F64, + V_CMP_T_I32, + V_CMP_T_I64, + V_CMP_T_U32, + V_CMP_T_U64, + V_CMPS_T_F32, + V_CMPS_T_F64:_emit_V_CMP_C(true,false); + + V_CMPX_F_F32, + V_CMPX_F_F64, + V_CMPX_F_I32, + V_CMPX_F_I64, + V_CMPX_F_U32, + V_CMPX_F_U64, + V_CMPSX_F_F32, + V_CMPSX_F_F64:_emit_V_CMP_C(false,true); + + V_CMPX_T_F32, + V_CMPX_T_F64, + V_CMPX_T_I32, + V_CMPX_T_I64, + V_CMPX_T_U32, + V_CMPX_T_U64, + V_CMPSX_T_F32, + 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_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_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_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_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)); + end; + +end; + +procedure TEmit_VOP3._emit_VOP3b; +begin + Assert(false,'VOP3b?'+IntToStr(FSPI.VOP3b.OP)); +end; + +procedure TEmit_VOP3._emit_VOP3a; +begin + + Case FSPI.VOP3a.OP of + + 256+V_CNDMASK_B32: + begin + _emit_V_CNDMASK_B32; + end; + + 256+V_ADD_F32: + begin + _emit_V_ADD_F32; + end; + + 256+V_SUB_F32: + begin + _emit_V_SUB_F32; + end; + + 256+V_CVT_PKRTZ_F16_F32: + begin + _emit_V_CVT_PKRTZ_F16_F32; + end; + + 256+V_MIN_F32: + begin + _emit_V_MIN_F32; + end; + + 256+V_MAX_F32: + begin + _emit_V_MAX_F32; + end; + + 256+V_MUL_F32: + begin + _emit_V_MUL_F32; + end; + + 256+V_MUL_I32_I24: + begin + _emit_V_MUL_I32_I24; + end; + + 256+V_MAC_F32: + begin + _emit_V_MAC_F32; + end; + + V_MUL_LO_I32: + begin + _emit_V_MUL_LO_I32; + end; + + V_BFE_U32: + begin + _emit_V_BFE_U32; + end; + + 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); + + 384+V_MOV_B32: + begin + _emit_V_MOV_B32; + end; + + 384+V_SQRT_F32: + begin + _emit_V_SQRT_F32; + end; + + 384+V_RCP_F32: + begin + _emit_V_RCP_F32; + end; + + else + Assert(false,'VOP3a?'+IntToStr(FSPI.VOP3a.OP)); + end; + +end; + +end. + diff --git a/spirv/emit_vopc.pas b/spirv/emit_vopc.pas new file mode 100644 index 0000000..dc6c8b5 --- /dev/null +++ b/spirv/emit_vopc.pas @@ -0,0 +1,205 @@ +unit emit_VOPC; + +{$mode objfpc}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + srTypes, + srReg, + spirv, + SprvEmit, + emit_op; + +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); + end; + +implementation + +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]; + + 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]); + + SetConst(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 + end; +end; + +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]; + + SetConst(dst[0],dtBool,QWORD(r)); + SetConst(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 + end; +end; + +procedure TEmit_VOPC._emit_VOPC; +begin + + Case FSPI.VOPC.OP of + + V_CMP_F_F32, + V_CMP_F_F64, + V_CMP_F_I32, + V_CMP_F_I64, + V_CMP_F_U32, + V_CMP_F_U64, + V_CMPS_F_F32, + V_CMPS_F_F64:_emit_V_CMP_C(false,false); + + V_CMP_T_F32, + V_CMP_T_F64, + V_CMP_T_I32, + V_CMP_T_I64, + V_CMP_T_U32, + V_CMP_T_U64, + V_CMPS_T_F32, + V_CMPS_T_F64:_emit_V_CMP_C(true,false); + + V_CMPX_F_F32, + V_CMPX_F_F64, + V_CMPX_F_I32, + V_CMPX_F_I64, + V_CMPX_F_U32, + V_CMPX_F_U64, + V_CMPSX_F_F32, + V_CMPSX_F_F64:_emit_V_CMP_C(false,true); + + V_CMPX_T_F32, + V_CMPX_T_F64, + V_CMPX_T_I32, + V_CMPX_T_I64, + V_CMPX_T_U32, + V_CMPX_T_U64, + V_CMPSX_T_F32, + 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_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_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_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_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?'); + end; + +end; + +end. + diff --git a/spirv/pssl-spirv.lpi b/spirv/pssl-spirv.lpi new file mode 100644 index 0000000..62cd8ff --- /dev/null +++ b/spirv/pssl-spirv.lpi @@ -0,0 +1,285 @@ + + + + + + + + + + + + + + + <UseAppBundle Value="False"/> + <ResourceType Value="res"/> + </General> + <BuildModes Count="1"> + <Item1 Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + </RunParams> + <Units Count="49"> + <Unit0> + <Filename Value="pssl-spirv.lpr"/> + <IsPartOfProject Value="True"/> + </Unit0> + <Unit1> + <Filename Value="Half16.pas"/> + <IsPartOfProject Value="True"/> + </Unit1> + <Unit2> + <Filename Value="srNodes.pas"/> + <IsPartOfProject Value="True"/> + </Unit2> + <Unit3> + <Filename Value="srTypes.pas"/> + <IsPartOfProject Value="True"/> + </Unit3> + <Unit4> + <Filename Value="srConst.pas"/> + <IsPartOfProject Value="True"/> + </Unit4> + <Unit5> + <Filename Value="srRefId.pas"/> + <IsPartOfProject Value="True"/> + </Unit5> + <Unit6> + <Filename Value="srIO.pas"/> + <IsPartOfProject Value="True"/> + </Unit6> + <Unit7> + <Filename Value="srOp.pas"/> + <IsPartOfProject Value="True"/> + </Unit7> + <Unit8> + <Filename Value="srReg.pas"/> + <IsPartOfProject Value="True"/> + </Unit8> + <Unit9> + <Filename Value="SprvEmit.pas"/> + <IsPartOfProject Value="True"/> + </Unit9> + <Unit10> + <Filename Value="srAllocator.pas"/> + <IsPartOfProject Value="True"/> + </Unit10> + <Unit11> + <Filename Value="srArray.pas"/> + <IsPartOfProject Value="True"/> + </Unit11> + <Unit12> + <Filename Value="emit_sop1.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_SOP1"/> + </Unit12> + <Unit13> + <Filename Value="emit_vop1.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_VOP1"/> + </Unit13> + <Unit14> + <Filename Value="emit_vopc.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_VOPC"/> + </Unit14> + <Unit15> + <Filename Value="emit_vop3b.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_VOP3b"/> + </Unit15> + <Unit16> + <Filename Value="emit_mubuf.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_MUBUF"/> + </Unit16> + <Unit17> + <Filename Value="emit_exp.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_EXP"/> + </Unit17> + <Unit18> + <Filename Value="emit_vintrp.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_VINTRP"/> + </Unit18> + <Unit19> + <Filename Value="emit_smrd.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_SMRD"/> + </Unit19> + <Unit20> + <Filename Value="emit_sop2.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_SOP2"/> + </Unit20> + <Unit21> + <Filename Value="emit_vop2.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_VOP2"/> + </Unit21> + <Unit22> + <Filename Value="emit_post_process.pas"/> + <IsPartOfProject Value="True"/> + </Unit22> + <Unit23> + <Filename Value="emit_print.pas"/> + <IsPartOfProject Value="True"/> + </Unit23> + <Unit24> + <Filename Value="emit_mimg.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_MIMG"/> + </Unit24> + <Unit25> + <Filename Value="emit_op.pas"/> + <IsPartOfProject Value="True"/> + </Unit25> + <Unit26> + <Filename Value="emit_sopp.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_SOPP"/> + </Unit26> + <Unit27> + <Filename Value="emit_sopc.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_SOPC"/> + </Unit27> + <Unit28> + <Filename Value="srparsernode.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="srParserNode"/> + </Unit28> + <Unit29> + <Filename Value="srLabel.pas"/> + <IsPartOfProject Value="True"/> + </Unit29> + <Unit30> + <Filename Value="emit_post_op.pas"/> + <IsPartOfProject Value="True"/> + </Unit30> + <Unit31> + <Filename Value="emit_bitcast.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="srBitcast"/> + </Unit31> + <Unit32> + <Filename Value="srVolatile.pas"/> + <IsPartOfProject Value="True"/> + </Unit32> + <Unit33> + <Filename Value="srLayout.pas"/> + <IsPartOfProject Value="True"/> + </Unit33> + <Unit34> + <Filename Value="srBuffer.pas"/> + <IsPartOfProject Value="True"/> + </Unit34> + <Unit35> + <Filename Value="gnSplayTree.pas"/> + <IsPartOfProject Value="True"/> + </Unit35> + <Unit36> + <Filename Value="srVariable.pas"/> + <IsPartOfProject Value="True"/> + </Unit36> + <Unit37> + <Filename Value="srInput.pas"/> + <IsPartOfProject Value="True"/> + </Unit37> + <Unit38> + <Filename Value="srOutput.pas"/> + <IsPartOfProject Value="True"/> + </Unit38> + <Unit39> + <Filename Value="srUniformConstant.pas"/> + <IsPartOfProject Value="True"/> + </Unit39> + <Unit40> + <Filename Value="srOpUtils.pas"/> + <IsPartOfProject Value="True"/> + </Unit40> + <Unit41> + <Filename Value="srCFG.pas"/> + <IsPartOfProject Value="True"/> + </Unit41> + <Unit42> + <Filename Value="srCap.pas"/> + <IsPartOfProject Value="True"/> + </Unit42> + <Unit43> + <Filename Value="srVertLayout.pas"/> + <IsPartOfProject Value="True"/> + </Unit43> + <Unit44> + <Filename Value="srFragLayout.pas"/> + <IsPartOfProject Value="True"/> + </Unit44> + <Unit45> + <Filename Value="srDecorate.pas"/> + <IsPartOfProject Value="True"/> + </Unit45> + <Unit46> + <Filename Value="emit_mbuf.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="emit_VBUF"/> + </Unit46> + <Unit47> + <Filename Value="srbufinfo.pas"/> + <IsPartOfProject Value="True"/> + <UnitName Value="srBufInfo"/> + </Unit47> + <Unit48> + <Filename Value="emit_bin.pas"/> + <IsPartOfProject Value="True"/> + </Unit48> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="pssl-spirv"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <OtherUnitFiles Value="..;..\rtl;..\chip;..\vulkan"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Parsing> + <SyntaxOptions> + <IncludeAssertionCode Value="True"/> + </SyntaxOptions> + </Parsing> + <CodeGeneration> + <SmartLinkUnit Value="True"/> + <RelocatableUnit Value="True"/> + </CodeGeneration> + <Linking> + <Debugging> + <DebugInfoType Value="dsDwarf2Set"/> + <UseLineInfoUnit Value="False"/> + </Debugging> + <LinkSmart Value="True"/> + </Linking> + </CompilerOptions> + <Debugging> + <Exceptions Count="3"> + <Item1> + <Name Value="EAbort"/> + </Item1> + <Item2> + <Name Value="ECodetoolError"/> + </Item2> + <Item3> + <Name Value="EFOpenError"/> + </Item3> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/spirv/pssl-spirv.lpr b/spirv/pssl-spirv.lpr new file mode 100644 index 0000000..5b9e68b --- /dev/null +++ b/spirv/pssl-spirv.lpr @@ -0,0 +1,784 @@ +{$mode objfpc}{$H+} + +Uses + classes, + Sysutils, + si_ci_vi_merged_offset, + si_ci_vi_merged_registers, + ps4_pssl, + ps4_shader, + //spirv, + srBuffer, + SprvEmit, + + emit_post, + emit_alloc, + emit_print, + emit_bin; + +var + cfg:record + FName:RawByteString; + FSave:RawByteString; + FPrintInfo:Boolean; + FPrintAsm:Boolean; + FPrintSpv:Boolean; + FUseVertexInput:Boolean; + FUseTexelBuffer:Boolean; + + BufferCfg:TsrBufferCfg; + end; + +type + TDUMP_WORD=packed record + 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); +var + F:TFileStream; +begin + F:=TFileStream.Create(FName,fmCreate); + SaveToStream_SprvEmit(F,SprvEmit); + F.Free; +end; + +type + TSPI_USER_DATA=array[0..15] of DWORD; + +var + GPU_REGS:packed record + + PS:packed record + Addr:Pointer; + + INPUT_CNTL:array[0..31] of TSPI_PS_INPUT_CNTL_0; + + RSRC1:TSPI_SHADER_PGM_RSRC1_PS; + RSRC2:TSPI_SHADER_PGM_RSRC2_PS; + RSRC3:TSPI_SHADER_PGM_RSRC3_PS; + + Z_FORMAT :TSPI_SHADER_Z_FORMAT; + COL_FORMAT:TSPI_SHADER_COL_FORMAT; + + INPUT_ENA :TSPI_PS_INPUT_ENA; + INPUT_ADDR:TSPI_PS_INPUT_ADDR; + IN_CONTROL:TSPI_PS_IN_CONTROL; + BARYC_CNTL:TSPI_BARYC_CNTL; + + SHADER_CONTROL:TDB_SHADER_CONTROL; + SHADER_MASK:TCB_SHADER_MASK; + + USER_DATA:TSPI_USER_DATA; + end; + + VS:packed record + Addr:Pointer; + + RSRC1:TSPI_SHADER_PGM_RSRC1_VS; + RSRC2:TSPI_SHADER_PGM_RSRC2_VS; + RSRC3:TSPI_SHADER_PGM_RSRC3_VS; + + OUT_CONFIG:TSPI_VS_OUT_CONFIG; + POS_FORMAT:TSPI_SHADER_POS_FORMAT; + OUT_CNTL :TPA_CL_VS_OUT_CNTL; + + USER_DATA:TSPI_USER_DATA; + end; + + CS:packed record + Addr:Pointer; + + RSRC1:TCOMPUTE_PGM_RSRC1; + RSRC2:TCOMPUTE_PGM_RSRC2; + + STATIC_THREAD_MGMT_SE0:TCOMPUTE_STATIC_THREAD_MGMT_SE0; + STATIC_THREAD_MGMT_SE1:TCOMPUTE_STATIC_THREAD_MGMT_SE1; + RESOURCE_LIMITS:TCOMPUTE_RESOURCE_LIMITS; + + NUM_THREAD_X:TCOMPUTE_NUM_THREAD_X; + NUM_THREAD_Y:TCOMPUTE_NUM_THREAD_Y; + NUM_THREAD_Z:TCOMPUTE_NUM_THREAD_Z; + + USER_DATA:TSPI_USER_DATA; + end; + + VGT_NUM_INSTANCES:TVGT_NUM_INSTANCES; + end; + + Blocks:TFPList; + +procedure ClearBlocks; +var + i:Integer; +begin + if (Blocks=nil) then + begin + Blocks:=TFPList.Create; + Exit; + end; + if (Blocks.Count<>0) then + For i:=0 to Blocks.Count-1 do + begin + FreeMem(Blocks.Items[i]); + end; + Blocks.Clear; +end; + +procedure load_dump(const fname:RawByteString); +var + M:TMemoryStream; + W:TDUMP_WORD; + V:DWORD; + addr:Pointer; + size,i:DWORD; +begin + ClearBlocks; + FillChar(GPU_REGS,SizeOf(GPU_REGS),0); + M:=TMemoryStream.Create; + M.LoadFromFile(fname); + M.Position:=0; + V:=0; + W:=Default(TDUMP_WORD); + repeat + if M.Read(W,SizeOf(W))<>SizeOf(W) then Break; + if (W.COUNT=0) then //simple + begin + if M.Read(V,SizeOf(V))<>SizeOf(V) then Break; + + Case W.REG of + mmCOMPUTE_PGM_RSRC1 :DWORD(GPU_REGS.CS.RSRC1 ):=V; + mmCOMPUTE_PGM_RSRC2 :DWORD(GPU_REGS.CS.RSRC2 ):=V; + mmCOMPUTE_NUM_THREAD_X:DWORD(GPU_REGS.CS.NUM_THREAD_X):=V; + mmCOMPUTE_NUM_THREAD_Y:DWORD(GPU_REGS.CS.NUM_THREAD_Y):=V; + mmCOMPUTE_NUM_THREAD_Z:DWORD(GPU_REGS.CS.NUM_THREAD_Z):=V; + // + mmCOMPUTE_USER_DATA_0..mmCOMPUTE_USER_DATA_15: + begin + i:=W.REG-mmCOMPUTE_USER_DATA_0; + GPU_REGS.CS.USER_DATA[i]:=V; + end; + // + mmCOMPUTE_STATIC_THREAD_MGMT_SE0:DWORD(GPU_REGS.CS.STATIC_THREAD_MGMT_SE0):=V; + mmCOMPUTE_STATIC_THREAD_MGMT_SE1:DWORD(GPU_REGS.CS.STATIC_THREAD_MGMT_SE1):=V; + mmCOMPUTE_RESOURCE_LIMITS :DWORD(GPU_REGS.CS.RESOURCE_LIMITS ):=V; + // + mmSPI_SHADER_PGM_RSRC1_PS:DWORD(GPU_REGS.PS.RSRC1 ):=V; + mmSPI_SHADER_PGM_RSRC2_PS:DWORD(GPU_REGS.PS.RSRC2 ):=V; + mmSPI_SHADER_PGM_RSRC3_PS:DWORD(GPU_REGS.PS.RSRC3 ):=V; + mmSPI_SHADER_Z_FORMAT :DWORD(GPU_REGS.PS.Z_FORMAT ):=V; + mmSPI_SHADER_COL_FORMAT :DWORD(GPU_REGS.PS.COL_FORMAT ):=V; + mmSPI_PS_INPUT_ENA :DWORD(GPU_REGS.PS.INPUT_ENA ):=V; + mmSPI_PS_INPUT_ADDR :DWORD(GPU_REGS.PS.INPUT_ADDR ):=V; + mmSPI_PS_IN_CONTROL :DWORD(GPU_REGS.PS.IN_CONTROL ):=V; + mmSPI_BARYC_CNTL :DWORD(GPU_REGS.PS.BARYC_CNTL ):=V; + mmDB_SHADER_CONTROL :DWORD(GPU_REGS.PS.SHADER_CONTROL):=V; + mmCB_SHADER_MASK :DWORD(GPU_REGS.PS.SHADER_MASK ):=V; + // + mmSPI_SHADER_USER_DATA_PS_0..mmSPI_SHADER_USER_DATA_PS_15: + begin + i:=W.REG-mmSPI_SHADER_USER_DATA_PS_0; + GPU_REGS.PS.USER_DATA[i]:=V; + end; + // + mmSPI_PS_INPUT_CNTL_0..mmSPI_PS_INPUT_CNTL_31: + begin + i:=W.REG-mmSPI_PS_INPUT_CNTL_0; + DWORD(GPU_REGS.PS.INPUT_CNTL[i]):=V; + end; + // + mmSPI_SHADER_PGM_RSRC1_VS:DWORD(GPU_REGS.VS.RSRC1 ):=V; + mmSPI_SHADER_PGM_RSRC2_VS:DWORD(GPU_REGS.VS.RSRC2 ):=V; + mmSPI_SHADER_PGM_RSRC3_VS:DWORD(GPU_REGS.VS.RSRC3 ):=V; + mmSPI_VS_OUT_CONFIG :DWORD(GPU_REGS.VS.OUT_CONFIG):=V; + mmSPI_SHADER_POS_FORMAT :DWORD(GPU_REGS.VS.POS_FORMAT):=V; + mmPA_CL_VS_OUT_CNTL :DWORD(GPU_REGS.VS.OUT_CNTL ):=V; + // + mmSPI_SHADER_USER_DATA_VS_0..mmSPI_SHADER_USER_DATA_VS_15: + begin + i:=W.REG-mmSPI_SHADER_USER_DATA_VS_0; + GPU_REGS.VS.USER_DATA[i]:=V; + end; + // + mmVGT_NUM_INSTANCES :DWORD(GPU_REGS.VGT_NUM_INSTANCES):=V; + end; + + + end else + begin + size:=(W.COUNT+1)*4; + + if cfg.FPrintInfo then + if (W.COUNT<>0) then Writeln('block:',getRegName(W.REG),' size:',size); + + addr:=AllocMem(size+7); + if M.Read(Align(addr,8)^,size)<>size then + begin + FreeMem(addr); + Break; + end else + begin + Blocks.Add(addr); + addr:=Align(addr,8); + end; + + Case W.REG of + mmCOMPUTE_PGM_LO: + begin + GPU_REGS.CS.Addr:=addr; + end; + mmSPI_SHADER_PGM_LO_PS: + begin + GPU_REGS.PS.Addr:=addr; + end; + mmSPI_SHADER_PGM_LO_VS: + begin + GPU_REGS.VS.Addr:=addr; + end; + + mmCOMPUTE_USER_DATA_0..mmCOMPUTE_USER_DATA_14: + begin + i:=W.REG-mmCOMPUTE_USER_DATA_0; + GPU_REGS.CS.USER_DATA[i+0]:=DWORD({%H-}QWORD(addr)); + GPU_REGS.CS.USER_DATA[i+1]:=DWORD({%H-}QWORD(addr) shr 32); + end; + + mmSPI_SHADER_USER_DATA_PS_0..mmSPI_SHADER_USER_DATA_PS_14: + begin + i:=W.REG-mmSPI_SHADER_USER_DATA_PS_0; + GPU_REGS.PS.USER_DATA[i+0]:=DWORD({%H-}QWORD(addr)); + GPU_REGS.PS.USER_DATA[i+1]:=DWORD({%H-}QWORD(addr) shr 32); + end; + + mmSPI_SHADER_USER_DATA_VS_0..mmSPI_SHADER_USER_DATA_VS_14: + begin + i:=W.REG-mmSPI_SHADER_USER_DATA_VS_0; + GPU_REGS.VS.USER_DATA[i+0]:=DWORD({%H-}QWORD(addr)); + GPU_REGS.VS.USER_DATA[i+1]:=DWORD({%H-}QWORD(addr) shr 32); + end; + + end; + end; + until false; +end; + +procedure load_pssl(base:Pointer); +var + info:PShaderBinaryInfo; + Slots:PInputUsageSlot; + + SprvEmit:TSprvEmit; + + //LParser:TsrLParser; + //FCode:TsrCodeBlock; + + i:Byte; + +begin + if (base=nil) then Exit; + + info:=_calc_shader_info(base,MemSize(base) div 4); + + if cfg.FPrintInfo then + if (info<>nil) then + begin + Writeln('signature =',info^.signature ); + Writeln('version =',info^.version ); + Writeln('pssl_or_cg =',info^.pssl_or_cg ); + Writeln('cached =',info^.cached ); + Writeln('m_type =',info^.m_type ); + Writeln('source_type =',info^.source_type ); + Writeln('length =',info^.length ); + Writeln('chunkUsageBaseOffsetInDW=',info^.chunkUsageBaseOffsetInDW); + Writeln('numInputUsageSlots =',info^.numInputUsageSlots ); + Writeln('isSrt =',info^.isSrt ); + Writeln('isSrtUsedInfoValid =',info^.isSrtUsedInfoValid ); + Writeln('isExtendedUsageInfo =',info^.isExtendedUsageInfo ); + Writeln('reserved2 =',info^.reserved2 ); + Writeln('reserved3 =',info^.reserved3 ); + Writeln('shaderHash0 =','0x',HexStr(info^.shaderHash0,8)); + Writeln('shaderHash1 =','0x',HexStr(info^.shaderHash1,8)); + Writeln('crc32 =','0x',HexStr(info^.crc32,8) ); + writeln; + + if (info^.numInputUsageSlots<>0) then + begin + Slots:=_calc_shader_slot(info); + + For i:=0 to info^.numInputUsageSlots-1 do + begin + Writeln('Slot[',i,']'); + + case Slots[i].m_usageType of + kShaderInputUsageImmResource :Writeln(' ','kShaderInputUsageImmResource '); + kShaderInputUsageImmSampler :Writeln(' ','kShaderInputUsageImmSampler '); + kShaderInputUsageImmConstBuffer :Writeln(' ','kShaderInputUsageImmConstBuffer '); + kShaderInputUsageImmVertexBuffer :Writeln(' ','kShaderInputUsageImmVertexBuffer '); + kShaderInputUsageImmRwResource :Writeln(' ','kShaderInputUsageImmRwResource '); + kShaderInputUsageImmAluFloatConst :Writeln(' ','kShaderInputUsageImmAluFloatConst '); + kShaderInputUsageImmAluBool32Const :Writeln(' ','kShaderInputUsageImmAluBool32Const '); + kShaderInputUsageImmGdsCounterRange :Writeln(' ','kShaderInputUsageImmGdsCounterRange '); + kShaderInputUsageImmGdsMemoryRange :Writeln(' ','kShaderInputUsageImmGdsMemoryRange '); + kShaderInputUsageImmGwsBase :Writeln(' ','kShaderInputUsageImmGwsBase '); + kShaderInputUsageImmShaderResourceTable :Writeln(' ','kShaderInputUsageImmShaderResourceTable '); + kShaderInputUsageImmLdsEsGsSize :Writeln(' ','kShaderInputUsageImmLdsEsGsSize '); + kShaderInputUsageSubPtrFetchShader :Writeln(' ','kShaderInputUsageSubPtrFetchShader '); + kShaderInputUsagePtrResourceTable :Writeln(' ','kShaderInputUsagePtrResourceTable '); + kShaderInputUsagePtrInternalResourceTable :Writeln(' ','kShaderInputUsagePtrInternalResourceTable '); + kShaderInputUsagePtrSamplerTable :Writeln(' ','kShaderInputUsagePtrSamplerTable '); + kShaderInputUsagePtrConstBufferTable :Writeln(' ','kShaderInputUsagePtrConstBufferTable '); + kShaderInputUsagePtrVertexBufferTable :Writeln(' ','kShaderInputUsagePtrVertexBufferTable '); + kShaderInputUsagePtrSoBufferTable :Writeln(' ','kShaderInputUsagePtrSoBufferTable '); + kShaderInputUsagePtrRwResourceTable :Writeln(' ','kShaderInputUsagePtrRwResourceTable '); + kShaderInputUsagePtrInternalGlobalTable :Writeln(' ','kShaderInputUsagePtrInternalGlobalTable '); + kShaderInputUsagePtrExtendedUserData :Writeln(' ','kShaderInputUsagePtrExtendedUserData '); + kShaderInputUsagePtrIndirectResourceTable :Writeln(' ','kShaderInputUsagePtrIndirectResourceTable '); + kShaderInputUsagePtrIndirectInternalResourceTable:Writeln(' ','kShaderInputUsagePtrIndirectInternalResourceTable'); + kShaderInputUsagePtrIndirectRwResourceTable :Writeln(' ','kShaderInputUsagePtrIndirectRwResourceTable '); + kShaderInputUsageImmGdsKickRingBufferOffse :Writeln(' ','kShaderInputUsageImmGdsKickRingBufferOffse '); + kShaderInputUsageImmVertexRingBufferOffse :Writeln(' ','kShaderInputUsageImmVertexRingBufferOffse '); + kShaderInputUsagePtrDispatchDraw :Writeln(' ','kShaderInputUsagePtrDispatchDraw '); + kShaderInputUsageImmDispatchDrawInstances :Writeln(' ','kShaderInputUsageImmDispatchDrawInstances '); + else + Writeln(' m_usageType=',Slots[i].m_usageType); + end; + + Writeln(' apiSlot=',Slots[i].m_apiSlot); + Writeln(' startRegister=',Slots[i].m_startRegister); + + Writeln(' param=',HexStr(Slots[i].m_srtSizeInDWordMinusOne,2)); + end; + Writeln; + end; + end; + + Assert(info<>nil); + + case info^.m_type of + kShaderTypePs : + begin + if cfg.FPrintInfo then + Writeln('USGPR:',GPU_REGS.PS.RSRC2.USER_SGPR,' VGPRS:',GPU_REGS.PS.RSRC1.VGPRS,' SGPRS:',GPU_REGS.PS.RSRC1.SGPRS); + + SprvEmit.InitPs(GPU_REGS.PS.RSRC2,GPU_REGS.PS.INPUT_ENA); + SprvEmit.SetUserData(@GPU_REGS.PS.USER_DATA); + end; + kShaderTypeVsVs: + begin + if cfg.FPrintInfo then + Writeln('USGPR:',GPU_REGS.VS.RSRC2.USER_SGPR,' VGPRS:',GPU_REGS.VS.RSRC1.VGPRS,' SGPRS:',GPU_REGS.VS.RSRC1.SGPRS); + + SprvEmit.InitVs(GPU_REGS.VS.RSRC2,GPU_REGS.VGT_NUM_INSTANCES); + SprvEmit.SetUserData(@GPU_REGS.VS.USER_DATA); + end; + kShaderTypeCs: + begin + if cfg.FPrintInfo then + Writeln('USGPR:',GPU_REGS.CS.RSRC2.USER_SGPR,' VGPRS:',GPU_REGS.CS.RSRC1.VGPRS,' SGPRS:',GPU_REGS.CS.RSRC1.SGPRS); + + SprvEmit.InitCs(GPU_REGS.CS.RSRC2,GPU_REGS.CS.NUM_THREAD_X,GPU_REGS.CS.NUM_THREAD_Y,GPU_REGS.CS.NUM_THREAD_Z); + SprvEmit.SetUserData(@GPU_REGS.CS.USER_DATA); + + end; + + else + begin + _parse_print(base); + Exit; + end; + end; + + SprvEmit.FPrintAsm :=cfg.FPrintAsm; + SprvEmit.FUseVertexInput:=cfg.FUseVertexInput; + SprvEmit.FUseTexelBuffer:=cfg.FUseTexelBuffer; + + SprvEmit.FBuffers.cfg:=cfg.BufferCfg; + + if (SprvEmit.Parse(base)>1) then + begin + Writeln(StdErr,'Shader Parse Err'); + end; + + if cfg.FPrintAsm or cfg.FPrintSpv or (cfg.FSave<>'') then + begin + post_SprvEmit(SprvEmit); + alloc_SprvEmit(SprvEmit); + end; + + if cfg.FPrintSpv then + begin + print_SprvEmit(SprvEmit); + Writeln; + end; + + if (cfg.FSave<>'') then + begin + SaveToFile_SprvEmit(cfg.FSave,SprvEmit); + end; + + if cfg.FPrintInfo then + Writeln('used_size=',SprvEmit.FAllocator.used_size); + + SprvEmit.FAllocator.Free; +end; + +function ParseCmd:Boolean; +var + i,n:Integer; +label + promo; +begin + if (ParamCount=0) then + begin + promo: + + Exit(False); + end; + + cfg.FUseVertexInput:=True; + cfg.BufferCfg.Init; + + n:=-1; + For i:=1 to ParamCount do + begin + case LowerCase(ParamStr(i)) of + '-i':cfg.FPrintInfo:=True; + '-a':cfg.FPrintAsm:=True; + '-p':cfg.FPrintSpv:=True; + '-eva':cfg.FUseVertexInput:=True; + '-dva':cfg.FUseVertexInput:=False; + '-etb':cfg.FUseTexelBuffer:=True; + '-dtb':cfg.FUseTexelBuffer:=False; + + '-b':n:=0; + + '-mubo':n:=1;//maxUniformBufferRange + '-pco':n:=2;//PushConstantsOffset + '-pcs':n:=3;//maxPushConstantsSize + '-sboa':n:=4;//minStorageBufferOffsetAlignment + '-uboa':n:=5;//minUniformBufferOffsetAlignment + + else + 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); + end; + n:=-1; + end; + end; + end; + + Result:=True; +end; + +begin + DefaultSystemCodePage:=CP_UTF8; + DefaultUnicodeCodePage:=CP_UTF8; + DefaultFileSystemCodePage:=CP_UTF8; + DefaultRTLFileSystemCodePage:=CP_UTF8; + UTF8CompareLocale:=CP_UTF8; + + FillChar(cfg,SizeOf(cfg),0); + + ParseCmd; + + 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-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\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_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\SonicMania\SonicMania_ps_11DF2A32.dump'); + + //load_dump('shader_dump\SonicMania\SonicMania_ps_3CC22A00.dump'); //cfg + end; + + if (cfg.FName<>'') then + load_dump(cfg.FName); + + load_pssl(GPU_REGS.CS.Addr); + + load_pssl(GPU_REGS.VS.Addr); + load_pssl(GPU_REGS.PS.Addr); + + if cfg.FPrintInfo then + readln; +end. + +{ + +///////////////////source ext + +[USER_DATA] + | + v +//DATA LAYOUT +[PARENT_LAYOUT|DATA_TYPE|OFFSET|INDEX] + ^ ^ ^ + | | | //CHILD LAYOUT //UNIFORM + | |[PARENT_LAYOUT|DATA_TYPE|OFFSET] <- [SOURCE_LAYOUT|HANDLE_TYPE|PVAR|PREG] + | | ^ ^ + | | | | + | | /-------------------------/ | + | | | | + | | v | + | | [PVAR] <- [opLoad]<--------------/ + | | + | | //CHILD LAYOUT //BUFFER + | [PARENT_LAYOUT|DATA_TYPE|OFFSET] <- [SOURCE_LAYOUT|CAST_NUM|PVAR] <-> [PVAR]<----------\ + | ^ | + | | //BUFFER FIELD | + | [SOURCE_BUFFER|SOURCE_FIELD|ID|OFFSET|SIZE|PREG] | + | ^ | | + | /------------/ | | + | | | | + | [OpAccessChain|ID|ID...]<-------------------------/ + | ^ | + | | | + | [opLoad]<-----------------------------------/ + | + |[SET] + | + | //CHAIN LAYOUT +[SOURCE_LAYOUT|OFFSET|PREG] <-> [opLoad] + +/////////////////// + + +[FUserDataVar] + ^ + | /----------------------------------------v---------------------------\ +[pArray|Source] <- [OpAccessChain|[Index]] <- [PChain|pWriter|ID] <- [opLoad] <- [pReg|ID] + + + [PChain]*x + ^ ^ + | | +[pGroup|chains] + +////////////////// + +[pUniform] + | ^ + v /-----------------------\ +[Forked_Var] <- [opLoad] <- [pReg|ID] <- [OpImageRead1D] + +////////////////// + +[OpVariable] [pointer struct] PushConstant + ^ ^ + | | + | [OpTypePointer] PushConstant [struct] + | ^ + | | + | [OpTypeStruct] [item1:type] <- aType + | ^ ^ ^ + | | | | + | | [OpMemberDecorate] [struct] [item1:index] Offset 0 + | | + | [OpDecorate] [struct] Block + | + | [OpTypePointer] PushConstant [item1:type] + | | + | v + [OpAccessChain] [pointer type] [pVar] [item1:index] + +} + + +{ + + x:=1 //write + + [opLabel]-> + + y:=x+1 //read ^make var + + [opLabel]<- + +////////////////////////////// + + y:=0 //write + + [opLabel]-> + + y:=1 //write + + y:=y+y //write <- + + [opLabel]<- + + x:=y+1; //read ^make var + + y:=1 //write <- reset var + +////////////////////////////// + + y:=0 //write + + [opLabel]-> + + x:=1 //write + + [opLabel]<- + + x:=y+1; //read ^nop + +////////////////////////////// + +[OpCond] + +IF[ [OpSelectionMerge] [OpBranchConditional] [OpLabel] + + //body + +[OpLabel] ]ENDIF + +////////////////////////////// + +IF[ [OpBranch] [OpLabel] + + WHILE[ [OpLoopMerge] [OpBranch] [OpLabel] + + //body + + [OpBranch] [OpLabel] ]WHILE(1) + + [OpCond] + +[OpBranchConditional] [OpLabel] ]WHILE(2) ]ENDIF + +////////////////////////////// + +} + + + + + + diff --git a/spirv/spirv.pas b/spirv/spirv.pas new file mode 100644 index 0000000..62d50f6 --- /dev/null +++ b/spirv/spirv.pas @@ -0,0 +1,4120 @@ +{ + Copyright (c) 2014-2020 The Khronos Group Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and/or associated documentation files (the "Materials"), + to deal in the Materials without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Materials, and to permit persons to whom the + Materials are furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Materials. + + MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS + STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND + HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ + + THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS + IN THE MATERIALS. + + This header is automatically generated by the same tool that creates + the Binary Section of the SPIR-V specification. + + Enumeration tokens for SPIR-V, in various styles: + C, C++, C++11, JSON, Lua, Python, C#, D + + - C will have tokens with a "Spv" prefix, e.g.: SpvSourceLanguageGLSL + - C++ will have tokens in the "spv" name space, e.g.: spv::SourceLanguageGLSL + - C++11 will use enum classes in the spv namespace, e.g.: spv::SourceLanguage::GLSL + - Lua will use tables, e.g.: spv.SourceLanguage.GLSL + - Python will use dictionaries, e.g.: spv['SourceLanguage']['GLSL'] + - C# will use enum classes in the Specification class located in the "Spv" namespace, + e.g.: Spv.Specification.SourceLanguage.GLSL + - D will have tokens under the "spv" module, e.g: spv.SourceLanguage.GLSL + + Some tokens act like mask values, which can be OR'd together, + while others are mutually exclusive. The mask-like ones have + "Mask" in their name, and a parallel enum that has the shift + amount (1 << x) for each corresponding enumerant. +} +unit spirv; + +{$mode objfpc}{$H+} + +{$WARNINGS OFF} + +interface + +Const + MagicNumber = 119734787; + OpCodeMask = 65535; + Revision = 1; + Version = 67072; + WordCountShift = 16; + +Type + SourceLanguage=object //Value + Const + Unknown = 0; + ESSL = 1; + GLSL = 2; + OpenCL_C = 3; + OpenCL_CPP = 4; + HLSL = 5; + CPP_for_OpenCL = 6; + function GetStr(w:Word):RawByteString; static; + end; + + ExecutionModel=object //Value + Const + Vertex = 0; + TessellationControl = 1; + TessellationEvaluation = 2; + Geometry = 3; + Fragment = 4; + GLCompute = 5; + Kernel = 6; + TaskNV = 5267; + MeshNV = 5268; + RayGenerationKHR = 5313; + IntersectionKHR = 5314; + AnyHitKHR = 5315; + ClosestHitKHR = 5316; + MissKHR = 5317; + CallableKHR = 5318; + function GetStr(w:Word):RawByteString; static; + end; + + AddressingModel=object //Value + Const + Logical = 0; + Physical32 = 1; + Physical64 = 2; + PhysicalStorageBuffer64 = 5348; + function GetStr(w:Word):RawByteString; static; + end; + + MemoryModel=object //Value + Const + Simple = 0; + GLSL450 = 1; + OpenCL = 2; + Vulkan = 3; + function GetStr(w:Word):RawByteString; static; + end; + + ExecutionMode=object //Value + Const + Invocations = 0; + SpacingEqual = 1; + SpacingFractionalEven = 2; + SpacingFractionalOdd = 3; + VertexOrderCw = 4; + VertexOrderCcw = 5; + PixelCenterInteger = 6; + OriginUpperLeft = 7; + OriginLowerLeft = 8; + EarlyFragmentTests = 9; + PointMode = 10; + Xfb = 11; + DepthReplacing = 12; + DepthGreater = 14; + DepthLess = 15; + DepthUnchanged = 16; + LocalSize = 17; + LocalSizeHint = 18; + InputPoints = 19; + InputLines = 20; + InputLinesAdjacency = 21; + Triangles = 22; + InputTrianglesAdjacency = 23; + Quads = 24; + Isolines = 25; + OutputVertices = 26; + OutputPoints = 27; + OutputLineStrip = 28; + OutputTriangleStrip = 29; + VecTypeHint = 30; + ContractionOff = 31; + Initializer = 33; + Finalizer = 34; + SubgroupSize = 35; + SubgroupsPerWorkgroup = 36; + SubgroupsPerWorkgroupId = 37; + LocalSizeId = 38; + LocalSizeHintId = 39; + SubgroupUniformControlFlowKHR = 4421; + PostDepthCoverage = 4446; + DenormPreserve = 4459; + DenormFlushToZero = 4460; + SignedZeroInfNanPreserve = 4461; + RoundingModeRTE = 4462; + RoundingModeRTZ = 4463; + StencilRefReplacingEXT = 5027; + OutputLinesNV = 5269; + OutputPrimitivesNV = 5270; + DerivativeGroupQuadsNV = 5289; + DerivativeGroupLinearNV = 5290; + OutputTrianglesNV = 5298; + PixelInterlockOrderedEXT = 5366; + PixelInterlockUnorderedEXT = 5367; + SampleInterlockOrderedEXT = 5368; + SampleInterlockUnorderedEXT = 5369; + ShadingRateInterlockOrderedEXT = 5370; + ShadingRateInterlockUnorderedEXT = 5371; + SharedLocalMemorySizeINTEL = 5618; + RoundingModeRTPINTEL = 5620; + RoundingModeRTNINTEL = 5621; + FloatingPointModeALTINTEL = 5622; + FloatingPointModeIEEEINTEL = 5623; + MaxWorkgroupSizeINTEL = 5893; + MaxWorkDimINTEL = 5894; + NoGlobalOffsetINTEL = 5895; + NumSIMDWorkitemsINTEL = 5896; + SchedulerTargetFmaxMhzINTEL = 5903; + function GetStr(w:Word):RawByteString; static; + end; + + StorageClass=object //Value + Const + UniformConstant = 0; + Input = 1; + Uniform = 2; + Output = 3; + Workgroup = 4; + CrossWorkgroup = 5; + Private_ = 6; + Function_ = 7; + Generic_ = 8; + PushConstant = 9; + AtomicCounter = 10; + Image = 11; + StorageBuffer = 12; + CallableDataKHR = 5328; + IncomingCallableDataKHR = 5329; + RayPayloadKHR = 5338; + HitAttributeKHR = 5339; + IncomingRayPayloadKHR = 5342; + ShaderRecordBufferKHR = 5343; + PhysicalStorageBuffer = 5349; + CodeSectionINTEL = 5605; + DeviceOnlyINTEL = 5936; + HostOnlyINTEL = 5937; + function GetStr(w:Word):RawByteString; static; + end; + + Dim=object //Value + Const + Dim1D = 0; + Dim2D = 1; + Dim3D = 2; + Cube = 3; + Rect = 4; + Buffer = 5; + SubpassData = 6; + function GetStr(w:Word):RawByteString; static; + end; + + SamplerAddressingMode=object //Value + Const + None = 0; + ClampToEdge = 1; + Clamp = 2; + Repeat_ = 3; + RepeatMirrored = 4; + function GetStr(w:Word):RawByteString; static; + end; + + SamplerFilterMode=object //Value + Const + Nearest = 0; + Linear = 1; + function GetStr(w:Word):RawByteString; static; + end; + + ImageFormat=object //Value + Const + Unknown = 0; + Rgba32f = 1; + Rgba16f = 2; + R32f = 3; + Rgba8 = 4; + Rgba8Snorm = 5; + Rg32f = 6; + Rg16f = 7; + R11fG11fB10f = 8; + R16f = 9; + Rgba16 = 10; + Rgb10A2 = 11; + Rg16 = 12; + Rg8 = 13; + R16 = 14; + R8 = 15; + Rgba16Snorm = 16; + Rg16Snorm = 17; + Rg8Snorm = 18; + R16Snorm = 19; + R8Snorm = 20; + Rgba32i = 21; + Rgba16i = 22; + Rgba8i = 23; + R32i = 24; + Rg32i = 25; + Rg16i = 26; + Rg8i = 27; + R16i = 28; + R8i = 29; + Rgba32ui = 30; + Rgba16ui = 31; + Rgba8ui = 32; + R32ui = 33; + Rgb10a2ui = 34; + Rg32ui = 35; + Rg16ui = 36; + Rg8ui = 37; + R16ui = 38; + R8ui = 39; + R64ui = 40; + R64i = 41; + function GetStr(w:Word):RawByteString; static; + end; + + ImageChannelOrder=object //Value + Const + R = 0; + A = 1; + RG = 2; + RA = 3; + RGB = 4; + RGBA = 5; + BGRA = 6; + ARGB = 7; + Intensity = 8; + Luminance = 9; + Rx = 10; + RGx = 11; + RGBx = 12; + Depth = 13; + DepthStencil = 14; + sRGB = 15; + sRGBx = 16; + sRGBA = 17; + sBGRA = 18; + ABGR = 19; + function GetStr(w:Word):RawByteString; static; + end; + + ImageChannelDataType=object //Value + Const + SnormInt8 = 0; + SnormInt16 = 1; + UnormInt8 = 2; + UnormInt16 = 3; + UnormShort565 = 4; + UnormShort555 = 5; + UnormInt101010 = 6; + SignedInt8 = 7; + SignedInt16 = 8; + SignedInt32 = 9; + UnsignedInt8 = 10; + UnsignedInt16 = 11; + UnsignedInt32 = 12; + HalfFloat = 13; + Float = 14; + UnormInt24 = 15; + UnormInt101010_2 = 16; + function GetStr(w:Word):RawByteString; static; + end; + + ImageOperands=object //Bit + Const + None = 0; + Bias = 1; + Lod = 2; + Grad = 4; + ConstOffset = 8; + Offset = 16; + ConstOffsets = 32; + Sample = 64; + MinLod = 128; + MakeTexelAvailable = 256; + MakeTexelVisible = 512; + NonPrivateTexel = 1024; + VolatileTexel = 2048; + SignExtend = 4096; + ZeroExtend = 8192; + Nontemporal = 16384; + Offsets = 65536; + end; + + FPFastMathMode=object //Bit + Const + None = 0; + NotNaN = 1; + NotInf = 2; + NSZ = 4; + AllowRecip = 8; + Fast = 16; + AllowContractFastINTEL = 65536; + AllowReassocINTEL = 131072; + end; + + FPRoundingMode=object //Value + Const + RTE = 0; + RTZ = 1; + RTP = 2; + RTN = 3; + function GetStr(w:Word):RawByteString; static; + end; + + LinkageType=object //Value + Const + Export_ = 0; + Import = 1; + LinkOnceODR = 2; + function GetStr(w:Word):RawByteString; static; + end; + + AccessQualifier=object //Value + Const + ReadOnly = 0; + WriteOnly = 1; + ReadWrite = 2; + function GetStr(w:Word):RawByteString; static; + end; + + FunctionParameterAttribute=object //Value + Const + Zext = 0; + Sext = 1; + ByVal = 2; + Sret = 3; + NoAlias = 4; + NoCapture = 5; + NoWrite = 6; + NoReadWrite = 7; + function GetStr(w:Word):RawByteString; static; + end; + + Decoration=object //Value + Const + RelaxedPrecision = 0; + SpecId = 1; + Block = 2; + BufferBlock = 3; + RowMajor = 4; + ColMajor = 5; + ArrayStride = 6; + MatrixStride = 7; + GLSLShared = 8; + GLSLPacked = 9; + CPacked = 10; + BuiltIn = 11; + NoPerspective = 13; + Flat = 14; + Patch = 15; + Centroid = 16; + Sample = 17; + Invariant = 18; + Restrict = 19; + Aliased = 20; + Volatile = 21; + Constant = 22; + Coherent = 23; + NonWritable = 24; + NonReadable = 25; + Uniform = 26; + UniformId = 27; + SaturatedConversion = 28; + Stream = 29; + Location = 30; + Component = 31; + Index = 32; + Binding = 33; + DescriptorSet = 34; + Offset = 35; + XfbBuffer = 36; + XfbStride = 37; + FuncParamAttr = 38; + FPRoundingMode = 39; + FPFastMathMode = 40; + LinkageAttributes = 41; + NoContraction = 42; + InputAttachmentIndex = 43; + Alignment = 44; + MaxByteOffset = 45; + AlignmentId = 46; + MaxByteOffsetId = 47; + NoSignedWrap = 4469; + NoUnsignedWrap = 4470; + ExplicitInterpAMD = 4999; + OverrideCoverageNV = 5248; + PassthroughNV = 5250; + ViewportRelativeNV = 5252; + SecondaryViewportRelativeNV = 5256; + PerPrimitiveNV = 5271; + PerViewNV = 5272; + PerTaskNV = 5273; + PerVertexKHR = 5285; + NonUniform = 5300; + RestrictPointer = 5355; + AliasedPointer = 5356; + BindlessSamplerNV = 5398; + BindlessImageNV = 5399; + BoundSamplerNV = 5400; + BoundImageNV = 5401; + SIMTCallINTEL = 5599; + ReferencedIndirectlyINTEL = 5602; + ClobberINTEL = 5607; + SideEffectsINTEL = 5608; + VectorComputeVariableINTEL = 5624; + FuncParamIOKindINTEL = 5625; + VectorComputeFunctionINTEL = 5626; + StackCallINTEL = 5627; + GlobalVariableOffsetINTEL = 5628; + CounterBuffer = 5634; + UserSemantic = 5635; + UserTypeGOOGLE = 5636; + FunctionRoundingModeINTEL = 5822; + FunctionDenormModeINTEL = 5823; + RegisterINTEL = 5825; + MemoryINTEL = 5826; + NumbanksINTEL = 5827; + BankwidthINTEL = 5828; + MaxPrivateCopiesINTEL = 5829; + SinglepumpINTEL = 5830; + DoublepumpINTEL = 5831; + MaxReplicatesINTEL = 5832; + SimpleDualPortINTEL = 5833; + MergeINTEL = 5834; + BankBitsINTEL = 5835; + ForcePow2DepthINTEL = 5836; + BurstCoalesceINTEL = 5899; + CacheSizeINTEL = 5900; + DontStaticallyCoalesceINTEL = 5901; + PrefetchINTEL = 5902; + StallEnableINTEL = 5905; + FuseLoopsInFunctionINTEL = 5907; + BufferLocationINTEL = 5921; + IOPipeStorageINTEL = 5944; + FunctionFloatingPointModeINTEL = 6080; + SingleElementVectorINTEL = 6085; + VectorComputeCallableFunctionINTEL = 6087; + MediaBlockIOINTEL = 6140; + function GetStr(w:Word):RawByteString; static; + end; + + BuiltIn=object //Value + Const + Position = 0; + PointSize = 1; + ClipDistance = 3; + CullDistance = 4; + VertexId = 5; + InstanceId = 6; + PrimitiveId = 7; + InvocationId = 8; + Layer = 9; + ViewportIndex = 10; + TessLevelOuter = 11; + TessLevelInner = 12; + TessCoord = 13; + PatchVertices = 14; + FragCoord = 15; + PointCoord = 16; + FrontFacing = 17; + SampleId = 18; + SamplePosition = 19; + SampleMask = 20; + FragDepth = 22; + HelperInvocation = 23; + NumWorkgroups = 24; + WorkgroupSize = 25; + WorkgroupId = 26; + LocalInvocationId = 27; + GlobalInvocationId = 28; + LocalInvocationIndex = 29; + WorkDim = 30; + GlobalSize = 31; + EnqueuedWorkgroupSize = 32; + GlobalOffset = 33; + GlobalLinearId = 34; + SubgroupSize = 36; + SubgroupMaxSize = 37; + NumSubgroups = 38; + NumEnqueuedSubgroups = 39; + SubgroupId = 40; + SubgroupLocalInvocationId = 41; + VertexIndex = 42; + InstanceIndex = 43; + SubgroupEqMask = 4416; + SubgroupGeMask = 4417; + SubgroupGtMask = 4418; + SubgroupLeMask = 4419; + SubgroupLtMask = 4420; + BaseVertex = 4424; + BaseInstance = 4425; + DrawIndex = 4426; + PrimitiveShadingRateKHR = 4432; + DeviceIndex = 4438; + ViewIndex = 4440; + ShadingRateKHR = 4444; + BaryCoordNoPerspAMD = 4992; + BaryCoordNoPerspCentroidAMD = 4993; + BaryCoordNoPerspSampleAMD = 4994; + BaryCoordSmoothAMD = 4995; + BaryCoordSmoothCentroidAMD = 4996; + BaryCoordSmoothSampleAMD = 4997; + BaryCoordPullModelAMD = 4998; + FragStencilRefEXT = 5014; + ViewportMaskNV = 5253; + SecondaryPositionNV = 5257; + SecondaryViewportMaskNV = 5258; + PositionPerViewNV = 5261; + ViewportMaskPerViewNV = 5262; + FullyCoveredEXT = 5264; + TaskCountNV = 5274; + PrimitiveCountNV = 5275; + PrimitiveIndicesNV = 5276; + ClipDistancePerViewNV = 5277; + CullDistancePerViewNV = 5278; + LayerPerViewNV = 5279; + MeshViewCountNV = 5280; + MeshViewIndicesNV = 5281; + BaryCoordKHR = 5286; + BaryCoordNoPerspKHR = 5287; + FragSizeEXT = 5292; + InvocationsPerPixelNV = 5293; + LaunchIdKHR = 5319; + LaunchSizeKHR = 5320; + WorldRayOriginKHR = 5321; + WorldRayDirectionKHR = 5322; + ObjectRayOriginKHR = 5323; + ObjectRayDirectionKHR = 5324; + RayTminKHR = 5325; + RayTmaxKHR = 5326; + InstanceCustomIndexKHR = 5327; + ObjectToWorldKHR = 5330; + WorldToObjectKHR = 5331; + HitTNV = 5332; + HitKindKHR = 5333; + CurrentRayTimeNV = 5334; + IncomingRayFlagsKHR = 5351; + RayGeometryIndexKHR = 5352; + WarpsPerSMNV = 5374; + SMCountNV = 5375; + WarpIDNV = 5376; + SMIDNV = 5377; + function GetStr(w:Word):RawByteString; static; + end; + + SelectionControl=object //Bit + Const + None = 0; + Flatten = 1; + DontFlatten = 2; + end; + + LoopControl=object //Bit + Const + None = 0; + Unroll = 1; + DontUnroll = 2; + DependencyInfinite = 4; + DependencyLength = 8; + MinIterations = 16; + MaxIterations = 32; + IterationMultiple = 64; + PeelCount = 128; + PartialCount = 256; + InitiationIntervalINTEL = 65536; + MaxConcurrencyINTEL = 131072; + DependencyArrayINTEL = 262144; + PipelineEnableINTEL = 524288; + LoopCoalesceINTEL = 1048576; + MaxInterleavingINTEL = 2097152; + SpeculatedIterationsINTEL = 4194304; + NoFusionINTEL = 8388608; + end; + + FunctionControl=object //Bit + Const + None = 0; + Inline_ = 1; + DontInline = 2; + Pure = 4; + Const_ = 8; + OptNoneINTEL = 65536; + end; + + MemorySemantics=object //Bit + Const + None = 0; + Acquire = 2; + Release = 4; + AcquireRelease = 8; + SequentiallyConsistent = 16; + UniformMemory = 64; + SubgroupMemory = 128; + WorkgroupMemory = 256; + CrossWorkgroupMemory = 512; + AtomicCounterMemory = 1024; + ImageMemory = 2048; + OutputMemory = 4096; + MakeAvailable = 8192; + MakeVisible = 16384; + Volatile = 32768; + end; + + MemoryAccess=object //Bit + Const + None = 0; + Volatile = 1; + Aligned = 2; + Nontemporal = 4; + MakePointerAvailable = 8; + MakePointerVisible = 16; + NonPrivatePointer = 32; + end; + + Scope=object //Value + Const + CrossDevice = 0; + Device = 1; + Workgroup = 2; + Subgroup = 3; + Invocation = 4; + QueueFamily = 5; + ShaderCallKHR = 6; + function GetStr(w:Word):RawByteString; static; + end; + + GroupOperation=object //Value + Const + Reduce = 0; + InclusiveScan = 1; + ExclusiveScan = 2; + ClusteredReduce = 3; + PartitionedReduceNV = 6; + PartitionedInclusiveScanNV = 7; + PartitionedExclusiveScanNV = 8; + function GetStr(w:Word):RawByteString; static; + end; + + KernelEnqueueFlags=object //Value + Const + NoWait = 0; + WaitKernel = 1; + WaitWorkGroup = 2; + function GetStr(w:Word):RawByteString; static; + end; + + KernelProfilingInfo=object //Bit + Const + None = 0; + CmdExecTime = 1; + end; + + Capability=object //Value + Const + Matrix = 0; + Shader = 1; + Geometry = 2; + Tessellation = 3; + Addresses = 4; + Linkage = 5; + Kernel = 6; + Vector16 = 7; + Float16Buffer = 8; + Float16 = 9; + Float64 = 10; + Int64 = 11; + Int64Atomics = 12; + ImageBasic = 13; + ImageReadWrite = 14; + ImageMipmap = 15; + Pipes = 17; + Groups = 18; + DeviceEnqueue = 19; + LiteralSampler = 20; + AtomicStorage = 21; + Int16 = 22; + TessellationPointSize = 23; + GeometryPointSize = 24; + ImageGatherExtended = 25; + StorageImageMultisample = 27; + UniformBufferArrayDynamicIndexing = 28; + SampledImageArrayDynamicIndexing = 29; + StorageBufferArrayDynamicIndexing = 30; + StorageImageArrayDynamicIndexing = 31; + ClipDistance = 32; + CullDistance = 33; + ImageCubeArray = 34; + SampleRateShading = 35; + ImageRect = 36; + SampledRect = 37; + GenericPointer = 38; + Int8 = 39; + InputAttachment = 40; + SparseResidency = 41; + MinLod = 42; + Sampled1D = 43; + Image1D = 44; + SampledCubeArray = 45; + SampledBuffer = 46; + ImageBuffer = 47; + ImageMSArray = 48; + StorageImageExtendedFormats = 49; + ImageQuery = 50; + DerivativeControl = 51; + InterpolationFunction = 52; + TransformFeedback = 53; + GeometryStreams = 54; + StorageImageReadWithoutFormat = 55; + StorageImageWriteWithoutFormat = 56; + MultiViewport = 57; + SubgroupDispatch = 58; + NamedBarrier = 59; + PipeStorage = 60; + GroupNonUniform = 61; + GroupNonUniformVote = 62; + GroupNonUniformArithmetic = 63; + GroupNonUniformBallot = 64; + GroupNonUniformShuffle = 65; + GroupNonUniformShuffleRelative = 66; + GroupNonUniformClustered = 67; + GroupNonUniformQuad = 68; + ShaderLayer = 69; + ShaderViewportIndex = 70; + UniformDecoration = 71; + FragmentShadingRateKHR = 4422; + SubgroupBallotKHR = 4423; + DrawParameters = 4427; + WorkgroupMemoryExplicitLayoutKHR = 4428; + WorkgroupMemoryExplicitLayout8BitAccessKHR = 4429; + WorkgroupMemoryExplicitLayout16BitAccessKHR = 4430; + SubgroupVoteKHR = 4431; + StorageBuffer16BitAccess = 4433; + StorageUniform16 = 4434; + StoragePushConstant16 = 4435; + StorageInputOutput16 = 4436; + DeviceGroup = 4437; + MultiView = 4439; + VariablePointersStorageBuffer = 4441; + VariablePointers = 4442; + AtomicStorageOps = 4445; + SampleMaskPostDepthCoverage = 4447; + StorageBuffer8BitAccess = 4448; + UniformAndStorageBuffer8BitAccess = 4449; + StoragePushConstant8 = 4450; + DenormPreserve = 4464; + DenormFlushToZero = 4465; + SignedZeroInfNanPreserve = 4466; + RoundingModeRTE = 4467; + RoundingModeRTZ = 4468; + RayQueryProvisionalKHR = 4471; + RayQueryKHR = 4472; + RayTraversalPrimitiveCullingKHR = 4478; + RayTracingKHR = 4479; + Float16ImageAMD = 5008; + ImageGatherBiasLodAMD = 5009; + FragmentMaskAMD = 5010; + StencilExportEXT = 5013; + ImageReadWriteLodAMD = 5015; + Int64ImageEXT = 5016; + ShaderClockKHR = 5055; + SampleMaskOverrideCoverageNV = 5249; + GeometryShaderPassthroughNV = 5251; + ShaderViewportIndexLayerNV = 5254; + ShaderViewportMaskNV = 5255; + ShaderStereoViewNV = 5259; + PerViewAttributesNV = 5260; + FragmentFullyCoveredEXT = 5265; + MeshShadingNV = 5266; + ImageFootprintNV = 5282; + FragmentBarycentricKHR = 5284; + ComputeDerivativeGroupQuadsNV = 5288; + ShadingRateNV = 5291; + GroupNonUniformPartitionedNV = 5297; + ShaderNonUniform = 5301; + RuntimeDescriptorArray = 5302; + InputAttachmentArrayDynamicIndexing = 5303; + UniformTexelBufferArrayDynamicIndexing = 5304; + StorageTexelBufferArrayDynamicIndexing = 5305; + UniformBufferArrayNonUniformIndexing = 5306; + SampledImageArrayNonUniformIndexing = 5307; + StorageBufferArrayNonUniformIndexing = 5308; + StorageImageArrayNonUniformIndexing = 5309; + InputAttachmentArrayNonUniformIndexing = 5310; + UniformTexelBufferArrayNonUniformIndexing = 5311; + StorageTexelBufferArrayNonUniformIndexing = 5312; + RayTracingNV = 5340; + RayTracingMotionBlurNV = 5341; + VulkanMemoryModel = 5345; + VulkanMemoryModelDeviceScope = 5346; + PhysicalStorageBufferAddresses = 5347; + ComputeDerivativeGroupLinearNV = 5350; + RayTracingProvisionalKHR = 5353; + CooperativeMatrixNV = 5357; + FragmentShaderSampleInterlockEXT = 5363; + FragmentShaderShadingRateInterlockEXT = 5372; + ShaderSMBuiltinsNV = 5373; + FragmentShaderPixelInterlockEXT = 5378; + DemoteToHelperInvocation = 5379; + BindlessTextureNV = 5390; + SubgroupShuffleINTEL = 5568; + SubgroupBufferBlockIOINTEL = 5569; + SubgroupImageBlockIOINTEL = 5570; + SubgroupImageMediaBlockIOINTEL = 5579; + RoundToInfinityINTEL = 5582; + FloatingPointModeINTEL = 5583; + IntegerFunctions2INTEL = 5584; + FunctionPointersINTEL = 5603; + IndirectReferencesINTEL = 5604; + AsmINTEL = 5606; + AtomicFloat32MinMaxEXT = 5612; + AtomicFloat64MinMaxEXT = 5613; + AtomicFloat16MinMaxEXT = 5616; + VectorComputeINTEL = 5617; + VectorAnyINTEL = 5619; + ExpectAssumeKHR = 5629; + SubgroupAvcMotionEstimationINTEL = 5696; + SubgroupAvcMotionEstimationIntraINTEL = 5697; + SubgroupAvcMotionEstimationChromaINTEL = 5698; + VariableLengthArrayINTEL = 5817; + FunctionFloatControlINTEL = 5821; + FPGAMemoryAttributesINTEL = 5824; + FPFastMathModeINTEL = 5837; + ArbitraryPrecisionIntegersINTEL = 5844; + ArbitraryPrecisionFloatingPointINTEL = 5845; + UnstructuredLoopControlsINTEL = 5886; + FPGALoopControlsINTEL = 5888; + KernelAttributesINTEL = 5892; + FPGAKernelAttributesINTEL = 5897; + FPGAMemoryAccessesINTEL = 5898; + FPGAClusterAttributesINTEL = 5904; + LoopFuseINTEL = 5906; + FPGABufferLocationINTEL = 5920; + ArbitraryPrecisionFixedPointINTEL = 5922; + USMStorageClassesINTEL = 5935; + IOPipesINTEL = 5943; + BlockingPipesINTEL = 5945; + FPGARegINTEL = 5948; + DotProductInputAll = 6016; + DotProductInput4x8Bit = 6017; + DotProductInput4x8BitPacked = 6018; + DotProduct = 6019; + BitInstructions = 6025; + AtomicFloat32AddEXT = 6033; + AtomicFloat64AddEXT = 6034; + LongConstantCompositeINTEL = 6089; + OptNoneINTEL = 6094; + AtomicFloat16AddEXT = 6095; + DebugInfoModuleINTEL = 6114; + function GetStr(w:Word):RawByteString; static; + end; + + RayFlags=object //Bit + Const + None = 0; + OpaqueKHR = 1; + NoOpaqueKHR = 2; + TerminateOnFirstHitKHR = 4; + SkipClosestHitShaderKHR = 8; + CullBackFacingTrianglesKHR = 16; + CullFrontFacingTrianglesKHR = 32; + CullOpaqueKHR = 64; + CullNoOpaqueKHR = 128; + SkipTrianglesKHR = 256; + SkipAABBsKHR = 512; + end; + + RayQueryIntersection=object //Value + Const + RayQueryCandidateIntersectionKHR = 0; + RayQueryCommittedIntersectionKHR = 1; + function GetStr(w:Word):RawByteString; static; + end; + + RayQueryCommittedIntersectionType=object //Value + Const + RayQueryCommittedIntersectionNoneKHR = 0; + RayQueryCommittedIntersectionTriangleKHR = 1; + RayQueryCommittedIntersectionGeneratedKHR = 2; + function GetStr(w:Word):RawByteString; static; + end; + + RayQueryCandidateIntersectionType=object //Value + Const + RayQueryCandidateIntersectionTriangleKHR = 0; + RayQueryCandidateIntersectionAABBKHR = 1; + function GetStr(w:Word):RawByteString; static; + end; + + FragmentShadingRate=object //Bit + Const + None = 0; + Vertical2Pixels = 1; + Vertical4Pixels = 2; + Horizontal2Pixels = 4; + Horizontal4Pixels = 8; + end; + + FPDenormMode=object //Value + Const + Preserve = 0; + FlushToZero = 1; + function GetStr(w:Word):RawByteString; static; + end; + + FPOperationMode=object //Value + Const + IEEE = 0; + ALT = 1; + function GetStr(w:Word):RawByteString; static; + end; + + QuantizationModes=object //Value + Const + TRN = 0; + TRN_ZERO = 1; + RND = 2; + RND_ZERO = 3; + RND_INF = 4; + RND_MIN_INF = 5; + RND_CONV = 6; + RND_CONV_ODD = 7; + function GetStr(w:Word):RawByteString; static; + end; + + OverflowModes=object //Value + Const + WRAP = 0; + SAT = 1; + SAT_ZERO = 2; + SAT_SYM = 3; + function GetStr(w:Word):RawByteString; static; + end; + + PackedVectorFormat=object //Value + Const + PackedVectorFormat4x8Bit = 0; + function GetStr(w:Word):RawByteString; static; + end; + + Op=object //Value + Const + OpNop = 0; + OpUndef = 1; + OpSourceContinued = 2; + OpSource = 3; + OpSourceExtension = 4; + OpName = 5; + OpMemberName = 6; + OpString = 7; + OpLine = 8; + OpExtension = 10; + OpExtInstImport = 11; + OpExtInst = 12; + OpMemoryModel = 14; + OpEntryPoint = 15; + OpExecutionMode = 16; + OpCapability = 17; + OpTypeVoid = 19; + OpTypeBool = 20; + OpTypeInt = 21; + OpTypeFloat = 22; + OpTypeVector = 23; + OpTypeMatrix = 24; + OpTypeImage = 25; + OpTypeSampler = 26; + OpTypeSampledImage = 27; + OpTypeArray = 28; + OpTypeRuntimeArray = 29; + OpTypeStruct = 30; + OpTypeOpaque = 31; + OpTypePointer = 32; + OpTypeFunction = 33; + OpTypeEvent = 34; + OpTypeDeviceEvent = 35; + OpTypeReserveId = 36; + OpTypeQueue = 37; + OpTypePipe = 38; + OpTypeForwardPointer = 39; + OpConstantTrue = 41; + OpConstantFalse = 42; + OpConstant = 43; + OpConstantComposite = 44; + OpConstantSampler = 45; + OpConstantNull = 46; + OpSpecConstantTrue = 48; + OpSpecConstantFalse = 49; + OpSpecConstant = 50; + OpSpecConstantComposite = 51; + OpSpecConstantOp = 52; + OpFunction = 54; + OpFunctionParameter = 55; + OpFunctionEnd = 56; + OpFunctionCall = 57; + OpVariable = 59; + OpImageTexelPointer = 60; + OpLoad = 61; + OpStore = 62; + OpCopyMemory = 63; + OpCopyMemorySized = 64; + OpAccessChain = 65; + OpInBoundsAccessChain = 66; + OpPtrAccessChain = 67; + OpArrayLength = 68; + OpGenericPtrMemSemantics = 69; + OpInBoundsPtrAccessChain = 70; + OpDecorate = 71; + OpMemberDecorate = 72; + OpDecorationGroup = 73; + OpGroupDecorate = 74; + OpGroupMemberDecorate = 75; + OpVectorExtractDynamic = 77; + OpVectorInsertDynamic = 78; + OpVectorShuffle = 79; + OpCompositeConstruct = 80; + OpCompositeExtract = 81; + OpCompositeInsert = 82; + OpCopyObject = 83; + OpTranspose = 84; + OpSampledImage = 86; + OpImageSampleImplicitLod = 87; + OpImageSampleExplicitLod = 88; + OpImageSampleDrefImplicitLod = 89; + OpImageSampleDrefExplicitLod = 90; + OpImageSampleProjImplicitLod = 91; + OpImageSampleProjExplicitLod = 92; + OpImageSampleProjDrefImplicitLod = 93; + OpImageSampleProjDrefExplicitLod = 94; + OpImageFetch = 95; + OpImageGather = 96; + OpImageDrefGather = 97; + OpImageRead = 98; + OpImageWrite = 99; + OpImage = 100; + OpImageQueryFormat = 101; + OpImageQueryOrder = 102; + OpImageQuerySizeLod = 103; + OpImageQuerySize = 104; + OpImageQueryLod = 105; + OpImageQueryLevels = 106; + OpImageQuerySamples = 107; + OpConvertFToU = 109; + OpConvertFToS = 110; + OpConvertSToF = 111; + OpConvertUToF = 112; + OpUConvert = 113; + OpSConvert = 114; + OpFConvert = 115; + OpQuantizeToF16 = 116; + OpConvertPtrToU = 117; + OpSatConvertSToU = 118; + OpSatConvertUToS = 119; + OpConvertUToPtr = 120; + OpPtrCastToGeneric = 121; + OpGenericCastToPtr = 122; + OpGenericCastToPtrExplicit = 123; + OpBitcast = 124; + OpSNegate = 126; + OpFNegate = 127; + OpIAdd = 128; + OpFAdd = 129; + OpISub = 130; + OpFSub = 131; + OpIMul = 132; + OpFMul = 133; + OpUDiv = 134; + OpSDiv = 135; + OpFDiv = 136; + OpUMod = 137; + OpSRem = 138; + OpSMod = 139; + OpFRem = 140; + OpFMod = 141; + OpVectorTimesScalar = 142; + OpMatrixTimesScalar = 143; + OpVectorTimesMatrix = 144; + OpMatrixTimesVector = 145; + OpMatrixTimesMatrix = 146; + OpOuterProduct = 147; + OpDot = 148; + OpIAddCarry = 149; + OpISubBorrow = 150; + OpUMulExtended = 151; + OpSMulExtended = 152; + OpAny = 154; + OpAll = 155; + OpIsNan = 156; + OpIsInf = 157; + OpIsFinite = 158; + OpIsNormal = 159; + OpSignBitSet = 160; + OpLessOrGreater = 161; + OpOrdered = 162; + OpUnordered = 163; + OpLogicalEqual = 164; + OpLogicalNotEqual = 165; + OpLogicalOr = 166; + OpLogicalAnd = 167; + OpLogicalNot = 168; + OpSelect = 169; + OpIEqual = 170; + OpINotEqual = 171; + OpUGreaterThan = 172; + OpSGreaterThan = 173; + OpUGreaterThanEqual = 174; + OpSGreaterThanEqual = 175; + OpULessThan = 176; + OpSLessThan = 177; + OpULessThanEqual = 178; + OpSLessThanEqual = 179; + OpFOrdEqual = 180; + OpFUnordEqual = 181; + OpFOrdNotEqual = 182; + OpFUnordNotEqual = 183; + OpFOrdLessThan = 184; + OpFUnordLessThan = 185; + OpFOrdGreaterThan = 186; + OpFUnordGreaterThan = 187; + OpFOrdLessThanEqual = 188; + OpFUnordLessThanEqual = 189; + OpFOrdGreaterThanEqual = 190; + OpFUnordGreaterThanEqual = 191; + OpShiftRightLogical = 194; + OpShiftRightArithmetic = 195; + OpShiftLeftLogical = 196; + OpBitwiseOr = 197; + OpBitwiseXor = 198; + OpBitwiseAnd = 199; + OpNot = 200; + OpBitFieldInsert = 201; + OpBitFieldSExtract = 202; + OpBitFieldUExtract = 203; + OpBitReverse = 204; + OpBitCount = 205; + OpDPdx = 207; + OpDPdy = 208; + OpFwidth = 209; + OpDPdxFine = 210; + OpDPdyFine = 211; + OpFwidthFine = 212; + OpDPdxCoarse = 213; + OpDPdyCoarse = 214; + OpFwidthCoarse = 215; + OpEmitVertex = 218; + OpEndPrimitive = 219; + OpEmitStreamVertex = 220; + OpEndStreamPrimitive = 221; + OpControlBarrier = 224; + OpMemoryBarrier = 225; + OpAtomicLoad = 227; + OpAtomicStore = 228; + OpAtomicExchange = 229; + OpAtomicCompareExchange = 230; + OpAtomicCompareExchangeWeak = 231; + OpAtomicIIncrement = 232; + OpAtomicIDecrement = 233; + OpAtomicIAdd = 234; + OpAtomicISub = 235; + OpAtomicSMin = 236; + OpAtomicUMin = 237; + OpAtomicSMax = 238; + OpAtomicUMax = 239; + OpAtomicAnd = 240; + OpAtomicOr = 241; + OpAtomicXor = 242; + OpPhi = 245; + OpLoopMerge = 246; + OpSelectionMerge = 247; + OpLabel = 248; + OpBranch = 249; + OpBranchConditional = 250; + OpSwitch = 251; + OpKill = 252; + OpReturn = 253; + OpReturnValue = 254; + OpUnreachable = 255; + OpLifetimeStart = 256; + OpLifetimeStop = 257; + OpGroupAsyncCopy = 259; + OpGroupWaitEvents = 260; + OpGroupAll = 261; + OpGroupAny = 262; + OpGroupBroadcast = 263; + OpGroupIAdd = 264; + OpGroupFAdd = 265; + OpGroupFMin = 266; + OpGroupUMin = 267; + OpGroupSMin = 268; + OpGroupFMax = 269; + OpGroupUMax = 270; + OpGroupSMax = 271; + OpReadPipe = 274; + OpWritePipe = 275; + OpReservedReadPipe = 276; + OpReservedWritePipe = 277; + OpReserveReadPipePackets = 278; + OpReserveWritePipePackets = 279; + OpCommitReadPipe = 280; + OpCommitWritePipe = 281; + OpIsValidReserveId = 282; + OpGetNumPipePackets = 283; + OpGetMaxPipePackets = 284; + OpGroupReserveReadPipePackets = 285; + OpGroupReserveWritePipePackets = 286; + OpGroupCommitReadPipe = 287; + OpGroupCommitWritePipe = 288; + OpEnqueueMarker = 291; + OpEnqueueKernel = 292; + OpGetKernelNDrangeSubGroupCount = 293; + OpGetKernelNDrangeMaxSubGroupSize = 294; + OpGetKernelWorkGroupSize = 295; + OpGetKernelPreferredWorkGroupSizeMultiple = 296; + OpRetainEvent = 297; + OpReleaseEvent = 298; + OpCreateUserEvent = 299; + OpIsValidEvent = 300; + OpSetUserEventStatus = 301; + OpCaptureEventProfilingInfo = 302; + OpGetDefaultQueue = 303; + OpBuildNDRange = 304; + OpImageSparseSampleImplicitLod = 305; + OpImageSparseSampleExplicitLod = 306; + OpImageSparseSampleDrefImplicitLod = 307; + OpImageSparseSampleDrefExplicitLod = 308; + OpImageSparseSampleProjImplicitLod = 309; + OpImageSparseSampleProjExplicitLod = 310; + OpImageSparseSampleProjDrefImplicitLod = 311; + OpImageSparseSampleProjDrefExplicitLod = 312; + OpImageSparseFetch = 313; + OpImageSparseGather = 314; + OpImageSparseDrefGather = 315; + OpImageSparseTexelsResident = 316; + OpNoLine = 317; + OpAtomicFlagTestAndSet = 318; + OpAtomicFlagClear = 319; + OpImageSparseRead = 320; + OpSizeOf = 321; + OpTypePipeStorage = 322; + OpConstantPipeStorage = 323; + OpCreatePipeFromPipeStorage = 324; + OpGetKernelLocalSizeForSubgroupCount = 325; + OpGetKernelMaxNumSubgroups = 326; + OpTypeNamedBarrier = 327; + OpNamedBarrierInitialize = 328; + OpMemoryNamedBarrier = 329; + OpModuleProcessed = 330; + OpExecutionModeId = 331; + OpDecorateId = 332; + OpGroupNonUniformElect = 333; + OpGroupNonUniformAll = 334; + OpGroupNonUniformAny = 335; + OpGroupNonUniformAllEqual = 336; + OpGroupNonUniformBroadcast = 337; + OpGroupNonUniformBroadcastFirst = 338; + OpGroupNonUniformBallot = 339; + OpGroupNonUniformInverseBallot = 340; + OpGroupNonUniformBallotBitExtract = 341; + OpGroupNonUniformBallotBitCount = 342; + OpGroupNonUniformBallotFindLSB = 343; + OpGroupNonUniformBallotFindMSB = 344; + OpGroupNonUniformShuffle = 345; + OpGroupNonUniformShuffleXor = 346; + OpGroupNonUniformShuffleUp = 347; + OpGroupNonUniformShuffleDown = 348; + OpGroupNonUniformIAdd = 349; + OpGroupNonUniformFAdd = 350; + OpGroupNonUniformIMul = 351; + OpGroupNonUniformFMul = 352; + OpGroupNonUniformSMin = 353; + OpGroupNonUniformUMin = 354; + OpGroupNonUniformFMin = 355; + OpGroupNonUniformSMax = 356; + OpGroupNonUniformUMax = 357; + OpGroupNonUniformFMax = 358; + OpGroupNonUniformBitwiseAnd = 359; + OpGroupNonUniformBitwiseOr = 360; + OpGroupNonUniformBitwiseXor = 361; + OpGroupNonUniformLogicalAnd = 362; + OpGroupNonUniformLogicalOr = 363; + OpGroupNonUniformLogicalXor = 364; + OpGroupNonUniformQuadBroadcast = 365; + OpGroupNonUniformQuadSwap = 366; + OpCopyLogical = 400; + OpPtrEqual = 401; + OpPtrNotEqual = 402; + OpPtrDiff = 403; + OpTerminateInvocation = 4416; + OpSubgroupBallotKHR = 4421; + OpSubgroupFirstInvocationKHR = 4422; + OpSubgroupAllKHR = 4428; + OpSubgroupAnyKHR = 4429; + OpSubgroupAllEqualKHR = 4430; + OpSubgroupReadInvocationKHR = 4432; + OpTraceRayKHR = 4445; + OpExecuteCallableKHR = 4446; + OpConvertUToAccelerationStructureKHR = 4447; + OpIgnoreIntersectionKHR = 4448; + OpTerminateRayKHR = 4449; + OpSDot = 4450; + OpUDot = 4451; + OpSUDot = 4452; + OpSDotAccSat = 4453; + OpUDotAccSat = 4454; + OpSUDotAccSat = 4455; + OpTypeRayQueryKHR = 4472; + OpRayQueryInitializeKHR = 4473; + OpRayQueryTerminateKHR = 4474; + OpRayQueryGenerateIntersectionKHR = 4475; + OpRayQueryConfirmIntersectionKHR = 4476; + OpRayQueryProceedKHR = 4477; + OpRayQueryGetIntersectionTypeKHR = 4479; + OpGroupIAddNonUniformAMD = 5000; + OpGroupFAddNonUniformAMD = 5001; + OpGroupFMinNonUniformAMD = 5002; + OpGroupUMinNonUniformAMD = 5003; + OpGroupSMinNonUniformAMD = 5004; + OpGroupFMaxNonUniformAMD = 5005; + OpGroupUMaxNonUniformAMD = 5006; + OpGroupSMaxNonUniformAMD = 5007; + OpFragmentMaskFetchAMD = 5011; + OpFragmentFetchAMD = 5012; + OpReadClockKHR = 5056; + OpImageSampleFootprintNV = 5283; + OpGroupNonUniformPartitionNV = 5296; + OpWritePackedPrimitiveIndices4x8NV = 5299; + OpReportIntersectionKHR = 5334; + OpIgnoreIntersectionNV = 5335; + OpTerminateRayNV = 5336; + OpTraceNV = 5337; + OpTraceMotionNV = 5338; + OpTraceRayMotionNV = 5339; + OpTypeAccelerationStructureKHR = 5341; + OpExecuteCallableNV = 5344; + OpTypeCooperativeMatrixNV = 5358; + OpCooperativeMatrixLoadNV = 5359; + OpCooperativeMatrixStoreNV = 5360; + OpCooperativeMatrixMulAddNV = 5361; + OpCooperativeMatrixLengthNV = 5362; + OpBeginInvocationInterlockEXT = 5364; + OpEndInvocationInterlockEXT = 5365; + OpDemoteToHelperInvocation = 5380; + OpIsHelperInvocationEXT = 5381; + OpConvertUToImageNV = 5391; + OpConvertUToSamplerNV = 5392; + OpConvertImageToUNV = 5393; + OpConvertSamplerToUNV = 5394; + OpConvertUToSampledImageNV = 5395; + OpConvertSampledImageToUNV = 5396; + OpSamplerImageAddressingModeNV = 5397; + OpSubgroupShuffleINTEL = 5571; + OpSubgroupShuffleDownINTEL = 5572; + OpSubgroupShuffleUpINTEL = 5573; + OpSubgroupShuffleXorINTEL = 5574; + OpSubgroupBlockReadINTEL = 5575; + OpSubgroupBlockWriteINTEL = 5576; + OpSubgroupImageBlockReadINTEL = 5577; + OpSubgroupImageBlockWriteINTEL = 5578; + OpSubgroupImageMediaBlockReadINTEL = 5580; + OpSubgroupImageMediaBlockWriteINTEL = 5581; + OpUCountLeadingZerosINTEL = 5585; + OpUCountTrailingZerosINTEL = 5586; + OpAbsISubINTEL = 5587; + OpAbsUSubINTEL = 5588; + OpIAddSatINTEL = 5589; + OpUAddSatINTEL = 5590; + OpIAverageINTEL = 5591; + OpUAverageINTEL = 5592; + OpIAverageRoundedINTEL = 5593; + OpUAverageRoundedINTEL = 5594; + OpISubSatINTEL = 5595; + OpUSubSatINTEL = 5596; + OpIMul32x16INTEL = 5597; + OpUMul32x16INTEL = 5598; + OpConstantFunctionPointerINTEL = 5600; + OpFunctionPointerCallINTEL = 5601; + OpAsmTargetINTEL = 5609; + OpAsmINTEL = 5610; + OpAsmCallINTEL = 5611; + OpAtomicFMinEXT = 5614; + OpAtomicFMaxEXT = 5615; + OpAssumeTrueKHR = 5630; + OpExpectKHR = 5631; + OpDecorateString = 5632; + OpMemberDecorateString = 5633; + OpVmeImageINTEL = 5699; + OpTypeVmeImageINTEL = 5700; + OpTypeAvcImePayloadINTEL = 5701; + OpTypeAvcRefPayloadINTEL = 5702; + OpTypeAvcSicPayloadINTEL = 5703; + OpTypeAvcMcePayloadINTEL = 5704; + OpTypeAvcMceResultINTEL = 5705; + OpTypeAvcImeResultINTEL = 5706; + OpTypeAvcImeResultSingleReferenceStreamoutINTEL = 5707; + OpTypeAvcImeResultDualReferenceStreamoutINTEL = 5708; + OpTypeAvcImeSingleReferenceStreaminINTEL = 5709; + OpTypeAvcImeDualReferenceStreaminINTEL = 5710; + OpTypeAvcRefResultINTEL = 5711; + OpTypeAvcSicResultINTEL = 5712; + OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL = 5713; + OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL = 5714; + OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL = 5715; + OpSubgroupAvcMceSetInterShapePenaltyINTEL = 5716; + OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL = 5717; + OpSubgroupAvcMceSetInterDirectionPenaltyINTEL = 5718; + OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL = 5719; + OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL = 5720; + OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL = 5721; + OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL = 5722; + OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL = 5723; + OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL = 5724; + OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL = 5725; + OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL = 5726; + OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL = 5727; + OpSubgroupAvcMceSetAcOnlyHaarINTEL = 5728; + OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL = 5729; + OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL = 5730; + OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL = 5731; + OpSubgroupAvcMceConvertToImePayloadINTEL = 5732; + OpSubgroupAvcMceConvertToImeResultINTEL = 5733; + OpSubgroupAvcMceConvertToRefPayloadINTEL = 5734; + OpSubgroupAvcMceConvertToRefResultINTEL = 5735; + OpSubgroupAvcMceConvertToSicPayloadINTEL = 5736; + OpSubgroupAvcMceConvertToSicResultINTEL = 5737; + OpSubgroupAvcMceGetMotionVectorsINTEL = 5738; + OpSubgroupAvcMceGetInterDistortionsINTEL = 5739; + OpSubgroupAvcMceGetBestInterDistortionsINTEL = 5740; + OpSubgroupAvcMceGetInterMajorShapeINTEL = 5741; + OpSubgroupAvcMceGetInterMinorShapeINTEL = 5742; + OpSubgroupAvcMceGetInterDirectionsINTEL = 5743; + OpSubgroupAvcMceGetInterMotionVectorCountINTEL = 5744; + OpSubgroupAvcMceGetInterReferenceIdsINTEL = 5745; + OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL = 5746; + OpSubgroupAvcImeInitializeINTEL = 5747; + OpSubgroupAvcImeSetSingleReferenceINTEL = 5748; + OpSubgroupAvcImeSetDualReferenceINTEL = 5749; + OpSubgroupAvcImeRefWindowSizeINTEL = 5750; + OpSubgroupAvcImeAdjustRefOffsetINTEL = 5751; + OpSubgroupAvcImeConvertToMcePayloadINTEL = 5752; + OpSubgroupAvcImeSetMaxMotionVectorCountINTEL = 5753; + OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL = 5754; + OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL = 5755; + OpSubgroupAvcImeSetWeightedSadINTEL = 5756; + OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL = 5757; + OpSubgroupAvcImeEvaluateWithDualReferenceINTEL = 5758; + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL = 5759; + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL = 5760; + OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL = 5761; + OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL = 5762; + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL = 5763; + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL = 5764; + OpSubgroupAvcImeConvertToMceResultINTEL = 5765; + OpSubgroupAvcImeGetSingleReferenceStreaminINTEL = 5766; + OpSubgroupAvcImeGetDualReferenceStreaminINTEL = 5767; + OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL = 5768; + OpSubgroupAvcImeStripDualReferenceStreamoutINTEL = 5769; + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL = 5770; + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL = 5771; + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL = 5772; + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL = 5773; + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL = 5774; + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL = 5775; + OpSubgroupAvcImeGetBorderReachedINTEL = 5776; + OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL = 5777; + OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL = 5778; + OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL = 5779; + OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL = 5780; + OpSubgroupAvcFmeInitializeINTEL = 5781; + OpSubgroupAvcBmeInitializeINTEL = 5782; + OpSubgroupAvcRefConvertToMcePayloadINTEL = 5783; + OpSubgroupAvcRefSetBidirectionalMixDisableINTEL = 5784; + OpSubgroupAvcRefSetBilinearFilterEnableINTEL = 5785; + OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL = 5786; + OpSubgroupAvcRefEvaluateWithDualReferenceINTEL = 5787; + OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL = 5788; + OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL = 5789; + OpSubgroupAvcRefConvertToMceResultINTEL = 5790; + OpSubgroupAvcSicInitializeINTEL = 5791; + OpSubgroupAvcSicConfigureSkcINTEL = 5792; + OpSubgroupAvcSicConfigureIpeLumaINTEL = 5793; + OpSubgroupAvcSicConfigureIpeLumaChromaINTEL = 5794; + OpSubgroupAvcSicGetMotionVectorMaskINTEL = 5795; + OpSubgroupAvcSicConvertToMcePayloadINTEL = 5796; + OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL = 5797; + OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL = 5798; + OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL = 5799; + OpSubgroupAvcSicSetBilinearFilterEnableINTEL = 5800; + OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL = 5801; + OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL = 5802; + OpSubgroupAvcSicEvaluateIpeINTEL = 5803; + OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL = 5804; + OpSubgroupAvcSicEvaluateWithDualReferenceINTEL = 5805; + OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL = 5806; + OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL = 5807; + OpSubgroupAvcSicConvertToMceResultINTEL = 5808; + OpSubgroupAvcSicGetIpeLumaShapeINTEL = 5809; + OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL = 5810; + OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL = 5811; + OpSubgroupAvcSicGetPackedIpeLumaModesINTEL = 5812; + OpSubgroupAvcSicGetIpeChromaModeINTEL = 5813; + OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL = 5814; + OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL = 5815; + OpSubgroupAvcSicGetInterRawSadsINTEL = 5816; + OpVariableLengthArrayINTEL = 5818; + OpSaveMemoryINTEL = 5819; + OpRestoreMemoryINTEL = 5820; + OpArbitraryFloatSinCosPiINTEL = 5840; + OpArbitraryFloatCastINTEL = 5841; + OpArbitraryFloatCastFromIntINTEL = 5842; + OpArbitraryFloatCastToIntINTEL = 5843; + OpArbitraryFloatAddINTEL = 5846; + OpArbitraryFloatSubINTEL = 5847; + OpArbitraryFloatMulINTEL = 5848; + OpArbitraryFloatDivINTEL = 5849; + OpArbitraryFloatGTINTEL = 5850; + OpArbitraryFloatGEINTEL = 5851; + OpArbitraryFloatLTINTEL = 5852; + OpArbitraryFloatLEINTEL = 5853; + OpArbitraryFloatEQINTEL = 5854; + OpArbitraryFloatRecipINTEL = 5855; + OpArbitraryFloatRSqrtINTEL = 5856; + OpArbitraryFloatCbrtINTEL = 5857; + OpArbitraryFloatHypotINTEL = 5858; + OpArbitraryFloatSqrtINTEL = 5859; + OpArbitraryFloatLogINTEL = 5860; + OpArbitraryFloatLog2INTEL = 5861; + OpArbitraryFloatLog10INTEL = 5862; + OpArbitraryFloatLog1pINTEL = 5863; + OpArbitraryFloatExpINTEL = 5864; + OpArbitraryFloatExp2INTEL = 5865; + OpArbitraryFloatExp10INTEL = 5866; + OpArbitraryFloatExpm1INTEL = 5867; + OpArbitraryFloatSinINTEL = 5868; + OpArbitraryFloatCosINTEL = 5869; + OpArbitraryFloatSinCosINTEL = 5870; + OpArbitraryFloatSinPiINTEL = 5871; + OpArbitraryFloatCosPiINTEL = 5872; + OpArbitraryFloatASinINTEL = 5873; + OpArbitraryFloatASinPiINTEL = 5874; + OpArbitraryFloatACosINTEL = 5875; + OpArbitraryFloatACosPiINTEL = 5876; + OpArbitraryFloatATanINTEL = 5877; + OpArbitraryFloatATanPiINTEL = 5878; + OpArbitraryFloatATan2INTEL = 5879; + OpArbitraryFloatPowINTEL = 5880; + OpArbitraryFloatPowRINTEL = 5881; + OpArbitraryFloatPowNINTEL = 5882; + OpLoopControlINTEL = 5887; + OpFixedSqrtINTEL = 5923; + OpFixedRecipINTEL = 5924; + OpFixedRsqrtINTEL = 5925; + OpFixedSinINTEL = 5926; + OpFixedCosINTEL = 5927; + OpFixedSinCosINTEL = 5928; + OpFixedSinPiINTEL = 5929; + OpFixedCosPiINTEL = 5930; + OpFixedSinCosPiINTEL = 5931; + OpFixedLogINTEL = 5932; + OpFixedExpINTEL = 5933; + OpPtrCastToCrossWorkgroupINTEL = 5934; + OpCrossWorkgroupCastToPtrINTEL = 5938; + OpReadPipeBlockingINTEL = 5946; + OpWritePipeBlockingINTEL = 5947; + OpFPGARegINTEL = 5949; + OpRayQueryGetRayTMinKHR = 6016; + OpRayQueryGetRayFlagsKHR = 6017; + OpRayQueryGetIntersectionTKHR = 6018; + OpRayQueryGetIntersectionInstanceCustomIndexKHR = 6019; + OpRayQueryGetIntersectionInstanceIdKHR = 6020; + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR = 6021; + OpRayQueryGetIntersectionGeometryIndexKHR = 6022; + OpRayQueryGetIntersectionPrimitiveIndexKHR = 6023; + OpRayQueryGetIntersectionBarycentricsKHR = 6024; + OpRayQueryGetIntersectionFrontFaceKHR = 6025; + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR = 6026; + OpRayQueryGetIntersectionObjectRayDirectionKHR = 6027; + OpRayQueryGetIntersectionObjectRayOriginKHR = 6028; + OpRayQueryGetWorldRayDirectionKHR = 6029; + OpRayQueryGetWorldRayOriginKHR = 6030; + OpRayQueryGetIntersectionObjectToWorldKHR = 6031; + OpRayQueryGetIntersectionWorldToObjectKHR = 6032; + OpAtomicFAddEXT = 6035; + OpTypeBufferSurfaceINTEL = 6086; + OpTypeStructContinuedINTEL = 6090; + OpConstantCompositeContinuedINTEL = 6091; + OpSpecConstantCompositeContinuedINTEL = 6092; + function GetStr(w:Word):RawByteString; static; + type + TOpInfo=packed record + op_min:Word; + op_max:Word; + result:Boolean; + rstype:Boolean; + align:Word; + end; + function GetInfo(w:Word):TOpInfo; static; + end; + + GlslOp=object //extinst.glsl.std.450 + Const + Round = 1; + RoundEven = 2; + Trunc = 3; + FAbs = 4; + SAbs = 5; + FSign = 6; + SSign = 7; + Floor = 8; + Ceil = 9; + Fract = 10; + Radians = 11; + Degrees = 12; + Sin = 13; + Cos = 14; + Tan = 15; + Asin = 16; + Acos = 17; + Atan = 18; + Sinh = 19; + Cosh = 20; + Tanh = 21; + Asinh = 22; + Acosh = 23; + Atanh = 24; + Atan2 = 25; + Pow = 26; + Exp = 27; + Log = 28; + Exp2 = 29; + Log2 = 30; + Sqrt = 31; + InverseSqrt = 32; + Determinant = 33; + MatrixInverse = 34; + Modf = 35; + ModfStruct = 36; + FMin = 37; + UMin = 38; + SMin = 39; + FMax = 40; + UMax = 41; + SMax = 42; + FClamp = 43; + UClamp = 44; + SClamp = 45; + FMix = 46; + IMix = 47; + Step = 48; + SmoothStep = 49; + Fma = 50; + Frexp = 51; + FrexpStruct = 52; + Ldexp = 53; + PackSnorm4x8 = 54; + PackUnorm4x8 = 55; + PackSnorm2x16 = 56; + PackUnorm2x16 = 57; + PackHalf2x16 = 58; + PackDouble2x32 = 59; + UnpackSnorm2x16 = 60; + UnpackUnorm2x16 = 61; + UnpackHalf2x16 = 62; + UnpackSnorm4x8 = 63; + UnpackUnorm4x8 = 64; + UnpackDouble2x32 = 65; + Length = 66; + Distance = 67; + Cross = 68; + Normalize = 69; + FaceForward = 70; + Reflect = 71; + Refract = 72; + FindILsb = 73; + FindSMsb = 74; + FindUMsb = 75; + InterpolateAtCentroid = 76; + InterpolateAtSample = 77; + InterpolateAtOffset = 78; + NMin = 79; + NMax = 80; + NClamp = 81; + function GetStr(w:Word):RawByteString; static; + type + TOpInfo=packed record + op_min:Word; + op_max:Word; + result:Boolean; + rstype:Boolean; + align:Word; + end; + function GetInfo(w:Word):TOpInfo; static; + end; + +implementation + +function SourceLanguage.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Unknown:Result:='Unknown'; + ESSL:Result:='ESSL'; + GLSL:Result:='GLSL'; + OpenCL_C:Result:='OpenCL_C'; + OpenCL_CPP:Result:='OpenCL_CPP'; + HLSL:Result:='HLSL'; + CPP_for_OpenCL:Result:='CPP_for_OpenCL'; + end; +end; + +function ExecutionModel.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Vertex:Result:='Vertex'; + TessellationControl:Result:='TessellationControl'; + TessellationEvaluation:Result:='TessellationEvaluation'; + Geometry:Result:='Geometry'; + Fragment:Result:='Fragment'; + GLCompute:Result:='GLCompute'; + Kernel:Result:='Kernel'; + TaskNV:Result:='TaskNV'; + MeshNV:Result:='MeshNV'; + RayGenerationKHR:Result:='RayGenerationKHR'; + IntersectionKHR:Result:='IntersectionKHR'; + AnyHitKHR:Result:='AnyHitKHR'; + ClosestHitKHR:Result:='ClosestHitKHR'; + MissKHR:Result:='MissKHR'; + CallableKHR:Result:='CallableKHR'; + end; +end; + +function AddressingModel.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Logical:Result:='Logical'; + Physical32:Result:='Physical32'; + Physical64:Result:='Physical64'; + PhysicalStorageBuffer64:Result:='PhysicalStorageBuffer64'; + end; +end; + +function MemoryModel.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Simple:Result:='Simple'; + GLSL450:Result:='GLSL450'; + OpenCL:Result:='OpenCL'; + Vulkan:Result:='Vulkan'; + end; +end; + +function ExecutionMode.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Invocations:Result:='Invocations'; + SpacingEqual:Result:='SpacingEqual'; + SpacingFractionalEven:Result:='SpacingFractionalEven'; + SpacingFractionalOdd:Result:='SpacingFractionalOdd'; + VertexOrderCw:Result:='VertexOrderCw'; + VertexOrderCcw:Result:='VertexOrderCcw'; + PixelCenterInteger:Result:='PixelCenterInteger'; + OriginUpperLeft:Result:='OriginUpperLeft'; + OriginLowerLeft:Result:='OriginLowerLeft'; + EarlyFragmentTests:Result:='EarlyFragmentTests'; + PointMode:Result:='PointMode'; + Xfb:Result:='Xfb'; + DepthReplacing:Result:='DepthReplacing'; + DepthGreater:Result:='DepthGreater'; + DepthLess:Result:='DepthLess'; + DepthUnchanged:Result:='DepthUnchanged'; + LocalSize:Result:='LocalSize'; + LocalSizeHint:Result:='LocalSizeHint'; + InputPoints:Result:='InputPoints'; + InputLines:Result:='InputLines'; + InputLinesAdjacency:Result:='InputLinesAdjacency'; + Triangles:Result:='Triangles'; + InputTrianglesAdjacency:Result:='InputTrianglesAdjacency'; + Quads:Result:='Quads'; + Isolines:Result:='Isolines'; + OutputVertices:Result:='OutputVertices'; + OutputPoints:Result:='OutputPoints'; + OutputLineStrip:Result:='OutputLineStrip'; + OutputTriangleStrip:Result:='OutputTriangleStrip'; + VecTypeHint:Result:='VecTypeHint'; + ContractionOff:Result:='ContractionOff'; + Initializer:Result:='Initializer'; + Finalizer:Result:='Finalizer'; + SubgroupSize:Result:='SubgroupSize'; + SubgroupsPerWorkgroup:Result:='SubgroupsPerWorkgroup'; + SubgroupsPerWorkgroupId:Result:='SubgroupsPerWorkgroupId'; + LocalSizeId:Result:='LocalSizeId'; + LocalSizeHintId:Result:='LocalSizeHintId'; + SubgroupUniformControlFlowKHR:Result:='SubgroupUniformControlFlowKHR'; + PostDepthCoverage:Result:='PostDepthCoverage'; + DenormPreserve:Result:='DenormPreserve'; + DenormFlushToZero:Result:='DenormFlushToZero'; + SignedZeroInfNanPreserve:Result:='SignedZeroInfNanPreserve'; + RoundingModeRTE:Result:='RoundingModeRTE'; + RoundingModeRTZ:Result:='RoundingModeRTZ'; + StencilRefReplacingEXT:Result:='StencilRefReplacingEXT'; + OutputLinesNV:Result:='OutputLinesNV'; + OutputPrimitivesNV:Result:='OutputPrimitivesNV'; + DerivativeGroupQuadsNV:Result:='DerivativeGroupQuadsNV'; + DerivativeGroupLinearNV:Result:='DerivativeGroupLinearNV'; + OutputTrianglesNV:Result:='OutputTrianglesNV'; + PixelInterlockOrderedEXT:Result:='PixelInterlockOrderedEXT'; + PixelInterlockUnorderedEXT:Result:='PixelInterlockUnorderedEXT'; + SampleInterlockOrderedEXT:Result:='SampleInterlockOrderedEXT'; + SampleInterlockUnorderedEXT:Result:='SampleInterlockUnorderedEXT'; + ShadingRateInterlockOrderedEXT:Result:='ShadingRateInterlockOrderedEXT'; + ShadingRateInterlockUnorderedEXT:Result:='ShadingRateInterlockUnorderedEXT'; + SharedLocalMemorySizeINTEL:Result:='SharedLocalMemorySizeINTEL'; + RoundingModeRTPINTEL:Result:='RoundingModeRTPINTEL'; + RoundingModeRTNINTEL:Result:='RoundingModeRTNINTEL'; + FloatingPointModeALTINTEL:Result:='FloatingPointModeALTINTEL'; + FloatingPointModeIEEEINTEL:Result:='FloatingPointModeIEEEINTEL'; + MaxWorkgroupSizeINTEL:Result:='MaxWorkgroupSizeINTEL'; + MaxWorkDimINTEL:Result:='MaxWorkDimINTEL'; + NoGlobalOffsetINTEL:Result:='NoGlobalOffsetINTEL'; + NumSIMDWorkitemsINTEL:Result:='NumSIMDWorkitemsINTEL'; + SchedulerTargetFmaxMhzINTEL:Result:='SchedulerTargetFmaxMhzINTEL'; + end; +end; + +function StorageClass.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + UniformConstant:Result:='UniformConstant'; + Input:Result:='Input'; + Uniform:Result:='Uniform'; + Output:Result:='Output'; + Workgroup:Result:='Workgroup'; + CrossWorkgroup:Result:='CrossWorkgroup'; + Private_:Result:='Private'; + Function_:Result:='Function'; + Generic_:Result:='Generic'; + PushConstant:Result:='PushConstant'; + AtomicCounter:Result:='AtomicCounter'; + Image:Result:='Image'; + StorageBuffer:Result:='StorageBuffer'; + CallableDataKHR:Result:='CallableDataKHR'; + IncomingCallableDataKHR:Result:='IncomingCallableDataKHR'; + RayPayloadKHR:Result:='RayPayloadKHR'; + HitAttributeKHR:Result:='HitAttributeKHR'; + IncomingRayPayloadKHR:Result:='IncomingRayPayloadKHR'; + ShaderRecordBufferKHR:Result:='ShaderRecordBufferKHR'; + PhysicalStorageBuffer:Result:='PhysicalStorageBuffer'; + CodeSectionINTEL:Result:='CodeSectionINTEL'; + DeviceOnlyINTEL:Result:='DeviceOnlyINTEL'; + HostOnlyINTEL:Result:='HostOnlyINTEL'; + end; +end; + +function Dim.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Dim1D:Result:='Dim1D'; + Dim2D:Result:='Dim2D'; + Dim3D:Result:='Dim3D'; + Cube:Result:='Cube'; + Rect:Result:='Rect'; + Buffer:Result:='Buffer'; + SubpassData:Result:='SubpassData'; + end; +end; + +function SamplerAddressingMode.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + None:Result:='None'; + ClampToEdge:Result:='ClampToEdge'; + Clamp:Result:='Clamp'; + Repeat_:Result:='Repeat'; + RepeatMirrored:Result:='RepeatMirrored'; + end; +end; + +function SamplerFilterMode.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Nearest:Result:='Nearest'; + Linear:Result:='Linear'; + end; +end; + +function ImageFormat.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Unknown:Result:='Unknown'; + Rgba32f:Result:='Rgba32f'; + Rgba16f:Result:='Rgba16f'; + R32f:Result:='R32f'; + Rgba8:Result:='Rgba8'; + Rgba8Snorm:Result:='Rgba8Snorm'; + Rg32f:Result:='Rg32f'; + Rg16f:Result:='Rg16f'; + R11fG11fB10f:Result:='R11fG11fB10f'; + R16f:Result:='R16f'; + Rgba16:Result:='Rgba16'; + Rgb10A2:Result:='Rgb10A2'; + Rg16:Result:='Rg16'; + Rg8:Result:='Rg8'; + R16:Result:='R16'; + R8:Result:='R8'; + Rgba16Snorm:Result:='Rgba16Snorm'; + Rg16Snorm:Result:='Rg16Snorm'; + Rg8Snorm:Result:='Rg8Snorm'; + R16Snorm:Result:='R16Snorm'; + R8Snorm:Result:='R8Snorm'; + Rgba32i:Result:='Rgba32i'; + Rgba16i:Result:='Rgba16i'; + Rgba8i:Result:='Rgba8i'; + R32i:Result:='R32i'; + Rg32i:Result:='Rg32i'; + Rg16i:Result:='Rg16i'; + Rg8i:Result:='Rg8i'; + R16i:Result:='R16i'; + R8i:Result:='R8i'; + Rgba32ui:Result:='Rgba32ui'; + Rgba16ui:Result:='Rgba16ui'; + Rgba8ui:Result:='Rgba8ui'; + R32ui:Result:='R32ui'; + Rgb10a2ui:Result:='Rgb10a2ui'; + Rg32ui:Result:='Rg32ui'; + Rg16ui:Result:='Rg16ui'; + Rg8ui:Result:='Rg8ui'; + R16ui:Result:='R16ui'; + R8ui:Result:='R8ui'; + R64ui:Result:='R64ui'; + R64i:Result:='R64i'; + end; +end; + +function ImageChannelOrder.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + R:Result:='R'; + A:Result:='A'; + RG:Result:='RG'; + RA:Result:='RA'; + RGB:Result:='RGB'; + RGBA:Result:='RGBA'; + BGRA:Result:='BGRA'; + ARGB:Result:='ARGB'; + Intensity:Result:='Intensity'; + Luminance:Result:='Luminance'; + Rx:Result:='Rx'; + RGx:Result:='RGx'; + RGBx:Result:='RGBx'; + Depth:Result:='Depth'; + DepthStencil:Result:='DepthStencil'; + sRGB:Result:='sRGB'; + sRGBx:Result:='sRGBx'; + sRGBA:Result:='sRGBA'; + sBGRA:Result:='sBGRA'; + ABGR:Result:='ABGR'; + end; +end; + +function ImageChannelDataType.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + SnormInt8:Result:='SnormInt8'; + SnormInt16:Result:='SnormInt16'; + UnormInt8:Result:='UnormInt8'; + UnormInt16:Result:='UnormInt16'; + UnormShort565:Result:='UnormShort565'; + UnormShort555:Result:='UnormShort555'; + UnormInt101010:Result:='UnormInt101010'; + SignedInt8:Result:='SignedInt8'; + SignedInt16:Result:='SignedInt16'; + SignedInt32:Result:='SignedInt32'; + UnsignedInt8:Result:='UnsignedInt8'; + UnsignedInt16:Result:='UnsignedInt16'; + UnsignedInt32:Result:='UnsignedInt32'; + HalfFloat:Result:='HalfFloat'; + Float:Result:='Float'; + UnormInt24:Result:='UnormInt24'; + UnormInt101010_2:Result:='UnormInt101010_2'; + end; +end; + +function FPRoundingMode.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + RTE:Result:='RTE'; + RTZ:Result:='RTZ'; + RTP:Result:='RTP'; + RTN:Result:='RTN'; + end; +end; + +function LinkageType.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Export_:Result:='Export'; + Import:Result:='Import'; + LinkOnceODR:Result:='LinkOnceODR'; + end; +end; + +function AccessQualifier.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + ReadOnly:Result:='ReadOnly'; + WriteOnly:Result:='WriteOnly'; + ReadWrite:Result:='ReadWrite'; + end; +end; + +function FunctionParameterAttribute.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Zext:Result:='Zext'; + Sext:Result:='Sext'; + ByVal:Result:='ByVal'; + Sret:Result:='Sret'; + NoAlias:Result:='NoAlias'; + NoCapture:Result:='NoCapture'; + NoWrite:Result:='NoWrite'; + NoReadWrite:Result:='NoReadWrite'; + end; +end; + +function Decoration.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + RelaxedPrecision:Result:='RelaxedPrecision'; + SpecId:Result:='SpecId'; + Block:Result:='Block'; + BufferBlock:Result:='BufferBlock'; + RowMajor:Result:='RowMajor'; + ColMajor:Result:='ColMajor'; + ArrayStride:Result:='ArrayStride'; + MatrixStride:Result:='MatrixStride'; + GLSLShared:Result:='GLSLShared'; + GLSLPacked:Result:='GLSLPacked'; + CPacked:Result:='CPacked'; + BuiltIn:Result:='BuiltIn'; + NoPerspective:Result:='NoPerspective'; + Flat:Result:='Flat'; + Patch:Result:='Patch'; + Centroid:Result:='Centroid'; + Sample:Result:='Sample'; + Invariant:Result:='Invariant'; + Restrict:Result:='Restrict'; + Aliased:Result:='Aliased'; + Volatile:Result:='Volatile'; + Constant:Result:='Constant'; + Coherent:Result:='Coherent'; + NonWritable:Result:='NonWritable'; + NonReadable:Result:='NonReadable'; + Uniform:Result:='Uniform'; + UniformId:Result:='UniformId'; + SaturatedConversion:Result:='SaturatedConversion'; + Stream:Result:='Stream'; + Location:Result:='Location'; + Component:Result:='Component'; + Index:Result:='Index'; + Binding:Result:='Binding'; + DescriptorSet:Result:='DescriptorSet'; + Offset:Result:='Offset'; + XfbBuffer:Result:='XfbBuffer'; + XfbStride:Result:='XfbStride'; + FuncParamAttr:Result:='FuncParamAttr'; + FPRoundingMode:Result:='FPRoundingMode'; + FPFastMathMode:Result:='FPFastMathMode'; + LinkageAttributes:Result:='LinkageAttributes'; + NoContraction:Result:='NoContraction'; + InputAttachmentIndex:Result:='InputAttachmentIndex'; + Alignment:Result:='Alignment'; + MaxByteOffset:Result:='MaxByteOffset'; + AlignmentId:Result:='AlignmentId'; + MaxByteOffsetId:Result:='MaxByteOffsetId'; + NoSignedWrap:Result:='NoSignedWrap'; + NoUnsignedWrap:Result:='NoUnsignedWrap'; + ExplicitInterpAMD:Result:='ExplicitInterpAMD'; + OverrideCoverageNV:Result:='OverrideCoverageNV'; + PassthroughNV:Result:='PassthroughNV'; + ViewportRelativeNV:Result:='ViewportRelativeNV'; + SecondaryViewportRelativeNV:Result:='SecondaryViewportRelativeNV'; + PerPrimitiveNV:Result:='PerPrimitiveNV'; + PerViewNV:Result:='PerViewNV'; + PerTaskNV:Result:='PerTaskNV'; + PerVertexKHR:Result:='PerVertexKHR'; + NonUniform:Result:='NonUniform'; + RestrictPointer:Result:='RestrictPointer'; + AliasedPointer:Result:='AliasedPointer'; + BindlessSamplerNV:Result:='BindlessSamplerNV'; + BindlessImageNV:Result:='BindlessImageNV'; + BoundSamplerNV:Result:='BoundSamplerNV'; + BoundImageNV:Result:='BoundImageNV'; + SIMTCallINTEL:Result:='SIMTCallINTEL'; + ReferencedIndirectlyINTEL:Result:='ReferencedIndirectlyINTEL'; + ClobberINTEL:Result:='ClobberINTEL'; + SideEffectsINTEL:Result:='SideEffectsINTEL'; + VectorComputeVariableINTEL:Result:='VectorComputeVariableINTEL'; + FuncParamIOKindINTEL:Result:='FuncParamIOKindINTEL'; + VectorComputeFunctionINTEL:Result:='VectorComputeFunctionINTEL'; + StackCallINTEL:Result:='StackCallINTEL'; + GlobalVariableOffsetINTEL:Result:='GlobalVariableOffsetINTEL'; + CounterBuffer:Result:='CounterBuffer'; + UserSemantic:Result:='UserSemantic'; + UserTypeGOOGLE:Result:='UserTypeGOOGLE'; + FunctionRoundingModeINTEL:Result:='FunctionRoundingModeINTEL'; + FunctionDenormModeINTEL:Result:='FunctionDenormModeINTEL'; + RegisterINTEL:Result:='RegisterINTEL'; + MemoryINTEL:Result:='MemoryINTEL'; + NumbanksINTEL:Result:='NumbanksINTEL'; + BankwidthINTEL:Result:='BankwidthINTEL'; + MaxPrivateCopiesINTEL:Result:='MaxPrivateCopiesINTEL'; + SinglepumpINTEL:Result:='SinglepumpINTEL'; + DoublepumpINTEL:Result:='DoublepumpINTEL'; + MaxReplicatesINTEL:Result:='MaxReplicatesINTEL'; + SimpleDualPortINTEL:Result:='SimpleDualPortINTEL'; + MergeINTEL:Result:='MergeINTEL'; + BankBitsINTEL:Result:='BankBitsINTEL'; + ForcePow2DepthINTEL:Result:='ForcePow2DepthINTEL'; + BurstCoalesceINTEL:Result:='BurstCoalesceINTEL'; + CacheSizeINTEL:Result:='CacheSizeINTEL'; + DontStaticallyCoalesceINTEL:Result:='DontStaticallyCoalesceINTEL'; + PrefetchINTEL:Result:='PrefetchINTEL'; + StallEnableINTEL:Result:='StallEnableINTEL'; + FuseLoopsInFunctionINTEL:Result:='FuseLoopsInFunctionINTEL'; + BufferLocationINTEL:Result:='BufferLocationINTEL'; + IOPipeStorageINTEL:Result:='IOPipeStorageINTEL'; + FunctionFloatingPointModeINTEL:Result:='FunctionFloatingPointModeINTEL'; + SingleElementVectorINTEL:Result:='SingleElementVectorINTEL'; + VectorComputeCallableFunctionINTEL:Result:='VectorComputeCallableFunctionINTEL'; + MediaBlockIOINTEL:Result:='MediaBlockIOINTEL'; + end; +end; + +function BuiltIn.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Position:Result:='Position'; + PointSize:Result:='PointSize'; + ClipDistance:Result:='ClipDistance'; + CullDistance:Result:='CullDistance'; + VertexId:Result:='VertexId'; + InstanceId:Result:='InstanceId'; + PrimitiveId:Result:='PrimitiveId'; + InvocationId:Result:='InvocationId'; + Layer:Result:='Layer'; + ViewportIndex:Result:='ViewportIndex'; + TessLevelOuter:Result:='TessLevelOuter'; + TessLevelInner:Result:='TessLevelInner'; + TessCoord:Result:='TessCoord'; + PatchVertices:Result:='PatchVertices'; + FragCoord:Result:='FragCoord'; + PointCoord:Result:='PointCoord'; + FrontFacing:Result:='FrontFacing'; + SampleId:Result:='SampleId'; + SamplePosition:Result:='SamplePosition'; + SampleMask:Result:='SampleMask'; + FragDepth:Result:='FragDepth'; + HelperInvocation:Result:='HelperInvocation'; + NumWorkgroups:Result:='NumWorkgroups'; + WorkgroupSize:Result:='WorkgroupSize'; + WorkgroupId:Result:='WorkgroupId'; + LocalInvocationId:Result:='LocalInvocationId'; + GlobalInvocationId:Result:='GlobalInvocationId'; + LocalInvocationIndex:Result:='LocalInvocationIndex'; + WorkDim:Result:='WorkDim'; + GlobalSize:Result:='GlobalSize'; + EnqueuedWorkgroupSize:Result:='EnqueuedWorkgroupSize'; + GlobalOffset:Result:='GlobalOffset'; + GlobalLinearId:Result:='GlobalLinearId'; + SubgroupSize:Result:='SubgroupSize'; + SubgroupMaxSize:Result:='SubgroupMaxSize'; + NumSubgroups:Result:='NumSubgroups'; + NumEnqueuedSubgroups:Result:='NumEnqueuedSubgroups'; + SubgroupId:Result:='SubgroupId'; + SubgroupLocalInvocationId:Result:='SubgroupLocalInvocationId'; + VertexIndex:Result:='VertexIndex'; + InstanceIndex:Result:='InstanceIndex'; + SubgroupEqMask:Result:='SubgroupEqMask'; + SubgroupGeMask:Result:='SubgroupGeMask'; + SubgroupGtMask:Result:='SubgroupGtMask'; + SubgroupLeMask:Result:='SubgroupLeMask'; + SubgroupLtMask:Result:='SubgroupLtMask'; + BaseVertex:Result:='BaseVertex'; + BaseInstance:Result:='BaseInstance'; + DrawIndex:Result:='DrawIndex'; + PrimitiveShadingRateKHR:Result:='PrimitiveShadingRateKHR'; + DeviceIndex:Result:='DeviceIndex'; + ViewIndex:Result:='ViewIndex'; + ShadingRateKHR:Result:='ShadingRateKHR'; + BaryCoordNoPerspAMD:Result:='BaryCoordNoPerspAMD'; + BaryCoordNoPerspCentroidAMD:Result:='BaryCoordNoPerspCentroidAMD'; + BaryCoordNoPerspSampleAMD:Result:='BaryCoordNoPerspSampleAMD'; + BaryCoordSmoothAMD:Result:='BaryCoordSmoothAMD'; + BaryCoordSmoothCentroidAMD:Result:='BaryCoordSmoothCentroidAMD'; + BaryCoordSmoothSampleAMD:Result:='BaryCoordSmoothSampleAMD'; + BaryCoordPullModelAMD:Result:='BaryCoordPullModelAMD'; + FragStencilRefEXT:Result:='FragStencilRefEXT'; + ViewportMaskNV:Result:='ViewportMaskNV'; + SecondaryPositionNV:Result:='SecondaryPositionNV'; + SecondaryViewportMaskNV:Result:='SecondaryViewportMaskNV'; + PositionPerViewNV:Result:='PositionPerViewNV'; + ViewportMaskPerViewNV:Result:='ViewportMaskPerViewNV'; + FullyCoveredEXT:Result:='FullyCoveredEXT'; + TaskCountNV:Result:='TaskCountNV'; + PrimitiveCountNV:Result:='PrimitiveCountNV'; + PrimitiveIndicesNV:Result:='PrimitiveIndicesNV'; + ClipDistancePerViewNV:Result:='ClipDistancePerViewNV'; + CullDistancePerViewNV:Result:='CullDistancePerViewNV'; + LayerPerViewNV:Result:='LayerPerViewNV'; + MeshViewCountNV:Result:='MeshViewCountNV'; + MeshViewIndicesNV:Result:='MeshViewIndicesNV'; + BaryCoordKHR:Result:='BaryCoordKHR'; + BaryCoordNoPerspKHR:Result:='BaryCoordNoPerspKHR'; + FragSizeEXT:Result:='FragSizeEXT'; + InvocationsPerPixelNV:Result:='InvocationsPerPixelNV'; + LaunchIdKHR:Result:='LaunchIdKHR'; + LaunchSizeKHR:Result:='LaunchSizeKHR'; + WorldRayOriginKHR:Result:='WorldRayOriginKHR'; + WorldRayDirectionKHR:Result:='WorldRayDirectionKHR'; + ObjectRayOriginKHR:Result:='ObjectRayOriginKHR'; + ObjectRayDirectionKHR:Result:='ObjectRayDirectionKHR'; + RayTminKHR:Result:='RayTminKHR'; + RayTmaxKHR:Result:='RayTmaxKHR'; + InstanceCustomIndexKHR:Result:='InstanceCustomIndexKHR'; + ObjectToWorldKHR:Result:='ObjectToWorldKHR'; + WorldToObjectKHR:Result:='WorldToObjectKHR'; + HitTNV:Result:='HitTNV'; + HitKindKHR:Result:='HitKindKHR'; + CurrentRayTimeNV:Result:='CurrentRayTimeNV'; + IncomingRayFlagsKHR:Result:='IncomingRayFlagsKHR'; + RayGeometryIndexKHR:Result:='RayGeometryIndexKHR'; + WarpsPerSMNV:Result:='WarpsPerSMNV'; + SMCountNV:Result:='SMCountNV'; + WarpIDNV:Result:='WarpIDNV'; + SMIDNV:Result:='SMIDNV'; + end; +end; + +function Scope.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + CrossDevice:Result:='CrossDevice'; + Device:Result:='Device'; + Workgroup:Result:='Workgroup'; + Subgroup:Result:='Subgroup'; + Invocation:Result:='Invocation'; + QueueFamily:Result:='QueueFamily'; + ShaderCallKHR:Result:='ShaderCallKHR'; + end; +end; + +function GroupOperation.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Reduce:Result:='Reduce'; + InclusiveScan:Result:='InclusiveScan'; + ExclusiveScan:Result:='ExclusiveScan'; + ClusteredReduce:Result:='ClusteredReduce'; + PartitionedReduceNV:Result:='PartitionedReduceNV'; + PartitionedInclusiveScanNV:Result:='PartitionedInclusiveScanNV'; + PartitionedExclusiveScanNV:Result:='PartitionedExclusiveScanNV'; + end; +end; + +function KernelEnqueueFlags.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + NoWait:Result:='NoWait'; + WaitKernel:Result:='WaitKernel'; + WaitWorkGroup:Result:='WaitWorkGroup'; + end; +end; + +function Capability.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Matrix:Result:='Matrix'; + Shader:Result:='Shader'; + Geometry:Result:='Geometry'; + Tessellation:Result:='Tessellation'; + Addresses:Result:='Addresses'; + Linkage:Result:='Linkage'; + Kernel:Result:='Kernel'; + Vector16:Result:='Vector16'; + Float16Buffer:Result:='Float16Buffer'; + Float16:Result:='Float16'; + Float64:Result:='Float64'; + Int64:Result:='Int64'; + Int64Atomics:Result:='Int64Atomics'; + ImageBasic:Result:='ImageBasic'; + ImageReadWrite:Result:='ImageReadWrite'; + ImageMipmap:Result:='ImageMipmap'; + Pipes:Result:='Pipes'; + Groups:Result:='Groups'; + DeviceEnqueue:Result:='DeviceEnqueue'; + LiteralSampler:Result:='LiteralSampler'; + AtomicStorage:Result:='AtomicStorage'; + Int16:Result:='Int16'; + TessellationPointSize:Result:='TessellationPointSize'; + GeometryPointSize:Result:='GeometryPointSize'; + ImageGatherExtended:Result:='ImageGatherExtended'; + StorageImageMultisample:Result:='StorageImageMultisample'; + UniformBufferArrayDynamicIndexing:Result:='UniformBufferArrayDynamicIndexing'; + SampledImageArrayDynamicIndexing:Result:='SampledImageArrayDynamicIndexing'; + StorageBufferArrayDynamicIndexing:Result:='StorageBufferArrayDynamicIndexing'; + StorageImageArrayDynamicIndexing:Result:='StorageImageArrayDynamicIndexing'; + ClipDistance:Result:='ClipDistance'; + CullDistance:Result:='CullDistance'; + ImageCubeArray:Result:='ImageCubeArray'; + SampleRateShading:Result:='SampleRateShading'; + ImageRect:Result:='ImageRect'; + SampledRect:Result:='SampledRect'; + GenericPointer:Result:='GenericPointer'; + Int8:Result:='Int8'; + InputAttachment:Result:='InputAttachment'; + SparseResidency:Result:='SparseResidency'; + MinLod:Result:='MinLod'; + Sampled1D:Result:='Sampled1D'; + Image1D:Result:='Image1D'; + SampledCubeArray:Result:='SampledCubeArray'; + SampledBuffer:Result:='SampledBuffer'; + ImageBuffer:Result:='ImageBuffer'; + ImageMSArray:Result:='ImageMSArray'; + StorageImageExtendedFormats:Result:='StorageImageExtendedFormats'; + ImageQuery:Result:='ImageQuery'; + DerivativeControl:Result:='DerivativeControl'; + InterpolationFunction:Result:='InterpolationFunction'; + TransformFeedback:Result:='TransformFeedback'; + GeometryStreams:Result:='GeometryStreams'; + StorageImageReadWithoutFormat:Result:='StorageImageReadWithoutFormat'; + StorageImageWriteWithoutFormat:Result:='StorageImageWriteWithoutFormat'; + MultiViewport:Result:='MultiViewport'; + SubgroupDispatch:Result:='SubgroupDispatch'; + NamedBarrier:Result:='NamedBarrier'; + PipeStorage:Result:='PipeStorage'; + GroupNonUniform:Result:='GroupNonUniform'; + GroupNonUniformVote:Result:='GroupNonUniformVote'; + GroupNonUniformArithmetic:Result:='GroupNonUniformArithmetic'; + GroupNonUniformBallot:Result:='GroupNonUniformBallot'; + GroupNonUniformShuffle:Result:='GroupNonUniformShuffle'; + GroupNonUniformShuffleRelative:Result:='GroupNonUniformShuffleRelative'; + GroupNonUniformClustered:Result:='GroupNonUniformClustered'; + GroupNonUniformQuad:Result:='GroupNonUniformQuad'; + ShaderLayer:Result:='ShaderLayer'; + ShaderViewportIndex:Result:='ShaderViewportIndex'; + UniformDecoration:Result:='UniformDecoration'; + FragmentShadingRateKHR:Result:='FragmentShadingRateKHR'; + SubgroupBallotKHR:Result:='SubgroupBallotKHR'; + DrawParameters:Result:='DrawParameters'; + WorkgroupMemoryExplicitLayoutKHR:Result:='WorkgroupMemoryExplicitLayoutKHR'; + WorkgroupMemoryExplicitLayout8BitAccessKHR:Result:='WorkgroupMemoryExplicitLayout8BitAccessKHR'; + WorkgroupMemoryExplicitLayout16BitAccessKHR:Result:='WorkgroupMemoryExplicitLayout16BitAccessKHR'; + SubgroupVoteKHR:Result:='SubgroupVoteKHR'; + StorageBuffer16BitAccess:Result:='StorageBuffer16BitAccess'; + StorageUniform16:Result:='StorageUniform16'; + StoragePushConstant16:Result:='StoragePushConstant16'; + StorageInputOutput16:Result:='StorageInputOutput16'; + DeviceGroup:Result:='DeviceGroup'; + MultiView:Result:='MultiView'; + VariablePointersStorageBuffer:Result:='VariablePointersStorageBuffer'; + VariablePointers:Result:='VariablePointers'; + AtomicStorageOps:Result:='AtomicStorageOps'; + SampleMaskPostDepthCoverage:Result:='SampleMaskPostDepthCoverage'; + StorageBuffer8BitAccess:Result:='StorageBuffer8BitAccess'; + UniformAndStorageBuffer8BitAccess:Result:='UniformAndStorageBuffer8BitAccess'; + StoragePushConstant8:Result:='StoragePushConstant8'; + DenormPreserve:Result:='DenormPreserve'; + DenormFlushToZero:Result:='DenormFlushToZero'; + SignedZeroInfNanPreserve:Result:='SignedZeroInfNanPreserve'; + RoundingModeRTE:Result:='RoundingModeRTE'; + RoundingModeRTZ:Result:='RoundingModeRTZ'; + RayQueryProvisionalKHR:Result:='RayQueryProvisionalKHR'; + RayQueryKHR:Result:='RayQueryKHR'; + RayTraversalPrimitiveCullingKHR:Result:='RayTraversalPrimitiveCullingKHR'; + RayTracingKHR:Result:='RayTracingKHR'; + Float16ImageAMD:Result:='Float16ImageAMD'; + ImageGatherBiasLodAMD:Result:='ImageGatherBiasLodAMD'; + FragmentMaskAMD:Result:='FragmentMaskAMD'; + StencilExportEXT:Result:='StencilExportEXT'; + ImageReadWriteLodAMD:Result:='ImageReadWriteLodAMD'; + Int64ImageEXT:Result:='Int64ImageEXT'; + ShaderClockKHR:Result:='ShaderClockKHR'; + SampleMaskOverrideCoverageNV:Result:='SampleMaskOverrideCoverageNV'; + GeometryShaderPassthroughNV:Result:='GeometryShaderPassthroughNV'; + ShaderViewportIndexLayerNV:Result:='ShaderViewportIndexLayerNV'; + ShaderViewportMaskNV:Result:='ShaderViewportMaskNV'; + ShaderStereoViewNV:Result:='ShaderStereoViewNV'; + PerViewAttributesNV:Result:='PerViewAttributesNV'; + FragmentFullyCoveredEXT:Result:='FragmentFullyCoveredEXT'; + MeshShadingNV:Result:='MeshShadingNV'; + ImageFootprintNV:Result:='ImageFootprintNV'; + FragmentBarycentricKHR:Result:='FragmentBarycentricKHR'; + ComputeDerivativeGroupQuadsNV:Result:='ComputeDerivativeGroupQuadsNV'; + ShadingRateNV:Result:='ShadingRateNV'; + GroupNonUniformPartitionedNV:Result:='GroupNonUniformPartitionedNV'; + ShaderNonUniform:Result:='ShaderNonUniform'; + RuntimeDescriptorArray:Result:='RuntimeDescriptorArray'; + InputAttachmentArrayDynamicIndexing:Result:='InputAttachmentArrayDynamicIndexing'; + UniformTexelBufferArrayDynamicIndexing:Result:='UniformTexelBufferArrayDynamicIndexing'; + StorageTexelBufferArrayDynamicIndexing:Result:='StorageTexelBufferArrayDynamicIndexing'; + UniformBufferArrayNonUniformIndexing:Result:='UniformBufferArrayNonUniformIndexing'; + SampledImageArrayNonUniformIndexing:Result:='SampledImageArrayNonUniformIndexing'; + StorageBufferArrayNonUniformIndexing:Result:='StorageBufferArrayNonUniformIndexing'; + StorageImageArrayNonUniformIndexing:Result:='StorageImageArrayNonUniformIndexing'; + InputAttachmentArrayNonUniformIndexing:Result:='InputAttachmentArrayNonUniformIndexing'; + UniformTexelBufferArrayNonUniformIndexing:Result:='UniformTexelBufferArrayNonUniformIndexing'; + StorageTexelBufferArrayNonUniformIndexing:Result:='StorageTexelBufferArrayNonUniformIndexing'; + RayTracingNV:Result:='RayTracingNV'; + RayTracingMotionBlurNV:Result:='RayTracingMotionBlurNV'; + VulkanMemoryModel:Result:='VulkanMemoryModel'; + VulkanMemoryModelDeviceScope:Result:='VulkanMemoryModelDeviceScope'; + PhysicalStorageBufferAddresses:Result:='PhysicalStorageBufferAddresses'; + ComputeDerivativeGroupLinearNV:Result:='ComputeDerivativeGroupLinearNV'; + RayTracingProvisionalKHR:Result:='RayTracingProvisionalKHR'; + CooperativeMatrixNV:Result:='CooperativeMatrixNV'; + FragmentShaderSampleInterlockEXT:Result:='FragmentShaderSampleInterlockEXT'; + FragmentShaderShadingRateInterlockEXT:Result:='FragmentShaderShadingRateInterlockEXT'; + ShaderSMBuiltinsNV:Result:='ShaderSMBuiltinsNV'; + FragmentShaderPixelInterlockEXT:Result:='FragmentShaderPixelInterlockEXT'; + DemoteToHelperInvocation:Result:='DemoteToHelperInvocation'; + BindlessTextureNV:Result:='BindlessTextureNV'; + SubgroupShuffleINTEL:Result:='SubgroupShuffleINTEL'; + SubgroupBufferBlockIOINTEL:Result:='SubgroupBufferBlockIOINTEL'; + SubgroupImageBlockIOINTEL:Result:='SubgroupImageBlockIOINTEL'; + SubgroupImageMediaBlockIOINTEL:Result:='SubgroupImageMediaBlockIOINTEL'; + RoundToInfinityINTEL:Result:='RoundToInfinityINTEL'; + FloatingPointModeINTEL:Result:='FloatingPointModeINTEL'; + IntegerFunctions2INTEL:Result:='IntegerFunctions2INTEL'; + FunctionPointersINTEL:Result:='FunctionPointersINTEL'; + IndirectReferencesINTEL:Result:='IndirectReferencesINTEL'; + AsmINTEL:Result:='AsmINTEL'; + AtomicFloat32MinMaxEXT:Result:='AtomicFloat32MinMaxEXT'; + AtomicFloat64MinMaxEXT:Result:='AtomicFloat64MinMaxEXT'; + AtomicFloat16MinMaxEXT:Result:='AtomicFloat16MinMaxEXT'; + VectorComputeINTEL:Result:='VectorComputeINTEL'; + VectorAnyINTEL:Result:='VectorAnyINTEL'; + ExpectAssumeKHR:Result:='ExpectAssumeKHR'; + SubgroupAvcMotionEstimationINTEL:Result:='SubgroupAvcMotionEstimationINTEL'; + SubgroupAvcMotionEstimationIntraINTEL:Result:='SubgroupAvcMotionEstimationIntraINTEL'; + SubgroupAvcMotionEstimationChromaINTEL:Result:='SubgroupAvcMotionEstimationChromaINTEL'; + VariableLengthArrayINTEL:Result:='VariableLengthArrayINTEL'; + FunctionFloatControlINTEL:Result:='FunctionFloatControlINTEL'; + FPGAMemoryAttributesINTEL:Result:='FPGAMemoryAttributesINTEL'; + FPFastMathModeINTEL:Result:='FPFastMathModeINTEL'; + ArbitraryPrecisionIntegersINTEL:Result:='ArbitraryPrecisionIntegersINTEL'; + ArbitraryPrecisionFloatingPointINTEL:Result:='ArbitraryPrecisionFloatingPointINTEL'; + UnstructuredLoopControlsINTEL:Result:='UnstructuredLoopControlsINTEL'; + FPGALoopControlsINTEL:Result:='FPGALoopControlsINTEL'; + KernelAttributesINTEL:Result:='KernelAttributesINTEL'; + FPGAKernelAttributesINTEL:Result:='FPGAKernelAttributesINTEL'; + FPGAMemoryAccessesINTEL:Result:='FPGAMemoryAccessesINTEL'; + FPGAClusterAttributesINTEL:Result:='FPGAClusterAttributesINTEL'; + LoopFuseINTEL:Result:='LoopFuseINTEL'; + FPGABufferLocationINTEL:Result:='FPGABufferLocationINTEL'; + ArbitraryPrecisionFixedPointINTEL:Result:='ArbitraryPrecisionFixedPointINTEL'; + USMStorageClassesINTEL:Result:='USMStorageClassesINTEL'; + IOPipesINTEL:Result:='IOPipesINTEL'; + BlockingPipesINTEL:Result:='BlockingPipesINTEL'; + FPGARegINTEL:Result:='FPGARegINTEL'; + DotProductInputAll:Result:='DotProductInputAll'; + DotProductInput4x8Bit:Result:='DotProductInput4x8Bit'; + DotProductInput4x8BitPacked:Result:='DotProductInput4x8BitPacked'; + DotProduct:Result:='DotProduct'; + BitInstructions:Result:='BitInstructions'; + AtomicFloat32AddEXT:Result:='AtomicFloat32AddEXT'; + AtomicFloat64AddEXT:Result:='AtomicFloat64AddEXT'; + LongConstantCompositeINTEL:Result:='LongConstantCompositeINTEL'; + OptNoneINTEL:Result:='OptNoneINTEL'; + AtomicFloat16AddEXT:Result:='AtomicFloat16AddEXT'; + DebugInfoModuleINTEL:Result:='DebugInfoModuleINTEL'; + end; +end; + +function RayQueryIntersection.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + RayQueryCandidateIntersectionKHR:Result:='RayQueryCandidateIntersectionKHR'; + RayQueryCommittedIntersectionKHR:Result:='RayQueryCommittedIntersectionKHR'; + end; +end; + +function RayQueryCommittedIntersectionType.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + RayQueryCommittedIntersectionNoneKHR:Result:='RayQueryCommittedIntersectionNoneKHR'; + RayQueryCommittedIntersectionTriangleKHR:Result:='RayQueryCommittedIntersectionTriangleKHR'; + RayQueryCommittedIntersectionGeneratedKHR:Result:='RayQueryCommittedIntersectionGeneratedKHR'; + end; +end; + +function RayQueryCandidateIntersectionType.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + RayQueryCandidateIntersectionTriangleKHR:Result:='RayQueryCandidateIntersectionTriangleKHR'; + RayQueryCandidateIntersectionAABBKHR:Result:='RayQueryCandidateIntersectionAABBKHR'; + end; +end; + +function FPDenormMode.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Preserve:Result:='Preserve'; + FlushToZero:Result:='FlushToZero'; + end; +end; + +function FPOperationMode.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + IEEE:Result:='IEEE'; + ALT:Result:='ALT'; + end; +end; + +function QuantizationModes.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + TRN:Result:='TRN'; + TRN_ZERO:Result:='TRN_ZERO'; + RND:Result:='RND'; + RND_ZERO:Result:='RND_ZERO'; + RND_INF:Result:='RND_INF'; + RND_MIN_INF:Result:='RND_MIN_INF'; + RND_CONV:Result:='RND_CONV'; + RND_CONV_ODD:Result:='RND_CONV_ODD'; + end; +end; + +function OverflowModes.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + WRAP:Result:='WRAP'; + SAT:Result:='SAT'; + SAT_ZERO:Result:='SAT_ZERO'; + SAT_SYM:Result:='SAT_SYM'; + end; +end; + +function PackedVectorFormat.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + PackedVectorFormat4x8Bit:Result:='PackedVectorFormat4x8Bit'; + end; +end; + +function Op.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + OpNop:Result:='OpNop'; + OpUndef:Result:='OpUndef'; + OpSourceContinued:Result:='OpSourceContinued'; + OpSource:Result:='OpSource'; + OpSourceExtension:Result:='OpSourceExtension'; + OpName:Result:='OpName'; + OpMemberName:Result:='OpMemberName'; + OpString:Result:='OpString'; + OpLine:Result:='OpLine'; + OpExtension:Result:='OpExtension'; + OpExtInstImport:Result:='OpExtInstImport'; + OpExtInst:Result:='OpExtInst'; + OpMemoryModel:Result:='OpMemoryModel'; + OpEntryPoint:Result:='OpEntryPoint'; + OpExecutionMode:Result:='OpExecutionMode'; + OpCapability:Result:='OpCapability'; + OpTypeVoid:Result:='OpTypeVoid'; + OpTypeBool:Result:='OpTypeBool'; + OpTypeInt:Result:='OpTypeInt'; + OpTypeFloat:Result:='OpTypeFloat'; + OpTypeVector:Result:='OpTypeVector'; + OpTypeMatrix:Result:='OpTypeMatrix'; + OpTypeImage:Result:='OpTypeImage'; + OpTypeSampler:Result:='OpTypeSampler'; + OpTypeSampledImage:Result:='OpTypeSampledImage'; + OpTypeArray:Result:='OpTypeArray'; + OpTypeRuntimeArray:Result:='OpTypeRuntimeArray'; + OpTypeStruct:Result:='OpTypeStruct'; + OpTypeOpaque:Result:='OpTypeOpaque'; + OpTypePointer:Result:='OpTypePointer'; + OpTypeFunction:Result:='OpTypeFunction'; + OpTypeEvent:Result:='OpTypeEvent'; + OpTypeDeviceEvent:Result:='OpTypeDeviceEvent'; + OpTypeReserveId:Result:='OpTypeReserveId'; + OpTypeQueue:Result:='OpTypeQueue'; + OpTypePipe:Result:='OpTypePipe'; + OpTypeForwardPointer:Result:='OpTypeForwardPointer'; + OpConstantTrue:Result:='OpConstantTrue'; + OpConstantFalse:Result:='OpConstantFalse'; + OpConstant:Result:='OpConstant'; + OpConstantComposite:Result:='OpConstantComposite'; + OpConstantSampler:Result:='OpConstantSampler'; + OpConstantNull:Result:='OpConstantNull'; + OpSpecConstantTrue:Result:='OpSpecConstantTrue'; + OpSpecConstantFalse:Result:='OpSpecConstantFalse'; + OpSpecConstant:Result:='OpSpecConstant'; + OpSpecConstantComposite:Result:='OpSpecConstantComposite'; + OpSpecConstantOp:Result:='OpSpecConstantOp'; + OpFunction:Result:='OpFunction'; + OpFunctionParameter:Result:='OpFunctionParameter'; + OpFunctionEnd:Result:='OpFunctionEnd'; + OpFunctionCall:Result:='OpFunctionCall'; + OpVariable:Result:='OpVariable'; + OpImageTexelPointer:Result:='OpImageTexelPointer'; + OpLoad:Result:='OpLoad'; + OpStore:Result:='OpStore'; + OpCopyMemory:Result:='OpCopyMemory'; + OpCopyMemorySized:Result:='OpCopyMemorySized'; + OpAccessChain:Result:='OpAccessChain'; + OpInBoundsAccessChain:Result:='OpInBoundsAccessChain'; + OpPtrAccessChain:Result:='OpPtrAccessChain'; + OpArrayLength:Result:='OpArrayLength'; + OpGenericPtrMemSemantics:Result:='OpGenericPtrMemSemantics'; + OpInBoundsPtrAccessChain:Result:='OpInBoundsPtrAccessChain'; + OpDecorate:Result:='OpDecorate'; + OpMemberDecorate:Result:='OpMemberDecorate'; + OpDecorationGroup:Result:='OpDecorationGroup'; + OpGroupDecorate:Result:='OpGroupDecorate'; + OpGroupMemberDecorate:Result:='OpGroupMemberDecorate'; + OpVectorExtractDynamic:Result:='OpVectorExtractDynamic'; + OpVectorInsertDynamic:Result:='OpVectorInsertDynamic'; + OpVectorShuffle:Result:='OpVectorShuffle'; + OpCompositeConstruct:Result:='OpCompositeConstruct'; + OpCompositeExtract:Result:='OpCompositeExtract'; + OpCompositeInsert:Result:='OpCompositeInsert'; + OpCopyObject:Result:='OpCopyObject'; + OpTranspose:Result:='OpTranspose'; + OpSampledImage:Result:='OpSampledImage'; + OpImageSampleImplicitLod:Result:='OpImageSampleImplicitLod'; + OpImageSampleExplicitLod:Result:='OpImageSampleExplicitLod'; + OpImageSampleDrefImplicitLod:Result:='OpImageSampleDrefImplicitLod'; + OpImageSampleDrefExplicitLod:Result:='OpImageSampleDrefExplicitLod'; + OpImageSampleProjImplicitLod:Result:='OpImageSampleProjImplicitLod'; + OpImageSampleProjExplicitLod:Result:='OpImageSampleProjExplicitLod'; + OpImageSampleProjDrefImplicitLod:Result:='OpImageSampleProjDrefImplicitLod'; + OpImageSampleProjDrefExplicitLod:Result:='OpImageSampleProjDrefExplicitLod'; + OpImageFetch:Result:='OpImageFetch'; + OpImageGather:Result:='OpImageGather'; + OpImageDrefGather:Result:='OpImageDrefGather'; + OpImageRead:Result:='OpImageRead'; + OpImageWrite:Result:='OpImageWrite'; + OpImage:Result:='OpImage'; + OpImageQueryFormat:Result:='OpImageQueryFormat'; + OpImageQueryOrder:Result:='OpImageQueryOrder'; + OpImageQuerySizeLod:Result:='OpImageQuerySizeLod'; + OpImageQuerySize:Result:='OpImageQuerySize'; + OpImageQueryLod:Result:='OpImageQueryLod'; + OpImageQueryLevels:Result:='OpImageQueryLevels'; + OpImageQuerySamples:Result:='OpImageQuerySamples'; + OpConvertFToU:Result:='OpConvertFToU'; + OpConvertFToS:Result:='OpConvertFToS'; + OpConvertSToF:Result:='OpConvertSToF'; + OpConvertUToF:Result:='OpConvertUToF'; + OpUConvert:Result:='OpUConvert'; + OpSConvert:Result:='OpSConvert'; + OpFConvert:Result:='OpFConvert'; + OpQuantizeToF16:Result:='OpQuantizeToF16'; + OpConvertPtrToU:Result:='OpConvertPtrToU'; + OpSatConvertSToU:Result:='OpSatConvertSToU'; + OpSatConvertUToS:Result:='OpSatConvertUToS'; + OpConvertUToPtr:Result:='OpConvertUToPtr'; + OpPtrCastToGeneric:Result:='OpPtrCastToGeneric'; + OpGenericCastToPtr:Result:='OpGenericCastToPtr'; + OpGenericCastToPtrExplicit:Result:='OpGenericCastToPtrExplicit'; + OpBitcast:Result:='OpBitcast'; + OpSNegate:Result:='OpSNegate'; + OpFNegate:Result:='OpFNegate'; + OpIAdd:Result:='OpIAdd'; + OpFAdd:Result:='OpFAdd'; + OpISub:Result:='OpISub'; + OpFSub:Result:='OpFSub'; + OpIMul:Result:='OpIMul'; + OpFMul:Result:='OpFMul'; + OpUDiv:Result:='OpUDiv'; + OpSDiv:Result:='OpSDiv'; + OpFDiv:Result:='OpFDiv'; + OpUMod:Result:='OpUMod'; + OpSRem:Result:='OpSRem'; + OpSMod:Result:='OpSMod'; + OpFRem:Result:='OpFRem'; + OpFMod:Result:='OpFMod'; + OpVectorTimesScalar:Result:='OpVectorTimesScalar'; + OpMatrixTimesScalar:Result:='OpMatrixTimesScalar'; + OpVectorTimesMatrix:Result:='OpVectorTimesMatrix'; + OpMatrixTimesVector:Result:='OpMatrixTimesVector'; + OpMatrixTimesMatrix:Result:='OpMatrixTimesMatrix'; + OpOuterProduct:Result:='OpOuterProduct'; + OpDot:Result:='OpDot'; + OpIAddCarry:Result:='OpIAddCarry'; + OpISubBorrow:Result:='OpISubBorrow'; + OpUMulExtended:Result:='OpUMulExtended'; + OpSMulExtended:Result:='OpSMulExtended'; + OpAny:Result:='OpAny'; + OpAll:Result:='OpAll'; + OpIsNan:Result:='OpIsNan'; + OpIsInf:Result:='OpIsInf'; + OpIsFinite:Result:='OpIsFinite'; + OpIsNormal:Result:='OpIsNormal'; + OpSignBitSet:Result:='OpSignBitSet'; + OpLessOrGreater:Result:='OpLessOrGreater'; + OpOrdered:Result:='OpOrdered'; + OpUnordered:Result:='OpUnordered'; + OpLogicalEqual:Result:='OpLogicalEqual'; + OpLogicalNotEqual:Result:='OpLogicalNotEqual'; + OpLogicalOr:Result:='OpLogicalOr'; + OpLogicalAnd:Result:='OpLogicalAnd'; + OpLogicalNot:Result:='OpLogicalNot'; + OpSelect:Result:='OpSelect'; + OpIEqual:Result:='OpIEqual'; + OpINotEqual:Result:='OpINotEqual'; + OpUGreaterThan:Result:='OpUGreaterThan'; + OpSGreaterThan:Result:='OpSGreaterThan'; + OpUGreaterThanEqual:Result:='OpUGreaterThanEqual'; + OpSGreaterThanEqual:Result:='OpSGreaterThanEqual'; + OpULessThan:Result:='OpULessThan'; + OpSLessThan:Result:='OpSLessThan'; + OpULessThanEqual:Result:='OpULessThanEqual'; + OpSLessThanEqual:Result:='OpSLessThanEqual'; + OpFOrdEqual:Result:='OpFOrdEqual'; + OpFUnordEqual:Result:='OpFUnordEqual'; + OpFOrdNotEqual:Result:='OpFOrdNotEqual'; + OpFUnordNotEqual:Result:='OpFUnordNotEqual'; + OpFOrdLessThan:Result:='OpFOrdLessThan'; + OpFUnordLessThan:Result:='OpFUnordLessThan'; + OpFOrdGreaterThan:Result:='OpFOrdGreaterThan'; + OpFUnordGreaterThan:Result:='OpFUnordGreaterThan'; + OpFOrdLessThanEqual:Result:='OpFOrdLessThanEqual'; + OpFUnordLessThanEqual:Result:='OpFUnordLessThanEqual'; + OpFOrdGreaterThanEqual:Result:='OpFOrdGreaterThanEqual'; + OpFUnordGreaterThanEqual:Result:='OpFUnordGreaterThanEqual'; + OpShiftRightLogical:Result:='OpShiftRightLogical'; + OpShiftRightArithmetic:Result:='OpShiftRightArithmetic'; + OpShiftLeftLogical:Result:='OpShiftLeftLogical'; + OpBitwiseOr:Result:='OpBitwiseOr'; + OpBitwiseXor:Result:='OpBitwiseXor'; + OpBitwiseAnd:Result:='OpBitwiseAnd'; + OpNot:Result:='OpNot'; + OpBitFieldInsert:Result:='OpBitFieldInsert'; + OpBitFieldSExtract:Result:='OpBitFieldSExtract'; + OpBitFieldUExtract:Result:='OpBitFieldUExtract'; + OpBitReverse:Result:='OpBitReverse'; + OpBitCount:Result:='OpBitCount'; + OpDPdx:Result:='OpDPdx'; + OpDPdy:Result:='OpDPdy'; + OpFwidth:Result:='OpFwidth'; + OpDPdxFine:Result:='OpDPdxFine'; + OpDPdyFine:Result:='OpDPdyFine'; + OpFwidthFine:Result:='OpFwidthFine'; + OpDPdxCoarse:Result:='OpDPdxCoarse'; + OpDPdyCoarse:Result:='OpDPdyCoarse'; + OpFwidthCoarse:Result:='OpFwidthCoarse'; + OpEmitVertex:Result:='OpEmitVertex'; + OpEndPrimitive:Result:='OpEndPrimitive'; + OpEmitStreamVertex:Result:='OpEmitStreamVertex'; + OpEndStreamPrimitive:Result:='OpEndStreamPrimitive'; + OpControlBarrier:Result:='OpControlBarrier'; + OpMemoryBarrier:Result:='OpMemoryBarrier'; + OpAtomicLoad:Result:='OpAtomicLoad'; + OpAtomicStore:Result:='OpAtomicStore'; + OpAtomicExchange:Result:='OpAtomicExchange'; + OpAtomicCompareExchange:Result:='OpAtomicCompareExchange'; + OpAtomicCompareExchangeWeak:Result:='OpAtomicCompareExchangeWeak'; + OpAtomicIIncrement:Result:='OpAtomicIIncrement'; + OpAtomicIDecrement:Result:='OpAtomicIDecrement'; + OpAtomicIAdd:Result:='OpAtomicIAdd'; + OpAtomicISub:Result:='OpAtomicISub'; + OpAtomicSMin:Result:='OpAtomicSMin'; + OpAtomicUMin:Result:='OpAtomicUMin'; + OpAtomicSMax:Result:='OpAtomicSMax'; + OpAtomicUMax:Result:='OpAtomicUMax'; + OpAtomicAnd:Result:='OpAtomicAnd'; + OpAtomicOr:Result:='OpAtomicOr'; + OpAtomicXor:Result:='OpAtomicXor'; + OpPhi:Result:='OpPhi'; + OpLoopMerge:Result:='OpLoopMerge'; + OpSelectionMerge:Result:='OpSelectionMerge'; + OpLabel:Result:='OpLabel'; + OpBranch:Result:='OpBranch'; + OpBranchConditional:Result:='OpBranchConditional'; + OpSwitch:Result:='OpSwitch'; + OpKill:Result:='OpKill'; + OpReturn:Result:='OpReturn'; + OpReturnValue:Result:='OpReturnValue'; + OpUnreachable:Result:='OpUnreachable'; + OpLifetimeStart:Result:='OpLifetimeStart'; + OpLifetimeStop:Result:='OpLifetimeStop'; + OpGroupAsyncCopy:Result:='OpGroupAsyncCopy'; + OpGroupWaitEvents:Result:='OpGroupWaitEvents'; + OpGroupAll:Result:='OpGroupAll'; + OpGroupAny:Result:='OpGroupAny'; + OpGroupBroadcast:Result:='OpGroupBroadcast'; + OpGroupIAdd:Result:='OpGroupIAdd'; + OpGroupFAdd:Result:='OpGroupFAdd'; + OpGroupFMin:Result:='OpGroupFMin'; + OpGroupUMin:Result:='OpGroupUMin'; + OpGroupSMin:Result:='OpGroupSMin'; + OpGroupFMax:Result:='OpGroupFMax'; + OpGroupUMax:Result:='OpGroupUMax'; + OpGroupSMax:Result:='OpGroupSMax'; + OpReadPipe:Result:='OpReadPipe'; + OpWritePipe:Result:='OpWritePipe'; + OpReservedReadPipe:Result:='OpReservedReadPipe'; + OpReservedWritePipe:Result:='OpReservedWritePipe'; + OpReserveReadPipePackets:Result:='OpReserveReadPipePackets'; + OpReserveWritePipePackets:Result:='OpReserveWritePipePackets'; + OpCommitReadPipe:Result:='OpCommitReadPipe'; + OpCommitWritePipe:Result:='OpCommitWritePipe'; + OpIsValidReserveId:Result:='OpIsValidReserveId'; + OpGetNumPipePackets:Result:='OpGetNumPipePackets'; + OpGetMaxPipePackets:Result:='OpGetMaxPipePackets'; + OpGroupReserveReadPipePackets:Result:='OpGroupReserveReadPipePackets'; + OpGroupReserveWritePipePackets:Result:='OpGroupReserveWritePipePackets'; + OpGroupCommitReadPipe:Result:='OpGroupCommitReadPipe'; + OpGroupCommitWritePipe:Result:='OpGroupCommitWritePipe'; + OpEnqueueMarker:Result:='OpEnqueueMarker'; + OpEnqueueKernel:Result:='OpEnqueueKernel'; + OpGetKernelNDrangeSubGroupCount:Result:='OpGetKernelNDrangeSubGroupCount'; + OpGetKernelNDrangeMaxSubGroupSize:Result:='OpGetKernelNDrangeMaxSubGroupSize'; + OpGetKernelWorkGroupSize:Result:='OpGetKernelWorkGroupSize'; + OpGetKernelPreferredWorkGroupSizeMultiple:Result:='OpGetKernelPreferredWorkGroupSizeMultiple'; + OpRetainEvent:Result:='OpRetainEvent'; + OpReleaseEvent:Result:='OpReleaseEvent'; + OpCreateUserEvent:Result:='OpCreateUserEvent'; + OpIsValidEvent:Result:='OpIsValidEvent'; + OpSetUserEventStatus:Result:='OpSetUserEventStatus'; + OpCaptureEventProfilingInfo:Result:='OpCaptureEventProfilingInfo'; + OpGetDefaultQueue:Result:='OpGetDefaultQueue'; + OpBuildNDRange:Result:='OpBuildNDRange'; + OpImageSparseSampleImplicitLod:Result:='OpImageSparseSampleImplicitLod'; + OpImageSparseSampleExplicitLod:Result:='OpImageSparseSampleExplicitLod'; + OpImageSparseSampleDrefImplicitLod:Result:='OpImageSparseSampleDrefImplicitLod'; + OpImageSparseSampleDrefExplicitLod:Result:='OpImageSparseSampleDrefExplicitLod'; + OpImageSparseSampleProjImplicitLod:Result:='OpImageSparseSampleProjImplicitLod'; + OpImageSparseSampleProjExplicitLod:Result:='OpImageSparseSampleProjExplicitLod'; + OpImageSparseSampleProjDrefImplicitLod:Result:='OpImageSparseSampleProjDrefImplicitLod'; + OpImageSparseSampleProjDrefExplicitLod:Result:='OpImageSparseSampleProjDrefExplicitLod'; + OpImageSparseFetch:Result:='OpImageSparseFetch'; + OpImageSparseGather:Result:='OpImageSparseGather'; + OpImageSparseDrefGather:Result:='OpImageSparseDrefGather'; + OpImageSparseTexelsResident:Result:='OpImageSparseTexelsResident'; + OpNoLine:Result:='OpNoLine'; + OpAtomicFlagTestAndSet:Result:='OpAtomicFlagTestAndSet'; + OpAtomicFlagClear:Result:='OpAtomicFlagClear'; + OpImageSparseRead:Result:='OpImageSparseRead'; + OpSizeOf:Result:='OpSizeOf'; + OpTypePipeStorage:Result:='OpTypePipeStorage'; + OpConstantPipeStorage:Result:='OpConstantPipeStorage'; + OpCreatePipeFromPipeStorage:Result:='OpCreatePipeFromPipeStorage'; + OpGetKernelLocalSizeForSubgroupCount:Result:='OpGetKernelLocalSizeForSubgroupCount'; + OpGetKernelMaxNumSubgroups:Result:='OpGetKernelMaxNumSubgroups'; + OpTypeNamedBarrier:Result:='OpTypeNamedBarrier'; + OpNamedBarrierInitialize:Result:='OpNamedBarrierInitialize'; + OpMemoryNamedBarrier:Result:='OpMemoryNamedBarrier'; + OpModuleProcessed:Result:='OpModuleProcessed'; + OpExecutionModeId:Result:='OpExecutionModeId'; + OpDecorateId:Result:='OpDecorateId'; + OpGroupNonUniformElect:Result:='OpGroupNonUniformElect'; + OpGroupNonUniformAll:Result:='OpGroupNonUniformAll'; + OpGroupNonUniformAny:Result:='OpGroupNonUniformAny'; + OpGroupNonUniformAllEqual:Result:='OpGroupNonUniformAllEqual'; + OpGroupNonUniformBroadcast:Result:='OpGroupNonUniformBroadcast'; + OpGroupNonUniformBroadcastFirst:Result:='OpGroupNonUniformBroadcastFirst'; + OpGroupNonUniformBallot:Result:='OpGroupNonUniformBallot'; + OpGroupNonUniformInverseBallot:Result:='OpGroupNonUniformInverseBallot'; + OpGroupNonUniformBallotBitExtract:Result:='OpGroupNonUniformBallotBitExtract'; + OpGroupNonUniformBallotBitCount:Result:='OpGroupNonUniformBallotBitCount'; + OpGroupNonUniformBallotFindLSB:Result:='OpGroupNonUniformBallotFindLSB'; + OpGroupNonUniformBallotFindMSB:Result:='OpGroupNonUniformBallotFindMSB'; + OpGroupNonUniformShuffle:Result:='OpGroupNonUniformShuffle'; + OpGroupNonUniformShuffleXor:Result:='OpGroupNonUniformShuffleXor'; + OpGroupNonUniformShuffleUp:Result:='OpGroupNonUniformShuffleUp'; + OpGroupNonUniformShuffleDown:Result:='OpGroupNonUniformShuffleDown'; + OpGroupNonUniformIAdd:Result:='OpGroupNonUniformIAdd'; + OpGroupNonUniformFAdd:Result:='OpGroupNonUniformFAdd'; + OpGroupNonUniformIMul:Result:='OpGroupNonUniformIMul'; + OpGroupNonUniformFMul:Result:='OpGroupNonUniformFMul'; + OpGroupNonUniformSMin:Result:='OpGroupNonUniformSMin'; + OpGroupNonUniformUMin:Result:='OpGroupNonUniformUMin'; + OpGroupNonUniformFMin:Result:='OpGroupNonUniformFMin'; + OpGroupNonUniformSMax:Result:='OpGroupNonUniformSMax'; + OpGroupNonUniformUMax:Result:='OpGroupNonUniformUMax'; + OpGroupNonUniformFMax:Result:='OpGroupNonUniformFMax'; + OpGroupNonUniformBitwiseAnd:Result:='OpGroupNonUniformBitwiseAnd'; + OpGroupNonUniformBitwiseOr:Result:='OpGroupNonUniformBitwiseOr'; + OpGroupNonUniformBitwiseXor:Result:='OpGroupNonUniformBitwiseXor'; + OpGroupNonUniformLogicalAnd:Result:='OpGroupNonUniformLogicalAnd'; + OpGroupNonUniformLogicalOr:Result:='OpGroupNonUniformLogicalOr'; + OpGroupNonUniformLogicalXor:Result:='OpGroupNonUniformLogicalXor'; + OpGroupNonUniformQuadBroadcast:Result:='OpGroupNonUniformQuadBroadcast'; + OpGroupNonUniformQuadSwap:Result:='OpGroupNonUniformQuadSwap'; + OpCopyLogical:Result:='OpCopyLogical'; + OpPtrEqual:Result:='OpPtrEqual'; + OpPtrNotEqual:Result:='OpPtrNotEqual'; + OpPtrDiff:Result:='OpPtrDiff'; + OpTerminateInvocation:Result:='OpTerminateInvocation'; + OpSubgroupBallotKHR:Result:='OpSubgroupBallotKHR'; + OpSubgroupFirstInvocationKHR:Result:='OpSubgroupFirstInvocationKHR'; + OpSubgroupAllKHR:Result:='OpSubgroupAllKHR'; + OpSubgroupAnyKHR:Result:='OpSubgroupAnyKHR'; + OpSubgroupAllEqualKHR:Result:='OpSubgroupAllEqualKHR'; + OpSubgroupReadInvocationKHR:Result:='OpSubgroupReadInvocationKHR'; + OpTraceRayKHR:Result:='OpTraceRayKHR'; + OpExecuteCallableKHR:Result:='OpExecuteCallableKHR'; + OpConvertUToAccelerationStructureKHR:Result:='OpConvertUToAccelerationStructureKHR'; + OpIgnoreIntersectionKHR:Result:='OpIgnoreIntersectionKHR'; + OpTerminateRayKHR:Result:='OpTerminateRayKHR'; + OpSDot:Result:='OpSDot'; + OpUDot:Result:='OpUDot'; + OpSUDot:Result:='OpSUDot'; + OpSDotAccSat:Result:='OpSDotAccSat'; + OpUDotAccSat:Result:='OpUDotAccSat'; + OpSUDotAccSat:Result:='OpSUDotAccSat'; + OpTypeRayQueryKHR:Result:='OpTypeRayQueryKHR'; + OpRayQueryInitializeKHR:Result:='OpRayQueryInitializeKHR'; + OpRayQueryTerminateKHR:Result:='OpRayQueryTerminateKHR'; + OpRayQueryGenerateIntersectionKHR:Result:='OpRayQueryGenerateIntersectionKHR'; + OpRayQueryConfirmIntersectionKHR:Result:='OpRayQueryConfirmIntersectionKHR'; + OpRayQueryProceedKHR:Result:='OpRayQueryProceedKHR'; + OpRayQueryGetIntersectionTypeKHR:Result:='OpRayQueryGetIntersectionTypeKHR'; + OpGroupIAddNonUniformAMD:Result:='OpGroupIAddNonUniformAMD'; + OpGroupFAddNonUniformAMD:Result:='OpGroupFAddNonUniformAMD'; + OpGroupFMinNonUniformAMD:Result:='OpGroupFMinNonUniformAMD'; + OpGroupUMinNonUniformAMD:Result:='OpGroupUMinNonUniformAMD'; + OpGroupSMinNonUniformAMD:Result:='OpGroupSMinNonUniformAMD'; + OpGroupFMaxNonUniformAMD:Result:='OpGroupFMaxNonUniformAMD'; + OpGroupUMaxNonUniformAMD:Result:='OpGroupUMaxNonUniformAMD'; + OpGroupSMaxNonUniformAMD:Result:='OpGroupSMaxNonUniformAMD'; + OpFragmentMaskFetchAMD:Result:='OpFragmentMaskFetchAMD'; + OpFragmentFetchAMD:Result:='OpFragmentFetchAMD'; + OpReadClockKHR:Result:='OpReadClockKHR'; + OpImageSampleFootprintNV:Result:='OpImageSampleFootprintNV'; + OpGroupNonUniformPartitionNV:Result:='OpGroupNonUniformPartitionNV'; + OpWritePackedPrimitiveIndices4x8NV:Result:='OpWritePackedPrimitiveIndices4x8NV'; + OpReportIntersectionKHR:Result:='OpReportIntersectionKHR'; + OpIgnoreIntersectionNV:Result:='OpIgnoreIntersectionNV'; + OpTerminateRayNV:Result:='OpTerminateRayNV'; + OpTraceNV:Result:='OpTraceNV'; + OpTraceMotionNV:Result:='OpTraceMotionNV'; + OpTraceRayMotionNV:Result:='OpTraceRayMotionNV'; + OpTypeAccelerationStructureKHR:Result:='OpTypeAccelerationStructureKHR'; + OpExecuteCallableNV:Result:='OpExecuteCallableNV'; + OpTypeCooperativeMatrixNV:Result:='OpTypeCooperativeMatrixNV'; + OpCooperativeMatrixLoadNV:Result:='OpCooperativeMatrixLoadNV'; + OpCooperativeMatrixStoreNV:Result:='OpCooperativeMatrixStoreNV'; + OpCooperativeMatrixMulAddNV:Result:='OpCooperativeMatrixMulAddNV'; + OpCooperativeMatrixLengthNV:Result:='OpCooperativeMatrixLengthNV'; + OpBeginInvocationInterlockEXT:Result:='OpBeginInvocationInterlockEXT'; + OpEndInvocationInterlockEXT:Result:='OpEndInvocationInterlockEXT'; + OpDemoteToHelperInvocation:Result:='OpDemoteToHelperInvocation'; + OpIsHelperInvocationEXT:Result:='OpIsHelperInvocationEXT'; + OpConvertUToImageNV:Result:='OpConvertUToImageNV'; + OpConvertUToSamplerNV:Result:='OpConvertUToSamplerNV'; + OpConvertImageToUNV:Result:='OpConvertImageToUNV'; + OpConvertSamplerToUNV:Result:='OpConvertSamplerToUNV'; + OpConvertUToSampledImageNV:Result:='OpConvertUToSampledImageNV'; + OpConvertSampledImageToUNV:Result:='OpConvertSampledImageToUNV'; + OpSamplerImageAddressingModeNV:Result:='OpSamplerImageAddressingModeNV'; + OpSubgroupShuffleINTEL:Result:='OpSubgroupShuffleINTEL'; + OpSubgroupShuffleDownINTEL:Result:='OpSubgroupShuffleDownINTEL'; + OpSubgroupShuffleUpINTEL:Result:='OpSubgroupShuffleUpINTEL'; + OpSubgroupShuffleXorINTEL:Result:='OpSubgroupShuffleXorINTEL'; + OpSubgroupBlockReadINTEL:Result:='OpSubgroupBlockReadINTEL'; + OpSubgroupBlockWriteINTEL:Result:='OpSubgroupBlockWriteINTEL'; + OpSubgroupImageBlockReadINTEL:Result:='OpSubgroupImageBlockReadINTEL'; + OpSubgroupImageBlockWriteINTEL:Result:='OpSubgroupImageBlockWriteINTEL'; + OpSubgroupImageMediaBlockReadINTEL:Result:='OpSubgroupImageMediaBlockReadINTEL'; + OpSubgroupImageMediaBlockWriteINTEL:Result:='OpSubgroupImageMediaBlockWriteINTEL'; + OpUCountLeadingZerosINTEL:Result:='OpUCountLeadingZerosINTEL'; + OpUCountTrailingZerosINTEL:Result:='OpUCountTrailingZerosINTEL'; + OpAbsISubINTEL:Result:='OpAbsISubINTEL'; + OpAbsUSubINTEL:Result:='OpAbsUSubINTEL'; + OpIAddSatINTEL:Result:='OpIAddSatINTEL'; + OpUAddSatINTEL:Result:='OpUAddSatINTEL'; + OpIAverageINTEL:Result:='OpIAverageINTEL'; + OpUAverageINTEL:Result:='OpUAverageINTEL'; + OpIAverageRoundedINTEL:Result:='OpIAverageRoundedINTEL'; + OpUAverageRoundedINTEL:Result:='OpUAverageRoundedINTEL'; + OpISubSatINTEL:Result:='OpISubSatINTEL'; + OpUSubSatINTEL:Result:='OpUSubSatINTEL'; + OpIMul32x16INTEL:Result:='OpIMul32x16INTEL'; + OpUMul32x16INTEL:Result:='OpUMul32x16INTEL'; + OpConstantFunctionPointerINTEL:Result:='OpConstantFunctionPointerINTEL'; + OpFunctionPointerCallINTEL:Result:='OpFunctionPointerCallINTEL'; + OpAsmTargetINTEL:Result:='OpAsmTargetINTEL'; + OpAsmINTEL:Result:='OpAsmINTEL'; + OpAsmCallINTEL:Result:='OpAsmCallINTEL'; + OpAtomicFMinEXT:Result:='OpAtomicFMinEXT'; + OpAtomicFMaxEXT:Result:='OpAtomicFMaxEXT'; + OpAssumeTrueKHR:Result:='OpAssumeTrueKHR'; + OpExpectKHR:Result:='OpExpectKHR'; + OpDecorateString:Result:='OpDecorateString'; + OpMemberDecorateString:Result:='OpMemberDecorateString'; + OpVmeImageINTEL:Result:='OpVmeImageINTEL'; + OpTypeVmeImageINTEL:Result:='OpTypeVmeImageINTEL'; + OpTypeAvcImePayloadINTEL:Result:='OpTypeAvcImePayloadINTEL'; + OpTypeAvcRefPayloadINTEL:Result:='OpTypeAvcRefPayloadINTEL'; + OpTypeAvcSicPayloadINTEL:Result:='OpTypeAvcSicPayloadINTEL'; + OpTypeAvcMcePayloadINTEL:Result:='OpTypeAvcMcePayloadINTEL'; + OpTypeAvcMceResultINTEL:Result:='OpTypeAvcMceResultINTEL'; + OpTypeAvcImeResultINTEL:Result:='OpTypeAvcImeResultINTEL'; + OpTypeAvcImeResultSingleReferenceStreamoutINTEL:Result:='OpTypeAvcImeResultSingleReferenceStreamoutINTEL'; + OpTypeAvcImeResultDualReferenceStreamoutINTEL:Result:='OpTypeAvcImeResultDualReferenceStreamoutINTEL'; + OpTypeAvcImeSingleReferenceStreaminINTEL:Result:='OpTypeAvcImeSingleReferenceStreaminINTEL'; + OpTypeAvcImeDualReferenceStreaminINTEL:Result:='OpTypeAvcImeDualReferenceStreaminINTEL'; + OpTypeAvcRefResultINTEL:Result:='OpTypeAvcRefResultINTEL'; + OpTypeAvcSicResultINTEL:Result:='OpTypeAvcSicResultINTEL'; + OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL:Result:='OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL'; + OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL:Result:='OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL'; + OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL:Result:='OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL'; + OpSubgroupAvcMceSetInterShapePenaltyINTEL:Result:='OpSubgroupAvcMceSetInterShapePenaltyINTEL'; + OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL:Result:='OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL'; + OpSubgroupAvcMceSetInterDirectionPenaltyINTEL:Result:='OpSubgroupAvcMceSetInterDirectionPenaltyINTEL'; + OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL:Result:='OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL'; + OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL:Result:='OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL'; + OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL:Result:='OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL'; + OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL:Result:='OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL'; + OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL:Result:='OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL'; + OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL:Result:='OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL'; + OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL:Result:='OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL'; + OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL:Result:='OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL'; + OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL:Result:='OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL'; + OpSubgroupAvcMceSetAcOnlyHaarINTEL:Result:='OpSubgroupAvcMceSetAcOnlyHaarINTEL'; + OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL:Result:='OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL'; + OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL:Result:='OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL'; + OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL:Result:='OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL'; + OpSubgroupAvcMceConvertToImePayloadINTEL:Result:='OpSubgroupAvcMceConvertToImePayloadINTEL'; + OpSubgroupAvcMceConvertToImeResultINTEL:Result:='OpSubgroupAvcMceConvertToImeResultINTEL'; + OpSubgroupAvcMceConvertToRefPayloadINTEL:Result:='OpSubgroupAvcMceConvertToRefPayloadINTEL'; + OpSubgroupAvcMceConvertToRefResultINTEL:Result:='OpSubgroupAvcMceConvertToRefResultINTEL'; + OpSubgroupAvcMceConvertToSicPayloadINTEL:Result:='OpSubgroupAvcMceConvertToSicPayloadINTEL'; + OpSubgroupAvcMceConvertToSicResultINTEL:Result:='OpSubgroupAvcMceConvertToSicResultINTEL'; + OpSubgroupAvcMceGetMotionVectorsINTEL:Result:='OpSubgroupAvcMceGetMotionVectorsINTEL'; + OpSubgroupAvcMceGetInterDistortionsINTEL:Result:='OpSubgroupAvcMceGetInterDistortionsINTEL'; + OpSubgroupAvcMceGetBestInterDistortionsINTEL:Result:='OpSubgroupAvcMceGetBestInterDistortionsINTEL'; + OpSubgroupAvcMceGetInterMajorShapeINTEL:Result:='OpSubgroupAvcMceGetInterMajorShapeINTEL'; + OpSubgroupAvcMceGetInterMinorShapeINTEL:Result:='OpSubgroupAvcMceGetInterMinorShapeINTEL'; + OpSubgroupAvcMceGetInterDirectionsINTEL:Result:='OpSubgroupAvcMceGetInterDirectionsINTEL'; + OpSubgroupAvcMceGetInterMotionVectorCountINTEL:Result:='OpSubgroupAvcMceGetInterMotionVectorCountINTEL'; + OpSubgroupAvcMceGetInterReferenceIdsINTEL:Result:='OpSubgroupAvcMceGetInterReferenceIdsINTEL'; + OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL:Result:='OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL'; + OpSubgroupAvcImeInitializeINTEL:Result:='OpSubgroupAvcImeInitializeINTEL'; + OpSubgroupAvcImeSetSingleReferenceINTEL:Result:='OpSubgroupAvcImeSetSingleReferenceINTEL'; + OpSubgroupAvcImeSetDualReferenceINTEL:Result:='OpSubgroupAvcImeSetDualReferenceINTEL'; + OpSubgroupAvcImeRefWindowSizeINTEL:Result:='OpSubgroupAvcImeRefWindowSizeINTEL'; + OpSubgroupAvcImeAdjustRefOffsetINTEL:Result:='OpSubgroupAvcImeAdjustRefOffsetINTEL'; + OpSubgroupAvcImeConvertToMcePayloadINTEL:Result:='OpSubgroupAvcImeConvertToMcePayloadINTEL'; + OpSubgroupAvcImeSetMaxMotionVectorCountINTEL:Result:='OpSubgroupAvcImeSetMaxMotionVectorCountINTEL'; + OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL:Result:='OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL'; + OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL:Result:='OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL'; + OpSubgroupAvcImeSetWeightedSadINTEL:Result:='OpSubgroupAvcImeSetWeightedSadINTEL'; + OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL:Result:='OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL'; + OpSubgroupAvcImeEvaluateWithDualReferenceINTEL:Result:='OpSubgroupAvcImeEvaluateWithDualReferenceINTEL'; + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL:Result:='OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL'; + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL:Result:='OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL'; + OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL:Result:='OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL'; + OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL:Result:='OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL'; + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL:Result:='OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL'; + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL:Result:='OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL'; + OpSubgroupAvcImeConvertToMceResultINTEL:Result:='OpSubgroupAvcImeConvertToMceResultINTEL'; + OpSubgroupAvcImeGetSingleReferenceStreaminINTEL:Result:='OpSubgroupAvcImeGetSingleReferenceStreaminINTEL'; + OpSubgroupAvcImeGetDualReferenceStreaminINTEL:Result:='OpSubgroupAvcImeGetDualReferenceStreaminINTEL'; + OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL:Result:='OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL'; + OpSubgroupAvcImeStripDualReferenceStreamoutINTEL:Result:='OpSubgroupAvcImeStripDualReferenceStreamoutINTEL'; + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL:Result:='OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL'; + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL:Result:='OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL'; + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL:Result:='OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL'; + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL:Result:='OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL'; + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL:Result:='OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL'; + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL:Result:='OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL'; + OpSubgroupAvcImeGetBorderReachedINTEL:Result:='OpSubgroupAvcImeGetBorderReachedINTEL'; + OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL:Result:='OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL'; + OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL:Result:='OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL'; + OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL:Result:='OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL'; + OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL:Result:='OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL'; + OpSubgroupAvcFmeInitializeINTEL:Result:='OpSubgroupAvcFmeInitializeINTEL'; + OpSubgroupAvcBmeInitializeINTEL:Result:='OpSubgroupAvcBmeInitializeINTEL'; + OpSubgroupAvcRefConvertToMcePayloadINTEL:Result:='OpSubgroupAvcRefConvertToMcePayloadINTEL'; + OpSubgroupAvcRefSetBidirectionalMixDisableINTEL:Result:='OpSubgroupAvcRefSetBidirectionalMixDisableINTEL'; + OpSubgroupAvcRefSetBilinearFilterEnableINTEL:Result:='OpSubgroupAvcRefSetBilinearFilterEnableINTEL'; + OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL:Result:='OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL'; + OpSubgroupAvcRefEvaluateWithDualReferenceINTEL:Result:='OpSubgroupAvcRefEvaluateWithDualReferenceINTEL'; + OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL:Result:='OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL'; + OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL:Result:='OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL'; + OpSubgroupAvcRefConvertToMceResultINTEL:Result:='OpSubgroupAvcRefConvertToMceResultINTEL'; + OpSubgroupAvcSicInitializeINTEL:Result:='OpSubgroupAvcSicInitializeINTEL'; + OpSubgroupAvcSicConfigureSkcINTEL:Result:='OpSubgroupAvcSicConfigureSkcINTEL'; + OpSubgroupAvcSicConfigureIpeLumaINTEL:Result:='OpSubgroupAvcSicConfigureIpeLumaINTEL'; + OpSubgroupAvcSicConfigureIpeLumaChromaINTEL:Result:='OpSubgroupAvcSicConfigureIpeLumaChromaINTEL'; + OpSubgroupAvcSicGetMotionVectorMaskINTEL:Result:='OpSubgroupAvcSicGetMotionVectorMaskINTEL'; + OpSubgroupAvcSicConvertToMcePayloadINTEL:Result:='OpSubgroupAvcSicConvertToMcePayloadINTEL'; + OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL:Result:='OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL'; + OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL:Result:='OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL'; + OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL:Result:='OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL'; + OpSubgroupAvcSicSetBilinearFilterEnableINTEL:Result:='OpSubgroupAvcSicSetBilinearFilterEnableINTEL'; + OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL:Result:='OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL'; + OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL:Result:='OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL'; + OpSubgroupAvcSicEvaluateIpeINTEL:Result:='OpSubgroupAvcSicEvaluateIpeINTEL'; + OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL:Result:='OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL'; + OpSubgroupAvcSicEvaluateWithDualReferenceINTEL:Result:='OpSubgroupAvcSicEvaluateWithDualReferenceINTEL'; + OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL:Result:='OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL'; + OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL:Result:='OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL'; + OpSubgroupAvcSicConvertToMceResultINTEL:Result:='OpSubgroupAvcSicConvertToMceResultINTEL'; + OpSubgroupAvcSicGetIpeLumaShapeINTEL:Result:='OpSubgroupAvcSicGetIpeLumaShapeINTEL'; + OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL:Result:='OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL'; + OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL:Result:='OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL'; + OpSubgroupAvcSicGetPackedIpeLumaModesINTEL:Result:='OpSubgroupAvcSicGetPackedIpeLumaModesINTEL'; + OpSubgroupAvcSicGetIpeChromaModeINTEL:Result:='OpSubgroupAvcSicGetIpeChromaModeINTEL'; + OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL:Result:='OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL'; + OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL:Result:='OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL'; + OpSubgroupAvcSicGetInterRawSadsINTEL:Result:='OpSubgroupAvcSicGetInterRawSadsINTEL'; + OpVariableLengthArrayINTEL:Result:='OpVariableLengthArrayINTEL'; + OpSaveMemoryINTEL:Result:='OpSaveMemoryINTEL'; + OpRestoreMemoryINTEL:Result:='OpRestoreMemoryINTEL'; + OpArbitraryFloatSinCosPiINTEL:Result:='OpArbitraryFloatSinCosPiINTEL'; + OpArbitraryFloatCastINTEL:Result:='OpArbitraryFloatCastINTEL'; + OpArbitraryFloatCastFromIntINTEL:Result:='OpArbitraryFloatCastFromIntINTEL'; + OpArbitraryFloatCastToIntINTEL:Result:='OpArbitraryFloatCastToIntINTEL'; + OpArbitraryFloatAddINTEL:Result:='OpArbitraryFloatAddINTEL'; + OpArbitraryFloatSubINTEL:Result:='OpArbitraryFloatSubINTEL'; + OpArbitraryFloatMulINTEL:Result:='OpArbitraryFloatMulINTEL'; + OpArbitraryFloatDivINTEL:Result:='OpArbitraryFloatDivINTEL'; + OpArbitraryFloatGTINTEL:Result:='OpArbitraryFloatGTINTEL'; + OpArbitraryFloatGEINTEL:Result:='OpArbitraryFloatGEINTEL'; + OpArbitraryFloatLTINTEL:Result:='OpArbitraryFloatLTINTEL'; + OpArbitraryFloatLEINTEL:Result:='OpArbitraryFloatLEINTEL'; + OpArbitraryFloatEQINTEL:Result:='OpArbitraryFloatEQINTEL'; + OpArbitraryFloatRecipINTEL:Result:='OpArbitraryFloatRecipINTEL'; + OpArbitraryFloatRSqrtINTEL:Result:='OpArbitraryFloatRSqrtINTEL'; + OpArbitraryFloatCbrtINTEL:Result:='OpArbitraryFloatCbrtINTEL'; + OpArbitraryFloatHypotINTEL:Result:='OpArbitraryFloatHypotINTEL'; + OpArbitraryFloatSqrtINTEL:Result:='OpArbitraryFloatSqrtINTEL'; + OpArbitraryFloatLogINTEL:Result:='OpArbitraryFloatLogINTEL'; + OpArbitraryFloatLog2INTEL:Result:='OpArbitraryFloatLog2INTEL'; + OpArbitraryFloatLog10INTEL:Result:='OpArbitraryFloatLog10INTEL'; + OpArbitraryFloatLog1pINTEL:Result:='OpArbitraryFloatLog1pINTEL'; + OpArbitraryFloatExpINTEL:Result:='OpArbitraryFloatExpINTEL'; + OpArbitraryFloatExp2INTEL:Result:='OpArbitraryFloatExp2INTEL'; + OpArbitraryFloatExp10INTEL:Result:='OpArbitraryFloatExp10INTEL'; + OpArbitraryFloatExpm1INTEL:Result:='OpArbitraryFloatExpm1INTEL'; + OpArbitraryFloatSinINTEL:Result:='OpArbitraryFloatSinINTEL'; + OpArbitraryFloatCosINTEL:Result:='OpArbitraryFloatCosINTEL'; + OpArbitraryFloatSinCosINTEL:Result:='OpArbitraryFloatSinCosINTEL'; + OpArbitraryFloatSinPiINTEL:Result:='OpArbitraryFloatSinPiINTEL'; + OpArbitraryFloatCosPiINTEL:Result:='OpArbitraryFloatCosPiINTEL'; + OpArbitraryFloatASinINTEL:Result:='OpArbitraryFloatASinINTEL'; + OpArbitraryFloatASinPiINTEL:Result:='OpArbitraryFloatASinPiINTEL'; + OpArbitraryFloatACosINTEL:Result:='OpArbitraryFloatACosINTEL'; + OpArbitraryFloatACosPiINTEL:Result:='OpArbitraryFloatACosPiINTEL'; + OpArbitraryFloatATanINTEL:Result:='OpArbitraryFloatATanINTEL'; + OpArbitraryFloatATanPiINTEL:Result:='OpArbitraryFloatATanPiINTEL'; + OpArbitraryFloatATan2INTEL:Result:='OpArbitraryFloatATan2INTEL'; + OpArbitraryFloatPowINTEL:Result:='OpArbitraryFloatPowINTEL'; + OpArbitraryFloatPowRINTEL:Result:='OpArbitraryFloatPowRINTEL'; + OpArbitraryFloatPowNINTEL:Result:='OpArbitraryFloatPowNINTEL'; + OpLoopControlINTEL:Result:='OpLoopControlINTEL'; + OpFixedSqrtINTEL:Result:='OpFixedSqrtINTEL'; + OpFixedRecipINTEL:Result:='OpFixedRecipINTEL'; + OpFixedRsqrtINTEL:Result:='OpFixedRsqrtINTEL'; + OpFixedSinINTEL:Result:='OpFixedSinINTEL'; + OpFixedCosINTEL:Result:='OpFixedCosINTEL'; + OpFixedSinCosINTEL:Result:='OpFixedSinCosINTEL'; + OpFixedSinPiINTEL:Result:='OpFixedSinPiINTEL'; + OpFixedCosPiINTEL:Result:='OpFixedCosPiINTEL'; + OpFixedSinCosPiINTEL:Result:='OpFixedSinCosPiINTEL'; + OpFixedLogINTEL:Result:='OpFixedLogINTEL'; + OpFixedExpINTEL:Result:='OpFixedExpINTEL'; + OpPtrCastToCrossWorkgroupINTEL:Result:='OpPtrCastToCrossWorkgroupINTEL'; + OpCrossWorkgroupCastToPtrINTEL:Result:='OpCrossWorkgroupCastToPtrINTEL'; + OpReadPipeBlockingINTEL:Result:='OpReadPipeBlockingINTEL'; + OpWritePipeBlockingINTEL:Result:='OpWritePipeBlockingINTEL'; + OpFPGARegINTEL:Result:='OpFPGARegINTEL'; + OpRayQueryGetRayTMinKHR:Result:='OpRayQueryGetRayTMinKHR'; + OpRayQueryGetRayFlagsKHR:Result:='OpRayQueryGetRayFlagsKHR'; + OpRayQueryGetIntersectionTKHR:Result:='OpRayQueryGetIntersectionTKHR'; + OpRayQueryGetIntersectionInstanceCustomIndexKHR:Result:='OpRayQueryGetIntersectionInstanceCustomIndexKHR'; + OpRayQueryGetIntersectionInstanceIdKHR:Result:='OpRayQueryGetIntersectionInstanceIdKHR'; + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR:Result:='OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR'; + OpRayQueryGetIntersectionGeometryIndexKHR:Result:='OpRayQueryGetIntersectionGeometryIndexKHR'; + OpRayQueryGetIntersectionPrimitiveIndexKHR:Result:='OpRayQueryGetIntersectionPrimitiveIndexKHR'; + OpRayQueryGetIntersectionBarycentricsKHR:Result:='OpRayQueryGetIntersectionBarycentricsKHR'; + OpRayQueryGetIntersectionFrontFaceKHR:Result:='OpRayQueryGetIntersectionFrontFaceKHR'; + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR:Result:='OpRayQueryGetIntersectionCandidateAABBOpaqueKHR'; + OpRayQueryGetIntersectionObjectRayDirectionKHR:Result:='OpRayQueryGetIntersectionObjectRayDirectionKHR'; + OpRayQueryGetIntersectionObjectRayOriginKHR:Result:='OpRayQueryGetIntersectionObjectRayOriginKHR'; + OpRayQueryGetWorldRayDirectionKHR:Result:='OpRayQueryGetWorldRayDirectionKHR'; + OpRayQueryGetWorldRayOriginKHR:Result:='OpRayQueryGetWorldRayOriginKHR'; + OpRayQueryGetIntersectionObjectToWorldKHR:Result:='OpRayQueryGetIntersectionObjectToWorldKHR'; + OpRayQueryGetIntersectionWorldToObjectKHR:Result:='OpRayQueryGetIntersectionWorldToObjectKHR'; + OpAtomicFAddEXT:Result:='OpAtomicFAddEXT'; + OpTypeBufferSurfaceINTEL:Result:='OpTypeBufferSurfaceINTEL'; + OpTypeStructContinuedINTEL:Result:='OpTypeStructContinuedINTEL'; + OpConstantCompositeContinuedINTEL:Result:='OpConstantCompositeContinuedINTEL'; + OpSpecConstantCompositeContinuedINTEL:Result:='OpSpecConstantCompositeContinuedINTEL'; + end; +end; + +function Op.GetInfo(w:Word):TOpInfo; static; +begin + Result:=Default(TOpInfo); + Case w of + OpNop:QWORD(Result):=$0000000000000000; + OpUndef:QWORD(Result):=$0000010100020002; + OpSourceContinued:QWORD(Result):=$0000000000010001; + OpSource:QWORD(Result):=$0000000000040002; + OpSourceExtension:QWORD(Result):=$0000000000010001; + OpName:QWORD(Result):=$0000000000020002; + OpMemberName:QWORD(Result):=$0000000000030003; + OpString:QWORD(Result):=$0000000100020002; + OpLine:QWORD(Result):=$0000000000030003; + OpExtension:QWORD(Result):=$0000000000010001; + OpExtInstImport:QWORD(Result):=$0000000100020002; + OpExtInst:QWORD(Result):=$00000101FFFF0004; + OpMemoryModel:QWORD(Result):=$0000000000020002; + OpEntryPoint:QWORD(Result):=$00000000FFFF0003; + OpExecutionMode:QWORD(Result):=$0000000000020002; + OpCapability:QWORD(Result):=$0000000000010001; + OpTypeVoid:QWORD(Result):=$0000000100010001; + OpTypeBool:QWORD(Result):=$0000000100010001; + OpTypeInt:QWORD(Result):=$0000000100030003; + OpTypeFloat:QWORD(Result):=$0000000100020002; + OpTypeVector:QWORD(Result):=$0000000100030003; + OpTypeMatrix:QWORD(Result):=$0000000100030003; + OpTypeImage:QWORD(Result):=$0000000100090008; + OpTypeSampler:QWORD(Result):=$0000000100010001; + OpTypeSampledImage:QWORD(Result):=$0000000100020002; + OpTypeArray:QWORD(Result):=$0000000100030003; + OpTypeRuntimeArray:QWORD(Result):=$0000000100020002; + OpTypeStruct:QWORD(Result):=$00000001FFFF0001; + OpTypeOpaque:QWORD(Result):=$0000000100020002; + OpTypePointer:QWORD(Result):=$0000000100030003; + OpTypeFunction:QWORD(Result):=$00000001FFFF0002; + OpTypeEvent:QWORD(Result):=$0000000100010001; + OpTypeDeviceEvent:QWORD(Result):=$0000000100010001; + OpTypeReserveId:QWORD(Result):=$0000000100010001; + OpTypeQueue:QWORD(Result):=$0000000100010001; + OpTypePipe:QWORD(Result):=$0000000100020002; + OpTypeForwardPointer:QWORD(Result):=$0000000000020002; + OpConstantTrue:QWORD(Result):=$0000010100020002; + OpConstantFalse:QWORD(Result):=$0000010100020002; + OpConstant:QWORD(Result):=$0000010100030003; + OpConstantComposite:QWORD(Result):=$00000101FFFF0002; + OpConstantSampler:QWORD(Result):=$0000010100050005; + OpConstantNull:QWORD(Result):=$0000010100020002; + OpSpecConstantTrue:QWORD(Result):=$0000010100020002; + OpSpecConstantFalse:QWORD(Result):=$0000010100020002; + OpSpecConstant:QWORD(Result):=$0000010100030003; + OpSpecConstantComposite:QWORD(Result):=$00000101FFFF0002; + OpSpecConstantOp:QWORD(Result):=$0000010100030003; + OpFunction:QWORD(Result):=$0000010100040004; + OpFunctionParameter:QWORD(Result):=$0000010100020002; + OpFunctionEnd:QWORD(Result):=$0000000000000000; + OpFunctionCall:QWORD(Result):=$00000101FFFF0003; + OpVariable:QWORD(Result):=$0000010100040003; + OpImageTexelPointer:QWORD(Result):=$0000010100050005; + OpLoad:QWORD(Result):=$0000010100040003; + OpStore:QWORD(Result):=$0000000000030002; + OpCopyMemory:QWORD(Result):=$0000000000040002; + OpCopyMemorySized:QWORD(Result):=$0000000000050003; + OpAccessChain:QWORD(Result):=$00000101FFFF0003; + OpInBoundsAccessChain:QWORD(Result):=$00000101FFFF0003; + OpPtrAccessChain:QWORD(Result):=$00000101FFFF0004; + OpArrayLength:QWORD(Result):=$0000010100040004; + OpGenericPtrMemSemantics:QWORD(Result):=$0000010100030003; + OpInBoundsPtrAccessChain:QWORD(Result):=$00000101FFFF0004; + OpDecorate:QWORD(Result):=$0000000000020002; + OpMemberDecorate:QWORD(Result):=$0000000000030003; + OpDecorationGroup:QWORD(Result):=$0000000100010001; + OpGroupDecorate:QWORD(Result):=$00000000FFFF0001; + OpGroupMemberDecorate:QWORD(Result):=$00000000FFFF0001; + OpVectorExtractDynamic:QWORD(Result):=$0000010100040004; + OpVectorInsertDynamic:QWORD(Result):=$0000010100050005; + OpVectorShuffle:QWORD(Result):=$00000101FFFF0004; + OpCompositeConstruct:QWORD(Result):=$00000101FFFF0002; + OpCompositeExtract:QWORD(Result):=$00000101FFFF0003; + OpCompositeInsert:QWORD(Result):=$00000101FFFF0004; + OpCopyObject:QWORD(Result):=$0000010100030003; + OpTranspose:QWORD(Result):=$0000010100030003; + OpSampledImage:QWORD(Result):=$0000010100040004; + OpImageSampleImplicitLod:QWORD(Result):=$0000010100050004; + OpImageSampleExplicitLod:QWORD(Result):=$0000010100050005; + OpImageSampleDrefImplicitLod:QWORD(Result):=$0000010100060005; + OpImageSampleDrefExplicitLod:QWORD(Result):=$0000010100060006; + OpImageSampleProjImplicitLod:QWORD(Result):=$0000010100050004; + OpImageSampleProjExplicitLod:QWORD(Result):=$0000010100050005; + OpImageSampleProjDrefImplicitLod:QWORD(Result):=$0000010100060005; + OpImageSampleProjDrefExplicitLod:QWORD(Result):=$0000010100060006; + OpImageFetch:QWORD(Result):=$0000010100050004; + OpImageGather:QWORD(Result):=$0000010100060005; + OpImageDrefGather:QWORD(Result):=$0000010100060005; + OpImageRead:QWORD(Result):=$0000010100050004; + OpImageWrite:QWORD(Result):=$0000000000040003; + OpImage:QWORD(Result):=$0000010100030003; + OpImageQueryFormat:QWORD(Result):=$0000010100030003; + OpImageQueryOrder:QWORD(Result):=$0000010100030003; + OpImageQuerySizeLod:QWORD(Result):=$0000010100040004; + OpImageQuerySize:QWORD(Result):=$0000010100030003; + OpImageQueryLod:QWORD(Result):=$0000010100040004; + OpImageQueryLevels:QWORD(Result):=$0000010100030003; + OpImageQuerySamples:QWORD(Result):=$0000010100030003; + OpConvertFToU:QWORD(Result):=$0000010100030003; + OpConvertFToS:QWORD(Result):=$0000010100030003; + OpConvertSToF:QWORD(Result):=$0000010100030003; + OpConvertUToF:QWORD(Result):=$0000010100030003; + OpUConvert:QWORD(Result):=$0000010100030003; + OpSConvert:QWORD(Result):=$0000010100030003; + OpFConvert:QWORD(Result):=$0000010100030003; + OpQuantizeToF16:QWORD(Result):=$0000010100030003; + OpConvertPtrToU:QWORD(Result):=$0000010100030003; + OpSatConvertSToU:QWORD(Result):=$0000010100030003; + OpSatConvertUToS:QWORD(Result):=$0000010100030003; + OpConvertUToPtr:QWORD(Result):=$0000010100030003; + OpPtrCastToGeneric:QWORD(Result):=$0000010100030003; + OpGenericCastToPtr:QWORD(Result):=$0000010100030003; + OpGenericCastToPtrExplicit:QWORD(Result):=$0000010100040004; + OpBitcast:QWORD(Result):=$0000010100030003; + OpSNegate:QWORD(Result):=$0000010100030003; + OpFNegate:QWORD(Result):=$0000010100030003; + OpIAdd:QWORD(Result):=$0000010100040004; + OpFAdd:QWORD(Result):=$0000010100040004; + OpISub:QWORD(Result):=$0000010100040004; + OpFSub:QWORD(Result):=$0000010100040004; + OpIMul:QWORD(Result):=$0000010100040004; + OpFMul:QWORD(Result):=$0000010100040004; + OpUDiv:QWORD(Result):=$0000010100040004; + OpSDiv:QWORD(Result):=$0000010100040004; + OpFDiv:QWORD(Result):=$0000010100040004; + OpUMod:QWORD(Result):=$0000010100040004; + OpSRem:QWORD(Result):=$0000010100040004; + OpSMod:QWORD(Result):=$0000010100040004; + OpFRem:QWORD(Result):=$0000010100040004; + OpFMod:QWORD(Result):=$0000010100040004; + OpVectorTimesScalar:QWORD(Result):=$0000010100040004; + OpMatrixTimesScalar:QWORD(Result):=$0000010100040004; + OpVectorTimesMatrix:QWORD(Result):=$0000010100040004; + OpMatrixTimesVector:QWORD(Result):=$0000010100040004; + OpMatrixTimesMatrix:QWORD(Result):=$0000010100040004; + OpOuterProduct:QWORD(Result):=$0000010100040004; + OpDot:QWORD(Result):=$0000010100040004; + OpIAddCarry:QWORD(Result):=$0000010100040004; + OpISubBorrow:QWORD(Result):=$0000010100040004; + OpUMulExtended:QWORD(Result):=$0000010100040004; + OpSMulExtended:QWORD(Result):=$0000010100040004; + OpAny:QWORD(Result):=$0000010100030003; + OpAll:QWORD(Result):=$0000010100030003; + OpIsNan:QWORD(Result):=$0000010100030003; + OpIsInf:QWORD(Result):=$0000010100030003; + OpIsFinite:QWORD(Result):=$0000010100030003; + OpIsNormal:QWORD(Result):=$0000010100030003; + OpSignBitSet:QWORD(Result):=$0000010100030003; + OpLessOrGreater:QWORD(Result):=$0000010100040004; + OpOrdered:QWORD(Result):=$0000010100040004; + OpUnordered:QWORD(Result):=$0000010100040004; + OpLogicalEqual:QWORD(Result):=$0000010100040004; + OpLogicalNotEqual:QWORD(Result):=$0000010100040004; + OpLogicalOr:QWORD(Result):=$0000010100040004; + OpLogicalAnd:QWORD(Result):=$0000010100040004; + OpLogicalNot:QWORD(Result):=$0000010100030003; + OpSelect:QWORD(Result):=$0000010100050005; + OpIEqual:QWORD(Result):=$0000010100040004; + OpINotEqual:QWORD(Result):=$0000010100040004; + OpUGreaterThan:QWORD(Result):=$0000010100040004; + OpSGreaterThan:QWORD(Result):=$0000010100040004; + OpUGreaterThanEqual:QWORD(Result):=$0000010100040004; + OpSGreaterThanEqual:QWORD(Result):=$0000010100040004; + OpULessThan:QWORD(Result):=$0000010100040004; + OpSLessThan:QWORD(Result):=$0000010100040004; + OpULessThanEqual:QWORD(Result):=$0000010100040004; + OpSLessThanEqual:QWORD(Result):=$0000010100040004; + OpFOrdEqual:QWORD(Result):=$0000010100040004; + OpFUnordEqual:QWORD(Result):=$0000010100040004; + OpFOrdNotEqual:QWORD(Result):=$0000010100040004; + OpFUnordNotEqual:QWORD(Result):=$0000010100040004; + OpFOrdLessThan:QWORD(Result):=$0000010100040004; + OpFUnordLessThan:QWORD(Result):=$0000010100040004; + OpFOrdGreaterThan:QWORD(Result):=$0000010100040004; + OpFUnordGreaterThan:QWORD(Result):=$0000010100040004; + OpFOrdLessThanEqual:QWORD(Result):=$0000010100040004; + OpFUnordLessThanEqual:QWORD(Result):=$0000010100040004; + OpFOrdGreaterThanEqual:QWORD(Result):=$0000010100040004; + OpFUnordGreaterThanEqual:QWORD(Result):=$0000010100040004; + OpShiftRightLogical:QWORD(Result):=$0000010100040004; + OpShiftRightArithmetic:QWORD(Result):=$0000010100040004; + OpShiftLeftLogical:QWORD(Result):=$0000010100040004; + OpBitwiseOr:QWORD(Result):=$0000010100040004; + OpBitwiseXor:QWORD(Result):=$0000010100040004; + OpBitwiseAnd:QWORD(Result):=$0000010100040004; + OpNot:QWORD(Result):=$0000010100030003; + OpBitFieldInsert:QWORD(Result):=$0000010100060006; + OpBitFieldSExtract:QWORD(Result):=$0000010100050005; + OpBitFieldUExtract:QWORD(Result):=$0000010100050005; + OpBitReverse:QWORD(Result):=$0000010100030003; + OpBitCount:QWORD(Result):=$0000010100030003; + OpDPdx:QWORD(Result):=$0000010100030003; + OpDPdy:QWORD(Result):=$0000010100030003; + OpFwidth:QWORD(Result):=$0000010100030003; + OpDPdxFine:QWORD(Result):=$0000010100030003; + OpDPdyFine:QWORD(Result):=$0000010100030003; + OpFwidthFine:QWORD(Result):=$0000010100030003; + OpDPdxCoarse:QWORD(Result):=$0000010100030003; + OpDPdyCoarse:QWORD(Result):=$0000010100030003; + OpFwidthCoarse:QWORD(Result):=$0000010100030003; + OpEmitVertex:QWORD(Result):=$0000000000000000; + OpEndPrimitive:QWORD(Result):=$0000000000000000; + OpEmitStreamVertex:QWORD(Result):=$0000000000010001; + OpEndStreamPrimitive:QWORD(Result):=$0000000000010001; + OpControlBarrier:QWORD(Result):=$0000000000030003; + OpMemoryBarrier:QWORD(Result):=$0000000000020002; + OpAtomicLoad:QWORD(Result):=$0000010100050005; + OpAtomicStore:QWORD(Result):=$0000000000040004; + OpAtomicExchange:QWORD(Result):=$0000010100060006; + OpAtomicCompareExchange:QWORD(Result):=$0000010100080008; + OpAtomicCompareExchangeWeak:QWORD(Result):=$0000010100080008; + OpAtomicIIncrement:QWORD(Result):=$0000010100050005; + OpAtomicIDecrement:QWORD(Result):=$0000010100050005; + OpAtomicIAdd:QWORD(Result):=$0000010100060006; + OpAtomicISub:QWORD(Result):=$0000010100060006; + OpAtomicSMin:QWORD(Result):=$0000010100060006; + OpAtomicUMin:QWORD(Result):=$0000010100060006; + OpAtomicSMax:QWORD(Result):=$0000010100060006; + OpAtomicUMax:QWORD(Result):=$0000010100060006; + OpAtomicAnd:QWORD(Result):=$0000010100060006; + OpAtomicOr:QWORD(Result):=$0000010100060006; + OpAtomicXor:QWORD(Result):=$0000010100060006; + OpPhi:QWORD(Result):=$00000101FFFF0002; + OpLoopMerge:QWORD(Result):=$0000000000030003; + OpSelectionMerge:QWORD(Result):=$0000000000020002; + OpLabel:QWORD(Result):=$0000000100010001; + OpBranch:QWORD(Result):=$0000000000010001; + OpBranchConditional:QWORD(Result):=$00000000FFFF0003; + OpSwitch:QWORD(Result):=$00000000FFFF0002; + OpKill:QWORD(Result):=$0000000000000000; + OpReturn:QWORD(Result):=$0000000000000000; + OpReturnValue:QWORD(Result):=$0000000000010001; + OpUnreachable:QWORD(Result):=$0000000000000000; + OpLifetimeStart:QWORD(Result):=$0000000000020002; + OpLifetimeStop:QWORD(Result):=$0000000000020002; + OpGroupAsyncCopy:QWORD(Result):=$0000010100080008; + OpGroupWaitEvents:QWORD(Result):=$0000000000030003; + OpGroupAll:QWORD(Result):=$0000010100040004; + OpGroupAny:QWORD(Result):=$0000010100040004; + OpGroupBroadcast:QWORD(Result):=$0000010100050005; + OpGroupIAdd:QWORD(Result):=$0000010100050005; + OpGroupFAdd:QWORD(Result):=$0000010100050005; + OpGroupFMin:QWORD(Result):=$0000010100050005; + OpGroupUMin:QWORD(Result):=$0000010100050005; + OpGroupSMin:QWORD(Result):=$0000010100050005; + OpGroupFMax:QWORD(Result):=$0000010100050005; + OpGroupUMax:QWORD(Result):=$0000010100050005; + OpGroupSMax:QWORD(Result):=$0000010100050005; + OpReadPipe:QWORD(Result):=$0000010100060006; + OpWritePipe:QWORD(Result):=$0000010100060006; + OpReservedReadPipe:QWORD(Result):=$0000010100080008; + OpReservedWritePipe:QWORD(Result):=$0000010100080008; + OpReserveReadPipePackets:QWORD(Result):=$0000010100060006; + OpReserveWritePipePackets:QWORD(Result):=$0000010100060006; + OpCommitReadPipe:QWORD(Result):=$0000000000040004; + OpCommitWritePipe:QWORD(Result):=$0000000000040004; + OpIsValidReserveId:QWORD(Result):=$0000010100030003; + OpGetNumPipePackets:QWORD(Result):=$0000010100050005; + OpGetMaxPipePackets:QWORD(Result):=$0000010100050005; + OpGroupReserveReadPipePackets:QWORD(Result):=$0000010100070007; + OpGroupReserveWritePipePackets:QWORD(Result):=$0000010100070007; + OpGroupCommitReadPipe:QWORD(Result):=$0000000000050005; + OpGroupCommitWritePipe:QWORD(Result):=$0000000000050005; + OpEnqueueMarker:QWORD(Result):=$0000010100060006; + OpEnqueueKernel:QWORD(Result):=$00000101FFFF000C; + OpGetKernelNDrangeSubGroupCount:QWORD(Result):=$0000010100070007; + OpGetKernelNDrangeMaxSubGroupSize:QWORD(Result):=$0000010100070007; + OpGetKernelWorkGroupSize:QWORD(Result):=$0000010100060006; + OpGetKernelPreferredWorkGroupSizeMultiple:QWORD(Result):=$0000010100060006; + OpRetainEvent:QWORD(Result):=$0000000000010001; + OpReleaseEvent:QWORD(Result):=$0000000000010001; + OpCreateUserEvent:QWORD(Result):=$0000010100020002; + OpIsValidEvent:QWORD(Result):=$0000010100030003; + OpSetUserEventStatus:QWORD(Result):=$0000000000020002; + OpCaptureEventProfilingInfo:QWORD(Result):=$0000000000030003; + OpGetDefaultQueue:QWORD(Result):=$0000010100020002; + OpBuildNDRange:QWORD(Result):=$0000010100050005; + OpImageSparseSampleImplicitLod:QWORD(Result):=$0000010100050004; + OpImageSparseSampleExplicitLod:QWORD(Result):=$0000010100050005; + OpImageSparseSampleDrefImplicitLod:QWORD(Result):=$0000010100060005; + OpImageSparseSampleDrefExplicitLod:QWORD(Result):=$0000010100060006; + OpImageSparseSampleProjImplicitLod:QWORD(Result):=$0000010100050004; + OpImageSparseSampleProjExplicitLod:QWORD(Result):=$0000010100050005; + OpImageSparseSampleProjDrefImplicitLod:QWORD(Result):=$0000010100060005; + OpImageSparseSampleProjDrefExplicitLod:QWORD(Result):=$0000010100060006; + OpImageSparseFetch:QWORD(Result):=$0000010100050004; + OpImageSparseGather:QWORD(Result):=$0000010100060005; + OpImageSparseDrefGather:QWORD(Result):=$0000010100060005; + OpImageSparseTexelsResident:QWORD(Result):=$0000010100030003; + OpNoLine:QWORD(Result):=$0000000000000000; + OpAtomicFlagTestAndSet:QWORD(Result):=$0000010100050005; + OpAtomicFlagClear:QWORD(Result):=$0000000000030003; + OpImageSparseRead:QWORD(Result):=$0000010100050004; + OpSizeOf:QWORD(Result):=$0000010100030003; + OpTypePipeStorage:QWORD(Result):=$0000000100010001; + OpConstantPipeStorage:QWORD(Result):=$0000010100050005; + OpCreatePipeFromPipeStorage:QWORD(Result):=$0000010100030003; + OpGetKernelLocalSizeForSubgroupCount:QWORD(Result):=$0000010100070007; + OpGetKernelMaxNumSubgroups:QWORD(Result):=$0000010100060006; + OpTypeNamedBarrier:QWORD(Result):=$0000000100010001; + OpNamedBarrierInitialize:QWORD(Result):=$0000010100030003; + OpMemoryNamedBarrier:QWORD(Result):=$0000000000030003; + OpModuleProcessed:QWORD(Result):=$0000000000010001; + OpExecutionModeId:QWORD(Result):=$0000000000020002; + OpDecorateId:QWORD(Result):=$0000000000020002; + OpGroupNonUniformElect:QWORD(Result):=$0000010100030003; + OpGroupNonUniformAll:QWORD(Result):=$0000010100040004; + OpGroupNonUniformAny:QWORD(Result):=$0000010100040004; + OpGroupNonUniformAllEqual:QWORD(Result):=$0000010100040004; + OpGroupNonUniformBroadcast:QWORD(Result):=$0000010100050005; + OpGroupNonUniformBroadcastFirst:QWORD(Result):=$0000010100040004; + OpGroupNonUniformBallot:QWORD(Result):=$0000010100040004; + OpGroupNonUniformInverseBallot:QWORD(Result):=$0000010100040004; + OpGroupNonUniformBallotBitExtract:QWORD(Result):=$0000010100050005; + OpGroupNonUniformBallotBitCount:QWORD(Result):=$0000010100050005; + OpGroupNonUniformBallotFindLSB:QWORD(Result):=$0000010100040004; + OpGroupNonUniformBallotFindMSB:QWORD(Result):=$0000010100040004; + OpGroupNonUniformShuffle:QWORD(Result):=$0000010100050005; + OpGroupNonUniformShuffleXor:QWORD(Result):=$0000010100050005; + OpGroupNonUniformShuffleUp:QWORD(Result):=$0000010100050005; + OpGroupNonUniformShuffleDown:QWORD(Result):=$0000010100050005; + OpGroupNonUniformIAdd:QWORD(Result):=$0000010100060005; + OpGroupNonUniformFAdd:QWORD(Result):=$0000010100060005; + OpGroupNonUniformIMul:QWORD(Result):=$0000010100060005; + OpGroupNonUniformFMul:QWORD(Result):=$0000010100060005; + OpGroupNonUniformSMin:QWORD(Result):=$0000010100060005; + OpGroupNonUniformUMin:QWORD(Result):=$0000010100060005; + OpGroupNonUniformFMin:QWORD(Result):=$0000010100060005; + OpGroupNonUniformSMax:QWORD(Result):=$0000010100060005; + OpGroupNonUniformUMax:QWORD(Result):=$0000010100060005; + OpGroupNonUniformFMax:QWORD(Result):=$0000010100060005; + OpGroupNonUniformBitwiseAnd:QWORD(Result):=$0000010100060005; + OpGroupNonUniformBitwiseOr:QWORD(Result):=$0000010100060005; + OpGroupNonUniformBitwiseXor:QWORD(Result):=$0000010100060005; + OpGroupNonUniformLogicalAnd:QWORD(Result):=$0000010100060005; + OpGroupNonUniformLogicalOr:QWORD(Result):=$0000010100060005; + OpGroupNonUniformLogicalXor:QWORD(Result):=$0000010100060005; + OpGroupNonUniformQuadBroadcast:QWORD(Result):=$0000010100050005; + OpGroupNonUniformQuadSwap:QWORD(Result):=$0000010100050005; + OpCopyLogical:QWORD(Result):=$0000010100030003; + OpPtrEqual:QWORD(Result):=$0000010100040004; + OpPtrNotEqual:QWORD(Result):=$0000010100040004; + OpPtrDiff:QWORD(Result):=$0000010100040004; + OpTerminateInvocation:QWORD(Result):=$0000000000000000; + OpSubgroupBallotKHR:QWORD(Result):=$0000010100030003; + OpSubgroupFirstInvocationKHR:QWORD(Result):=$0000010100030003; + OpSubgroupAllKHR:QWORD(Result):=$0000010100030003; + OpSubgroupAnyKHR:QWORD(Result):=$0000010100030003; + OpSubgroupAllEqualKHR:QWORD(Result):=$0000010100030003; + OpSubgroupReadInvocationKHR:QWORD(Result):=$0000010100040004; + OpTraceRayKHR:QWORD(Result):=$00000000000B000B; + OpExecuteCallableKHR:QWORD(Result):=$0000000000020002; + OpConvertUToAccelerationStructureKHR:QWORD(Result):=$0000010100030003; + OpIgnoreIntersectionKHR:QWORD(Result):=$0000000000000000; + OpTerminateRayKHR:QWORD(Result):=$0000000000000000; + OpSDot:QWORD(Result):=$0000010100050004; + OpUDot:QWORD(Result):=$0000010100050004; + OpSUDot:QWORD(Result):=$0000010100050004; + OpSDotAccSat:QWORD(Result):=$0000010100060005; + OpUDotAccSat:QWORD(Result):=$0000010100060005; + OpSUDotAccSat:QWORD(Result):=$0000010100060005; + OpTypeRayQueryKHR:QWORD(Result):=$0000000100010001; + OpRayQueryInitializeKHR:QWORD(Result):=$0000000000080008; + OpRayQueryTerminateKHR:QWORD(Result):=$0000000000010001; + OpRayQueryGenerateIntersectionKHR:QWORD(Result):=$0000000000020002; + OpRayQueryConfirmIntersectionKHR:QWORD(Result):=$0000000000010001; + OpRayQueryProceedKHR:QWORD(Result):=$0000010100030003; + OpRayQueryGetIntersectionTypeKHR:QWORD(Result):=$0000010100040004; + OpGroupIAddNonUniformAMD:QWORD(Result):=$0000010100050005; + OpGroupFAddNonUniformAMD:QWORD(Result):=$0000010100050005; + OpGroupFMinNonUniformAMD:QWORD(Result):=$0000010100050005; + OpGroupUMinNonUniformAMD:QWORD(Result):=$0000010100050005; + OpGroupSMinNonUniformAMD:QWORD(Result):=$0000010100050005; + OpGroupFMaxNonUniformAMD:QWORD(Result):=$0000010100050005; + OpGroupUMaxNonUniformAMD:QWORD(Result):=$0000010100050005; + OpGroupSMaxNonUniformAMD:QWORD(Result):=$0000010100050005; + OpFragmentMaskFetchAMD:QWORD(Result):=$0000010100040004; + OpFragmentFetchAMD:QWORD(Result):=$0000010100050005; + OpReadClockKHR:QWORD(Result):=$0000010100030003; + OpImageSampleFootprintNV:QWORD(Result):=$0000010100070006; + OpGroupNonUniformPartitionNV:QWORD(Result):=$0000010100030003; + OpWritePackedPrimitiveIndices4x8NV:QWORD(Result):=$0000000000020002; + OpReportIntersectionKHR:QWORD(Result):=$0000010100040004; + OpIgnoreIntersectionNV:QWORD(Result):=$0000000000000000; + OpTerminateRayNV:QWORD(Result):=$0000000000000000; + OpTraceNV:QWORD(Result):=$00000000000B000B; + OpTraceMotionNV:QWORD(Result):=$00000000000C000C; + OpTraceRayMotionNV:QWORD(Result):=$00000000000C000C; + OpTypeAccelerationStructureKHR:QWORD(Result):=$0000000100010001; + OpExecuteCallableNV:QWORD(Result):=$0000000000020002; + OpTypeCooperativeMatrixNV:QWORD(Result):=$0000000100050005; + OpCooperativeMatrixLoadNV:QWORD(Result):=$0000010100060005; + OpCooperativeMatrixStoreNV:QWORD(Result):=$0000000000050004; + OpCooperativeMatrixMulAddNV:QWORD(Result):=$0000010100050005; + OpCooperativeMatrixLengthNV:QWORD(Result):=$0000010100030003; + OpBeginInvocationInterlockEXT:QWORD(Result):=$0000000000000000; + OpEndInvocationInterlockEXT:QWORD(Result):=$0000000000000000; + OpDemoteToHelperInvocation:QWORD(Result):=$0000000000000000; + OpIsHelperInvocationEXT:QWORD(Result):=$0000010100020002; + OpConvertUToImageNV:QWORD(Result):=$0000010100030003; + OpConvertUToSamplerNV:QWORD(Result):=$0000010100030003; + OpConvertImageToUNV:QWORD(Result):=$0000010100030003; + OpConvertSamplerToUNV:QWORD(Result):=$0000010100030003; + OpConvertUToSampledImageNV:QWORD(Result):=$0000010100030003; + OpConvertSampledImageToUNV:QWORD(Result):=$0000010100030003; + OpSamplerImageAddressingModeNV:QWORD(Result):=$0000000000010001; + OpSubgroupShuffleINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupShuffleDownINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupShuffleUpINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupShuffleXorINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupBlockReadINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupBlockWriteINTEL:QWORD(Result):=$0000000000020002; + OpSubgroupImageBlockReadINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupImageBlockWriteINTEL:QWORD(Result):=$0000000000030003; + OpSubgroupImageMediaBlockReadINTEL:QWORD(Result):=$0000010100060006; + OpSubgroupImageMediaBlockWriteINTEL:QWORD(Result):=$0000000000050005; + OpUCountLeadingZerosINTEL:QWORD(Result):=$0000010100030003; + OpUCountTrailingZerosINTEL:QWORD(Result):=$0000010100030003; + OpAbsISubINTEL:QWORD(Result):=$0000010100040004; + OpAbsUSubINTEL:QWORD(Result):=$0000010100040004; + OpIAddSatINTEL:QWORD(Result):=$0000010100040004; + OpUAddSatINTEL:QWORD(Result):=$0000010100040004; + OpIAverageINTEL:QWORD(Result):=$0000010100040004; + OpUAverageINTEL:QWORD(Result):=$0000010100040004; + OpIAverageRoundedINTEL:QWORD(Result):=$0000010100040004; + OpUAverageRoundedINTEL:QWORD(Result):=$0000010100040004; + OpISubSatINTEL:QWORD(Result):=$0000010100040004; + OpUSubSatINTEL:QWORD(Result):=$0000010100040004; + OpIMul32x16INTEL:QWORD(Result):=$0000010100040004; + OpUMul32x16INTEL:QWORD(Result):=$0000010100040004; + OpConstantFunctionPointerINTEL:QWORD(Result):=$0000010100030003; + OpFunctionPointerCallINTEL:QWORD(Result):=$00000101FFFF0002; + OpAsmTargetINTEL:QWORD(Result):=$0000010100030003; + OpAsmINTEL:QWORD(Result):=$0000010100060006; + OpAsmCallINTEL:QWORD(Result):=$00000101FFFF0003; + OpAtomicFMinEXT:QWORD(Result):=$0000010100060006; + OpAtomicFMaxEXT:QWORD(Result):=$0000010100060006; + OpAssumeTrueKHR:QWORD(Result):=$0000000000010001; + OpExpectKHR:QWORD(Result):=$0000010100040004; + OpDecorateString:QWORD(Result):=$0000000000020002; + OpMemberDecorateString:QWORD(Result):=$0000000000030003; + OpVmeImageINTEL:QWORD(Result):=$0000010100040004; + OpTypeVmeImageINTEL:QWORD(Result):=$0000000100020002; + OpTypeAvcImePayloadINTEL:QWORD(Result):=$0000000100010001; + OpTypeAvcRefPayloadINTEL:QWORD(Result):=$0000000100010001; + OpTypeAvcSicPayloadINTEL:QWORD(Result):=$0000000100010001; + OpTypeAvcMcePayloadINTEL:QWORD(Result):=$0000000100010001; + OpTypeAvcMceResultINTEL:QWORD(Result):=$0000000100010001; + OpTypeAvcImeResultINTEL:QWORD(Result):=$0000000100010001; + OpTypeAvcImeResultSingleReferenceStreamoutINTEL:QWORD(Result):=$0000000100010001; + OpTypeAvcImeResultDualReferenceStreamoutINTEL:QWORD(Result):=$0000000100010001; + OpTypeAvcImeSingleReferenceStreaminINTEL:QWORD(Result):=$0000000100010001; + OpTypeAvcImeDualReferenceStreaminINTEL:QWORD(Result):=$0000000100010001; + OpTypeAvcRefResultINTEL:QWORD(Result):=$0000000100010001; + OpTypeAvcSicResultINTEL:QWORD(Result):=$0000000100010001; + OpSubgroupAvcMceGetDefaultInterBaseMultiReferencePenaltyINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcMceSetInterBaseMultiReferencePenaltyINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcMceGetDefaultInterShapePenaltyINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcMceSetInterShapePenaltyINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcMceGetDefaultInterDirectionPenaltyINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcMceSetInterDirectionPenaltyINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcMceGetDefaultIntraLumaShapePenaltyINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcMceGetDefaultInterMotionVectorCostTableINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcMceGetDefaultHighPenaltyCostTableINTEL:QWORD(Result):=$0000010100020002; + OpSubgroupAvcMceGetDefaultMediumPenaltyCostTableINTEL:QWORD(Result):=$0000010100020002; + OpSubgroupAvcMceGetDefaultLowPenaltyCostTableINTEL:QWORD(Result):=$0000010100020002; + OpSubgroupAvcMceSetMotionVectorCostFunctionINTEL:QWORD(Result):=$0000010100060006; + OpSubgroupAvcMceGetDefaultIntraLumaModePenaltyINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcMceGetDefaultNonDcLumaIntraPenaltyINTEL:QWORD(Result):=$0000010100020002; + OpSubgroupAvcMceGetDefaultIntraChromaModeBasePenaltyINTEL:QWORD(Result):=$0000010100020002; + OpSubgroupAvcMceSetAcOnlyHaarINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceSetSourceInterlacedFieldPolarityINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcMceSetSingleReferenceInterlacedFieldPolarityINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcMceSetDualReferenceInterlacedFieldPolaritiesINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupAvcMceConvertToImePayloadINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceConvertToImeResultINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceConvertToRefPayloadINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceConvertToRefResultINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceConvertToSicPayloadINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceConvertToSicResultINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceGetMotionVectorsINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceGetInterDistortionsINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceGetBestInterDistortionsINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceGetInterMajorShapeINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceGetInterMinorShapeINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceGetInterDirectionsINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceGetInterMotionVectorCountINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceGetInterReferenceIdsINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcMceGetInterReferenceInterlacedFieldPolaritiesINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupAvcImeInitializeINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupAvcImeSetSingleReferenceINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupAvcImeSetDualReferenceINTEL:QWORD(Result):=$0000010100060006; + OpSubgroupAvcImeRefWindowSizeINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcImeAdjustRefOffsetINTEL:QWORD(Result):=$0000010100060006; + OpSubgroupAvcImeConvertToMcePayloadINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcImeSetMaxMotionVectorCountINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcImeSetUnidirectionalMixDisableINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcImeSetEarlySearchTerminationThresholdINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcImeSetWeightedSadINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcImeEvaluateWithSingleReferenceINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupAvcImeEvaluateWithDualReferenceINTEL:QWORD(Result):=$0000010100060006; + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminINTEL:QWORD(Result):=$0000010100060006; + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminINTEL:QWORD(Result):=$0000010100070007; + OpSubgroupAvcImeEvaluateWithSingleReferenceStreamoutINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupAvcImeEvaluateWithDualReferenceStreamoutINTEL:QWORD(Result):=$0000010100060006; + OpSubgroupAvcImeEvaluateWithSingleReferenceStreaminoutINTEL:QWORD(Result):=$0000010100060006; + OpSubgroupAvcImeEvaluateWithDualReferenceStreaminoutINTEL:QWORD(Result):=$0000010100070007; + OpSubgroupAvcImeConvertToMceResultINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcImeGetSingleReferenceStreaminINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcImeGetDualReferenceStreaminINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcImeStripSingleReferenceStreamoutINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcImeStripDualReferenceStreamoutINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeMotionVectorsINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeDistortionsINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcImeGetStreamoutSingleReferenceMajorShapeReferenceIdsINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeMotionVectorsINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeDistortionsINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupAvcImeGetStreamoutDualReferenceMajorShapeReferenceIdsINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupAvcImeGetBorderReachedINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcImeGetTruncatedSearchIndicationINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcImeGetUnidirectionalEarlySearchTerminationINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcImeGetWeightingPatternMinimumMotionVectorINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcImeGetWeightingPatternMinimumDistortionINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcFmeInitializeINTEL:QWORD(Result):=$0000010100090009; + OpSubgroupAvcBmeInitializeINTEL:QWORD(Result):=$00000101000A000A; + OpSubgroupAvcRefConvertToMcePayloadINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcRefSetBidirectionalMixDisableINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcRefSetBilinearFilterEnableINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcRefEvaluateWithSingleReferenceINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupAvcRefEvaluateWithDualReferenceINTEL:QWORD(Result):=$0000010100060006; + OpSubgroupAvcRefEvaluateWithMultiReferenceINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupAvcRefEvaluateWithMultiReferenceInterlacedINTEL:QWORD(Result):=$0000010100060006; + OpSubgroupAvcRefConvertToMceResultINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcSicInitializeINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcSicConfigureSkcINTEL:QWORD(Result):=$0000010100080008; + OpSubgroupAvcSicConfigureIpeLumaINTEL:QWORD(Result):=$00000101000A000A; + OpSubgroupAvcSicConfigureIpeLumaChromaINTEL:QWORD(Result):=$00000101000D000D; + OpSubgroupAvcSicGetMotionVectorMaskINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcSicConvertToMcePayloadINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcSicSetIntraLumaShapePenaltyINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcSicSetIntraLumaModeCostFunctionINTEL:QWORD(Result):=$0000010100060006; + OpSubgroupAvcSicSetIntraChromaModeCostFunctionINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcSicSetBilinearFilterEnableINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcSicSetSkcForwardTransformEnableINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcSicSetBlockBasedRawSkipSadINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcSicEvaluateIpeINTEL:QWORD(Result):=$0000010100040004; + OpSubgroupAvcSicEvaluateWithSingleReferenceINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupAvcSicEvaluateWithDualReferenceINTEL:QWORD(Result):=$0000010100060006; + OpSubgroupAvcSicEvaluateWithMultiReferenceINTEL:QWORD(Result):=$0000010100050005; + OpSubgroupAvcSicEvaluateWithMultiReferenceInterlacedINTEL:QWORD(Result):=$0000010100060006; + OpSubgroupAvcSicConvertToMceResultINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcSicGetIpeLumaShapeINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcSicGetBestIpeLumaDistortionINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcSicGetBestIpeChromaDistortionINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcSicGetPackedIpeLumaModesINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcSicGetIpeChromaModeINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcSicGetPackedSkcLumaCountThresholdINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcSicGetPackedSkcLumaSumThresholdINTEL:QWORD(Result):=$0000010100030003; + OpSubgroupAvcSicGetInterRawSadsINTEL:QWORD(Result):=$0000010100030003; + OpVariableLengthArrayINTEL:QWORD(Result):=$0000010100030003; + OpSaveMemoryINTEL:QWORD(Result):=$0000010100020002; + OpRestoreMemoryINTEL:QWORD(Result):=$0000000000010001; + OpArbitraryFloatSinCosPiINTEL:QWORD(Result):=$0000010100090009; + OpArbitraryFloatCastINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatCastFromIntINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatCastToIntINTEL:QWORD(Result):=$0000010100070007; + OpArbitraryFloatAddINTEL:QWORD(Result):=$00000101000A000A; + OpArbitraryFloatSubINTEL:QWORD(Result):=$00000101000A000A; + OpArbitraryFloatMulINTEL:QWORD(Result):=$00000101000A000A; + OpArbitraryFloatDivINTEL:QWORD(Result):=$00000101000A000A; + OpArbitraryFloatGTINTEL:QWORD(Result):=$0000010100060006; + OpArbitraryFloatGEINTEL:QWORD(Result):=$0000010100060006; + OpArbitraryFloatLTINTEL:QWORD(Result):=$0000010100060006; + OpArbitraryFloatLEINTEL:QWORD(Result):=$0000010100060006; + OpArbitraryFloatEQINTEL:QWORD(Result):=$0000010100060006; + OpArbitraryFloatRecipINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatRSqrtINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatCbrtINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatHypotINTEL:QWORD(Result):=$00000101000A000A; + OpArbitraryFloatSqrtINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatLogINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatLog2INTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatLog10INTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatLog1pINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatExpINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatExp2INTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatExp10INTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatExpm1INTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatSinINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatCosINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatSinCosINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatSinPiINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatCosPiINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatASinINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatASinPiINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatACosINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatACosPiINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatATanINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatATanPiINTEL:QWORD(Result):=$0000010100080008; + OpArbitraryFloatATan2INTEL:QWORD(Result):=$00000101000A000A; + OpArbitraryFloatPowINTEL:QWORD(Result):=$00000101000A000A; + OpArbitraryFloatPowRINTEL:QWORD(Result):=$00000101000A000A; + OpArbitraryFloatPowNINTEL:QWORD(Result):=$0000010100090009; + OpLoopControlINTEL:QWORD(Result):=$00000000FFFF0000; + OpFixedSqrtINTEL:QWORD(Result):=$0000010100090009; + OpFixedRecipINTEL:QWORD(Result):=$0000010100090009; + OpFixedRsqrtINTEL:QWORD(Result):=$0000010100090009; + OpFixedSinINTEL:QWORD(Result):=$0000010100090009; + OpFixedCosINTEL:QWORD(Result):=$0000010100090009; + OpFixedSinCosINTEL:QWORD(Result):=$0000010100090009; + OpFixedSinPiINTEL:QWORD(Result):=$0000010100090009; + OpFixedCosPiINTEL:QWORD(Result):=$0000010100090009; + OpFixedSinCosPiINTEL:QWORD(Result):=$0000010100090009; + OpFixedLogINTEL:QWORD(Result):=$0000010100090009; + OpFixedExpINTEL:QWORD(Result):=$0000010100090009; + OpPtrCastToCrossWorkgroupINTEL:QWORD(Result):=$0000010100030003; + OpCrossWorkgroupCastToPtrINTEL:QWORD(Result):=$0000010100030003; + OpReadPipeBlockingINTEL:QWORD(Result):=$0000010100040004; + OpWritePipeBlockingINTEL:QWORD(Result):=$0000010100040004; + OpFPGARegINTEL:QWORD(Result):=$0000010100040004; + OpRayQueryGetRayTMinKHR:QWORD(Result):=$0000010100030003; + OpRayQueryGetRayFlagsKHR:QWORD(Result):=$0000010100030003; + OpRayQueryGetIntersectionTKHR:QWORD(Result):=$0000010100040004; + OpRayQueryGetIntersectionInstanceCustomIndexKHR:QWORD(Result):=$0000010100040004; + OpRayQueryGetIntersectionInstanceIdKHR:QWORD(Result):=$0000010100040004; + OpRayQueryGetIntersectionInstanceShaderBindingTableRecordOffsetKHR:QWORD(Result):=$0000010100040004; + OpRayQueryGetIntersectionGeometryIndexKHR:QWORD(Result):=$0000010100040004; + OpRayQueryGetIntersectionPrimitiveIndexKHR:QWORD(Result):=$0000010100040004; + OpRayQueryGetIntersectionBarycentricsKHR:QWORD(Result):=$0000010100040004; + OpRayQueryGetIntersectionFrontFaceKHR:QWORD(Result):=$0000010100040004; + OpRayQueryGetIntersectionCandidateAABBOpaqueKHR:QWORD(Result):=$0000010100030003; + OpRayQueryGetIntersectionObjectRayDirectionKHR:QWORD(Result):=$0000010100040004; + OpRayQueryGetIntersectionObjectRayOriginKHR:QWORD(Result):=$0000010100040004; + OpRayQueryGetWorldRayDirectionKHR:QWORD(Result):=$0000010100030003; + OpRayQueryGetWorldRayOriginKHR:QWORD(Result):=$0000010100030003; + OpRayQueryGetIntersectionObjectToWorldKHR:QWORD(Result):=$0000010100040004; + OpRayQueryGetIntersectionWorldToObjectKHR:QWORD(Result):=$0000010100040004; + OpAtomicFAddEXT:QWORD(Result):=$0000010100060006; + OpTypeBufferSurfaceINTEL:QWORD(Result):=$0000000100020002; + OpTypeStructContinuedINTEL:QWORD(Result):=$00000000FFFF0000; + OpConstantCompositeContinuedINTEL:QWORD(Result):=$00000000FFFF0000; + OpSpecConstantCompositeContinuedINTEL:QWORD(Result):=$00000000FFFF0000; + end; +end; + +function GlslOp.GetStr(w:Word):RawByteString; +begin + Result:='???'; + Case w of + Round:Result:='Round'; + RoundEven:Result:='RoundEven'; + Trunc:Result:='Trunc'; + FAbs:Result:='FAbs'; + SAbs:Result:='SAbs'; + FSign:Result:='FSign'; + SSign:Result:='SSign'; + Floor:Result:='Floor'; + Ceil:Result:='Ceil'; + Fract:Result:='Fract'; + Radians:Result:='Radians'; + Degrees:Result:='Degrees'; + Sin:Result:='Sin'; + Cos:Result:='Cos'; + Tan:Result:='Tan'; + Asin:Result:='Asin'; + Acos:Result:='Acos'; + Atan:Result:='Atan'; + Sinh:Result:='Sinh'; + Cosh:Result:='Cosh'; + Tanh:Result:='Tanh'; + Asinh:Result:='Asinh'; + Acosh:Result:='Acosh'; + Atanh:Result:='Atanh'; + Atan2:Result:='Atan2'; + Pow:Result:='Pow'; + Exp:Result:='Exp'; + Log:Result:='Log'; + Exp2:Result:='Exp2'; + Log2:Result:='Log2'; + Sqrt:Result:='Sqrt'; + InverseSqrt:Result:='InverseSqrt'; + Determinant:Result:='Determinant'; + MatrixInverse:Result:='MatrixInverse'; + Modf:Result:='Modf'; + ModfStruct:Result:='ModfStruct'; + FMin:Result:='FMin'; + UMin:Result:='UMin'; + SMin:Result:='SMin'; + FMax:Result:='FMax'; + UMax:Result:='UMax'; + SMax:Result:='SMax'; + FClamp:Result:='FClamp'; + UClamp:Result:='UClamp'; + SClamp:Result:='SClamp'; + FMix:Result:='FMix'; + IMix:Result:='IMix'; + Step:Result:='Step'; + SmoothStep:Result:='SmoothStep'; + Fma:Result:='Fma'; + Frexp:Result:='Frexp'; + FrexpStruct:Result:='FrexpStruct'; + Ldexp:Result:='Ldexp'; + PackSnorm4x8:Result:='PackSnorm4x8'; + PackUnorm4x8:Result:='PackUnorm4x8'; + PackSnorm2x16:Result:='PackSnorm2x16'; + PackUnorm2x16:Result:='PackUnorm2x16'; + PackHalf2x16:Result:='PackHalf2x16'; + PackDouble2x32:Result:='PackDouble2x32'; + UnpackSnorm2x16:Result:='UnpackSnorm2x16'; + UnpackUnorm2x16:Result:='UnpackUnorm2x16'; + UnpackHalf2x16:Result:='UnpackHalf2x16'; + UnpackSnorm4x8:Result:='UnpackSnorm4x8'; + UnpackUnorm4x8:Result:='UnpackUnorm4x8'; + UnpackDouble2x32:Result:='UnpackDouble2x32'; + Length:Result:='Length'; + Distance:Result:='Distance'; + Cross:Result:='Cross'; + Normalize:Result:='Normalize'; + FaceForward:Result:='FaceForward'; + Reflect:Result:='Reflect'; + Refract:Result:='Refract'; + FindILsb:Result:='FindILsb'; + FindSMsb:Result:='FindSMsb'; + FindUMsb:Result:='FindUMsb'; + InterpolateAtCentroid:Result:='InterpolateAtCentroid'; + InterpolateAtSample:Result:='InterpolateAtSample'; + InterpolateAtOffset:Result:='InterpolateAtOffset'; + NMin:Result:='NMin'; + NMax:Result:='NMax'; + NClamp:Result:='NClamp'; + end; +end; + +function GlslOp.GetInfo(w:Word):TOpInfo; static; +begin + Result:=Default(TOpInfo); + Case w of + Round:QWORD(Result):=$0000000000010001; + RoundEven:QWORD(Result):=$0000000000010001; + Trunc:QWORD(Result):=$0000000000010001; + FAbs:QWORD(Result):=$0000000000010001; + SAbs:QWORD(Result):=$0000000000010001; + FSign:QWORD(Result):=$0000000000010001; + SSign:QWORD(Result):=$0000000000010001; + Floor:QWORD(Result):=$0000000000010001; + Ceil:QWORD(Result):=$0000000000010001; + Fract:QWORD(Result):=$0000000000010001; + Radians:QWORD(Result):=$0000000000010001; + Degrees:QWORD(Result):=$0000000000010001; + Sin:QWORD(Result):=$0000000000010001; + Cos:QWORD(Result):=$0000000000010001; + Tan:QWORD(Result):=$0000000000010001; + Asin:QWORD(Result):=$0000000000010001; + Acos:QWORD(Result):=$0000000000010001; + Atan:QWORD(Result):=$0000000000010001; + Sinh:QWORD(Result):=$0000000000010001; + Cosh:QWORD(Result):=$0000000000010001; + Tanh:QWORD(Result):=$0000000000010001; + Asinh:QWORD(Result):=$0000000000010001; + Acosh:QWORD(Result):=$0000000000010001; + Atanh:QWORD(Result):=$0000000000010001; + Atan2:QWORD(Result):=$0000000000020002; + Pow:QWORD(Result):=$0000000000020002; + Exp:QWORD(Result):=$0000000000010001; + Log:QWORD(Result):=$0000000000010001; + Exp2:QWORD(Result):=$0000000000010001; + Log2:QWORD(Result):=$0000000000010001; + Sqrt:QWORD(Result):=$0000000000010001; + InverseSqrt:QWORD(Result):=$0000000000010001; + Determinant:QWORD(Result):=$0000000000010001; + MatrixInverse:QWORD(Result):=$0000000000010001; + Modf:QWORD(Result):=$0000000000020002; + ModfStruct:QWORD(Result):=$0000000000010001; + FMin:QWORD(Result):=$0000000000020002; + UMin:QWORD(Result):=$0000000000020002; + SMin:QWORD(Result):=$0000000000020002; + FMax:QWORD(Result):=$0000000000020002; + UMax:QWORD(Result):=$0000000000020002; + SMax:QWORD(Result):=$0000000000020002; + FClamp:QWORD(Result):=$0000000000030003; + UClamp:QWORD(Result):=$0000000000030003; + SClamp:QWORD(Result):=$0000000000030003; + FMix:QWORD(Result):=$0000000000030003; + IMix:QWORD(Result):=$0000000000030003; + Step:QWORD(Result):=$0000000000020002; + SmoothStep:QWORD(Result):=$0000000000030003; + Fma:QWORD(Result):=$0000000000030003; + Frexp:QWORD(Result):=$0000000000020002; + FrexpStruct:QWORD(Result):=$0000000000010001; + Ldexp:QWORD(Result):=$0000000000020002; + PackSnorm4x8:QWORD(Result):=$0000000000010001; + PackUnorm4x8:QWORD(Result):=$0000000000010001; + PackSnorm2x16:QWORD(Result):=$0000000000010001; + PackUnorm2x16:QWORD(Result):=$0000000000010001; + PackHalf2x16:QWORD(Result):=$0000000000010001; + PackDouble2x32:QWORD(Result):=$0000000000010001; + UnpackSnorm2x16:QWORD(Result):=$0000000000010001; + UnpackUnorm2x16:QWORD(Result):=$0000000000010001; + UnpackHalf2x16:QWORD(Result):=$0000000000010001; + UnpackSnorm4x8:QWORD(Result):=$0000000000010001; + UnpackUnorm4x8:QWORD(Result):=$0000000000010001; + UnpackDouble2x32:QWORD(Result):=$0000000000010001; + Length:QWORD(Result):=$0000000000010001; + Distance:QWORD(Result):=$0000000000020002; + Cross:QWORD(Result):=$0000000000020002; + Normalize:QWORD(Result):=$0000000000010001; + FaceForward:QWORD(Result):=$0000000000030003; + Reflect:QWORD(Result):=$0000000000020002; + Refract:QWORD(Result):=$0000000000030003; + FindILsb:QWORD(Result):=$0000000000010001; + FindSMsb:QWORD(Result):=$0000000000010001; + FindUMsb:QWORD(Result):=$0000000000010001; + InterpolateAtCentroid:QWORD(Result):=$0000000000010001; + InterpolateAtSample:QWORD(Result):=$0000000000020002; + InterpolateAtOffset:QWORD(Result):=$0000000000020002; + NMin:QWORD(Result):=$0000000000020002; + NMax:QWORD(Result):=$0000000000020002; + NClamp:QWORD(Result):=$0000000000030003; + end; +end; + +end. diff --git a/spirv/srAllocator.pas b/spirv/srAllocator.pas new file mode 100644 index 0000000..0c68549 --- /dev/null +++ b/spirv/srAllocator.pas @@ -0,0 +1,81 @@ +unit srAllocator; + +{$mode objfpc}{$H+} + +interface + +uses + srNodes; + +type + PsrAllocNode=^TsrAllocNode; + TsrAllocNode=packed record + pNext:PsrAllocNode; + data:record end; + end; + + _TsrAllocator=specialize TNodeStack<PsrAllocNode>; + TsrAllocator=object(_TsrAllocator) + curr_apos:ptruint; //alloc pos in current node + curr_size:ptruint; //useable size of current node + used_size:ptruint; //full usable size + full_size:ptruint; //full alloc size + Function Alloc(Size:ptruint):Pointer; + Procedure Free; + end; + +implementation + +Function TsrAllocator.Alloc(Size:ptruint):Pointer; +const + asize=$FFFF-SizeOf(ptruint)*3; +var + mem_size:ptruint; + + function _alloc:Pointer; + begin + if (Size>asize-SizeOf(Pointer)) then + begin + Result:=AllocMem(Size+SizeOf(Pointer)); + end else + begin + Result:=AllocMem(asize); + end; + end; + +begin + if (pHead=nil) or (Size>curr_size) then + begin + Push_head(_alloc); + mem_size:=MemSize(pHead); + curr_apos:=0; + curr_size:=mem_size-SizeOf(Pointer); + Inc(full_size,mem_size); + end; + + Result:=@PByte(@pHead^.data)[curr_apos]; + + Inc(used_size,Size); + Size:=Align(Size,SizeOf(ptruint)); + Inc(curr_apos,Size); + Dec(curr_size,Size); +end; + +Procedure TsrAllocator.Free; +var + node:PsrAllocNode; +begin + node:=Pop_head; + While (node<>nil) do + begin + FreeMem(node); + node:=Pop_head; + end; + curr_apos:=0; + curr_size:=0; + used_size:=0; + full_size:=0; +end; + +end. + diff --git a/spirv/srBitcast.pas b/spirv/srBitcast.pas new file mode 100644 index 0000000..5f662d5 --- /dev/null +++ b/spirv/srBitcast.pas @@ -0,0 +1,152 @@ +unit srBitcast; + +{$mode ObjFPC}{$H+} + +interface + +uses + sysutils, + srNodes, + srTypes, + srConst, + srReg; + +type + PsrBitcast=^TsrBitcast; + TsrBitcast=object + pLeft,pRight:PsrBitcast; + //---- + key:packed record + dtype:TsrDataType; + src:PsrRegNode; + end; + dst:PsrRegNode; + function c(n1,n2:PsrBitcast):Integer; static; + end; + + TsrBitcastList=object + type + TNodeFetch=specialize TNodeFetch<PsrBitcast,TsrBitcast>; + 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; + end; + +implementation + +uses + SprvEmit, + emit_op; + +function TsrBitcast.c(n1,n2:PsrBitcast):Integer; +begin + Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrBitcast.key)); +end; + +function TsrBitcastList.Find(dtype:TsrDataType;src:PsrRegNode):PsrBitcast; +var + node:TsrBitcast; +begin + node:=Default(TsrBitcast); + node.key.dtype:=dtype; + node.key.src:=src; + Result:=FNTree.Find(@node); +end; + +function TsrBitcastList.FetchRead(dtype:TsrDataType;src:PsrRegNode):PsrRegNode; +var + dst:PsrRegNode; +begin + Result:=src; + if (src=nil) then Exit; + if (dtype=dtUnknow) or (dtype=src^.dtype) then + begin + src^.mark_read; + Exit; + end; + + src^.mark_read; + dst:=PSprvEmit(pRoot)^.NewReg(dtype); + dst^.pLine:=src^.pLine; + dst^.pWriter.SetParam(ntReg,src); + + dst^.mark_read; + Result:=dst; +end; + +function TsrBitcastList.FetchDst(dtype:TsrDataType;src:PsrRegNode):PsrRegNode; +begin + Result:=src; + if (src=nil) then Exit; + if (dtype=dtUnknow) or (dtype=src^.dtype) then Exit; + + Result:=PSprvEmit(pRoot)^.NewReg(dtype); + Result^.pLine:=src^.pLine; + Result^.mark_read; + + Result^.pWriter:=src^.pWriter; + src^.pWriter.SetParam(ntReg,Result); +end; + +function TsrBitcastList.FetchCast(dtype:TsrDataType;src:PsrRegNode):PsrRegNode; +var + node:PsrBitcast; + dst:PsrRegNode; + +begin + Result:=src; + if (src=nil) then Exit; + if (dtype=dtUnknow) or (dtype=src^.dtype) then + begin + src^.mark_read; + Exit; + end; + + dst:=nil; + + node:=Find(dtype,src); + if (node<>nil) then + begin + dst:=node^.dst; + dst^.mark_read; + Result:=dst; + Exit; + end; + + if src^.is_const then + begin + src^.AsConst^.mark_unread; + dst:=PSprvEmit(pRoot)^.NewReg(dtype); + dst^.pLine:=src^.pLine; + dst^.pWriter.SetParam(ntConst,PSprvEmit(pRoot)^.FConsts.Bitcast(dtype,src^.AsConst)); + 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); + end else + begin + Assert(false,'bitcast'); + end; + end; + + node:=PSprvEmit(pRoot)^.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; + +end. + diff --git a/spirv/srBuffer.pas b/spirv/srBuffer.pas new file mode 100644 index 0000000..9d94a23 --- /dev/null +++ b/spirv/srBuffer.pas @@ -0,0 +1,837 @@ +unit srBuffer; + +{$mode ObjFPC}{$H+} + +interface + +uses + spirv, + srNodes, + srTypes, + srVariable, + srLayout, + srDecorate; + +type + PsrBuffer=^TsrBuffer; + + PsrField=^TsrField; + + TsrFieldValue=(frNotFit,frIdent,frVectorAsValue,frValueInVector,frValueInArray); + + TFieldFetchValue=record + fValue:TsrFieldValue; + pField:PsrField; + end; + + TFieldEnumCb=procedure(pField:PsrField) of object; + TsrField=object + type + TFieldFetch=specialize TNodeFetch<PsrField,TsrField>; + var + pLeft,pRight:PsrField; + //---- + + pBuffer:PsrBuffer; + parent:PsrField; + offset:PtrUint; + size:PtrUint; + stride:PtrUint; + + FCount:PtrUint; + dtype:TsrDataType; + pType:PsrType; + FID:Integer; //alloc late + + // + + Alloc:TfnAlloc; + FList:TFieldFetch; + + function c(n1,n2:PsrField):Integer; static; + function Cross(o,s:PtrUint):Boolean; + function Find_be(o:PtrUint):PsrField; + function Find_le(o:PtrUint):PsrField; + function First:PsrField; + function Last:PsrField; + function Next(p:PsrField):PsrField; + function Prev(p:PsrField):PsrField; + function Fetch(o:PtrUint):PsrField; + function FetchValue(_offset,_size:PtrUint;_dtype:TsrDataType):TFieldFetchValue; + function FetchRuntimeArray(_offset,_stride:PtrUint):TFieldFetchValue; + function IsStructUsedRuntimeArray:Boolean; + function IsStructNotUsed:Boolean; + function GetStructDecorate:DWORD; + procedure FillNode(o,s:PtrUint); + function FillSpace:Integer; + procedure AllocID; + procedure AllocBinding(aType:PsrType;Decorates:PsrDecorateList); + end; + + TsrBufferType=(btStorageBuffer,btUniformBuffer,btPushConstant); + + TsrBuffer=object(TsrDescriptor) + pLeft,pRight:PsrBuffer; + //---- + + key:packed record + pLayout:PsrDataLayout; + CastNum:PtrInt; + end; + + bType:TsrBufferType; + + write_count:DWORD; + align_offset:DWORD; + + FTop:TsrField; + function c(n1,n2:PsrBuffer):Integer; static; + function GetTypeChar:Char; + function GetString:RawByteString; + function GetStructName:RawByteString; + procedure UpdateSize; + function GetSize:PtrUint; + 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; + + TsrBufferList=object + type + TNodeFetch=specialize TNodeFetch<PsrBuffer,TsrBuffer>; + var + Alloc:TfnAlloc; + cfg:TsrBufferCfg; + FNTree:TNodeFetch; + FPushConstant:PsrBuffer; + procedure Init(cb:TfnAlloc); + function Fetch(s:PsrDataLayout;n:PtrInt):PsrBuffer; + function NextCast(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 AllocID; + procedure AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList); + procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList); + procedure UpdateStorage(node:PsrChain;pBuffer:PsrBuffer); + procedure ApplyBufferType; + procedure AlignOffset(node:PsrBuffer;offset:PtrUint); + procedure AlignOffset; + end; + +implementation + +//--- + +function TsrField.c(n1,n2:PsrField):Integer; +begin + Result:=Integer(n1^.offset>n2^.offset)-Integer(n1^.offset<n2^.offset); +end; + +function TsrField.Cross(o,s:PtrUint):Boolean; +begin + Result:=((o>=offset) and (o<offset+size)) or + ((offset>=o) and (offset<o+s)); +end; + +function TsrField.Find_be(o:PtrUint):PsrField; +var + node:TsrField; +begin + node:=Default(TsrField); + node.offset:=o; + Result:=FList.Find_be(@node); +end; + +function TsrField.Find_le(o:PtrUint):PsrField; +var + node:TsrField; +begin + node:=Default(TsrField); + node.offset:=o; + Result:=FList.Find_le(@node); +end; + +function TsrField.First:PsrField; +begin + Result:=FList.Min; +end; + +function TsrField.Last:PsrField; +begin + Result:=FList.Max; +end; + +function TsrField.Next(p:PsrField):PsrField; +begin + Result:=FList.Next(p); +end; + +function TsrField.Prev(p:PsrField):PsrField; +begin + Result:=FList.Prev(p); +end; + +function TsrField.Fetch(o:PtrUint):PsrField; +var + node:TsrField; +begin + node:=Default(TsrField); + node.offset:=o; + Result:=FList.Find(@node); + if (Result=nil) then + begin + Result:=Alloc(SizeOf(TsrField)); + Result^.Alloc:=Alloc; + Result^.pBuffer:=pBuffer; + Result^.parent:=@Self; + Result^.offset:=o; + Result^.FID:=-1; + FList.Insert(Result); + Inc(FCount); + end; +end; + +function TsrField.FetchValue(_offset,_size:PtrUint;_dtype:TsrDataType):TFieldFetchValue; +var + node:PsrField; + _stride:PtrUint; +begin + Result:=Default(TFieldFetchValue); + + _stride:=0; + if isVector(_dtype) then + begin + _stride:=BitSizeType(GetVecChild(_dtype)) div 8; + end; + + node:=Find_le(_offset); + if (node<>nil) then + begin + if not node^.Cross(_offset,_size) then + begin + node:=Next(node); + if (node<>nil) then + begin + if not node^.Cross(_offset,_size) then + begin + node:=nil; + end; + end; + end; + end; + + if (node=nil) then + begin + //new + node:=Fetch(_offset); + node^.size :=_size; + node^.stride:=_stride; + node^.dtype :=_dtype; + Result.fValue:=frIdent; + Result.pField:=node; + end else + Case node^.dtype of + dtTypeArray: + begin + if (node^.offset>_offset) then Exit; //ident or big than + if (node^.offset+node^.size<_offset+_size) then Exit; + if (node^.stride<_size) then Exit; //ident or min stride + Result.fValue:=frValueInArray; + Result.pField:=node; + end; + dtTypeRuntimeArray: + begin + if (node^.offset>_offset) then Exit; //ident or big than + if (node^.stride<_size) then Exit; //ident or min stride + Result.fValue:=frValueInArray; + Result.pField:=node; + end; + else + begin + if isVector(node^.dtype) then + begin //ftVector + if isVector(_dtype) then + begin + if (node^.offset=_offset) and + (node^.size =_size) and + (node^.stride=_stride) then + begin + Result.fValue:=frIdent; //ident + Result.pField:=node; + end; + end else + begin + if (node^.offset>_offset) then Exit; //ident or big than + _offset:=_offset-node^.offset; + + if (node^.stride=_size) and + (_offset mod node^.stride=0) then + begin + Result.fValue:=frValueInVector; //down to vector + Result.pField:=node; + end; + end; + end else + begin //ftValue + if isVector(_dtype) then + begin + if (node^.offset=_offset) and + (node^.size =_size) then + begin + Result.fValue:=frVectorAsValue; //vector as value? + Result.pField:=node; + end; + end else + begin + if (node^.offset=_offset) and + (node^.size =_size) then + begin + Result.fValue:=frIdent; //ident + Result.pField:=node; + end; + end; + end; + end; + end; +end; + +function TsrField.FetchRuntimeArray(_offset,_stride:PtrUint):TFieldFetchValue; +var + node:PsrField; +begin + Result:=Default(TFieldFetchValue); + node:=Find_le(_offset); + if (node=nil) then + begin + //new + node:=Fetch(_offset); + node^.size :=High(PtrUint)-_offset; + node^.stride :=_stride; + node^.dtype :=dtTypeRuntimeArray; + Result.fValue:=frValueInArray; + Result.pField:=node; + end else + if (node^.stride=_stride) and + (node^.dtype =dtTypeRuntimeArray) and + (node^.offset<=_offset) then //ident or big than + begin + Result.fValue:=frValueInArray; + Result.pField:=node; + end; +end; + +function TsrField.IsStructUsedRuntimeArray:Boolean; +var + node:PsrField; +begin + Result:=False; + if (dtype=dtTypeStruct) then + begin + node:=FList.Max; + if (node<>nil) then + begin + size:=node^.offset+node^.size; + end; + Result:=(size=High(PtrUint)); + end; +end; + +function TsrField.IsStructNotUsed:Boolean; +begin + Result:=(FCount<=1) and (parent<>nil); +end; + +function TsrField.GetStructDecorate:DWORD; +begin + Result:=DWORD(-1); //dont use + if (parent=nil) then //is top + if (dtype=dtTypeStruct) then //is struct + begin + + if (pBuffer^.FStorage<>StorageClass.StorageBuffer) and + (pBuffer^.bType=btStorageBuffer) then + begin + Result:=Decoration.BufferBlock; + end else + begin + Result:=Decoration.Block; + end; + + end; +end; + +procedure TsrField.FillNode(o,s:PtrUint); + + procedure _Pad(p,v:PtrUint;_dtype:TsrDataType); //inline; + var + node:PsrField; + begin + if (o mod p<>0) and (s>=v) then + begin + node:=Fetch(o); + Assert(node^.dtype=dtUnknow,'WTF'); + node^.size:=v; + node^.dtype:=_dtype; + o:=o+v; + s:=s-v; + end; + end; + + procedure _Fill(v:PtrUint;_dtype:TsrDataType); //inline; + var + count:PtrUint; + node:PsrField; + begin + count:=s div v; + While (count<>0) do + begin + node:=Fetch(o); + Assert(node^.dtype=dtUnknow,'WTF'); + node^.size:=v; + node^.dtype:=_dtype; + o:=o+v; + s:=s-v; + Dec(count); + end; + end; + +begin + if (s=0) then Exit; + + _Pad ( 2,1,dtUint8); + _Pad ( 4,2,dtHalf16); + _Pad ( 8,4,dtFloat32); + _Pad (16,8,dtVec2f); + + _Fill(16,dtVec4f); + _Fill(8 ,dtVec2f); + _Fill(4 ,dtFloat32); + _Fill(2 ,dtHalf16); + _Fill(1 ,dtUint8); +end; + +function TsrField.FillSpace:Integer; +var + pNode:PsrField; + Foffset,Fsize:PtrUint; +begin + Result:=0; + pNode:=First; + if (pNode=nil) then Exit; + + Foffset:=0; + While (pNode<>nil) do + begin + Assert(pNode^.dtype<>dtUnknow,'WTF'); + if (Foffset<pNode^.offset) then + begin + Fsize:=pNode^.offset-Foffset; + FillNode(Foffset,Fsize); + Inc(Result); + end; + Foffset:=pNode^.offset+pNode^.size; + pNode:=Next(pNode); + end; + + if (stride<>0) and (dtype in [dtTypeArray,dtTypeRuntimeArray]) then + begin + pNode:=FList.Max; + if (pNode<>nil) then + begin + Foffset:=pNode^.offset+pNode^.size; + Assert(Foffset<=stride); + if (Foffset<stride) then + begin + Fsize:=stride-Foffset; + FillNode(Foffset,Fsize); + Inc(Result); + end; + end; + 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; +begin + //first pLayout + Result:=Integer(n1^.key.pLayout>n2^.key.pLayout)-Integer(n1^.key.pLayout<n2^.key.pLayout); + if (Result<>0) then Exit; + //second CastNum + Result:=Integer(n1^.key.CastNum>n2^.key.CastNum)-Integer(n1^.key.CastNum<n2^.key.CastNum); +end; + +function TsrBuffer.GetTypeChar:Char; +begin + Result:=#0; + Case bType of + btStorageBuffer:Result:='S'; + btUniformBuffer:Result:='U'; + btPushConstant :Result:='P'; + end; +end; + +function TsrBuffer.GetString:RawByteString; +var + PID:DWORD; +begin + PID:=0; + if (key.pLayout<>nil) then + begin + PID:=key.pLayout^.FID; + end; + Result:='B'+GetTypeChar+ + ';PID='+HexStr(PID,8)+ + ';BND='+HexStr(FBinding,8)+ + ';LEN='+HexStr(GetSize,8)+ + ';OFS='+HexStr(align_offset,8); +end; + +function TsrBuffer.GetStructName:RawByteString; +begin + Result:='TD'+HexStr(FBinding,8); +end; + +procedure TsrBuffer.UpdateSize; +var + node:PsrField; +begin + node:=FTop.FList.Max; + if (node<>nil) then + begin + FTop.size:=node^.offset+node^.size; + end; +end; + +function TsrBuffer.GetSize:PtrUint; +begin + UpdateSize; + Result:=FTop.size; +end; + +procedure TsrBuffer.EnumAllField(cb:TFieldEnumCb); +var + curr,node:PsrField; +begin + if (cb=nil) then Exit; + curr:=@FTop; + node:=curr^.First; + repeat + While (node<>nil) do + begin + if (node^.FList.pRoot<>nil) then //child exist + begin + curr^.FList._Splay(node); //Move to root + curr:=node; + node:=curr^.First; //down + end else + begin + cb(node); + node:=curr^.Next(node); + end; + end; + cb(curr); + curr:=curr^.parent; //up + if (curr=nil) then Break; + node:=curr^.FList.pRoot; //last find + node:=curr^.Next(node); + until false; +end; + +procedure TsrBuffer.ShiftOffset(Offset:PtrUint); +var + node:PsrField; +begin + if (Offset=0) then Exit; + node:=FTop.Last; + While (node<>nil) do + begin + if (node^.offset+node^.size=High(PtrUint)) then + begin + node^.size:=node^.size-Offset; + end; + node^.offset:=node^.offset+Offset; + node:=FTop.Prev(node); + end; +end; + +Procedure TsrBufferCfg.Init; +begin + SpvVersion:=$10100; + maxUniformBufferRange:=$FFFF; + maxPushConstantsSize:=128; + minStorageBufferOffsetAlignment:=$10; + minUniformBufferOffsetAlignment:=$100; +end; + +Function TsrBufferCfg.CanUseStorageBufferClass:Boolean; +begin + Result:=(SpvVersion>=$10300); +end; + +procedure TsrBufferList.Init(cb:TfnAlloc); +begin + Alloc:=cb; + cfg.Init; +end; + +function TsrBufferList.Fetch(s:PsrDataLayout;n:PtrInt):PsrBuffer; +var + node:TsrBuffer; +begin + node:=Default(TsrBuffer); + node.key.pLayout:=s; + node.key.CastNum:=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^.FTop.pBuffer:=Result; + Result^.FTop.FID:=-1; + Result^.FTop.dtype:=dtTypeStruct; + FNTree.Insert(Result); + end; +end; + +function TsrBufferList.NextCast(buf:PsrBuffer):PsrBuffer; +begin + Result:=nil; + if (buf=nil) then Exit; + Result:=Fetch(buf^.key.pLayout,buf^.key.CastNum+1); +end; + +Function TsrBufferList.First:PsrBuffer; +begin + Result:=FNTree.Min; +end; + +Function TsrBufferList.Next(node:PsrBuffer):PsrBuffer; +begin + Result:=FNTree.Next(node); +end; + +procedure TsrBufferList.EnumAllField(cb:TFieldEnumCb); +var + node:PsrBuffer; +begin + if (cb=nil) then Exit; + node:=First; + While (node<>nil) do + begin + node^.EnumAllField(cb); + node:=Next(node); + end; +end; + +procedure TsrBufferList.OnFillSpace(node:PsrField); +begin + node^.FillSpace; +end; + +procedure TsrBufferList.FillSpace; +begin + EnumAllField(@OnFillSpace); +end; + +procedure TsrBufferList.OnAllocID(node:PsrField); +begin + node^.AllocID; +end; + +procedure TsrBufferList.AllocID; +begin + EnumAllField(@OnAllocID); +end; + +procedure TsrBufferList.AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList); +var + node:PsrBuffer; + pVar:PsrVariable; +begin + if (Decorates=nil) then Exit; + node:=First; + While (node<>nil) do + begin + pVar:=node^.pVar; + if (pVar<>nil) then + begin + if (node^.bType<>btPushConstant) then + if (node^.FBinding=-1) then //alloc + begin + Decorates^.emit_decorate(ntVar,pVar,Decoration.Binding,FBinding); + Decorates^.emit_decorate(ntVar,pVar,Decoration.DescriptorSet,Decorates^.FDescriptorSet); + node^.FBinding:=FBinding; + Inc(FBinding); + 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 + node:PsrBuffer; +begin + node:=First; + While (node<>nil) do + begin + if (node^.bType=btStorageBuffer) then + begin + + if (FPushConstant=nil) and + (node^.write_count=0) and + (node^.GetSize<=cfg.maxPushConstantsSize) then + begin + node^.bType :=btPushConstant; + node^.FStorage:=StorageClass.PushConstant; + FPushConstant:=node; + end else + if (node^.write_count=0) and + (node^.GetSize<=cfg.maxUniformBufferRange) then + begin + node^.bType :=btUniformBuffer; + node^.FStorage:=StorageClass.Uniform; + end else + if cfg.CanUseStorageBufferClass then + begin + node^.FStorage:=StorageClass.StorageBuffer; + end else + begin + node^.FStorage:=StorageClass.Uniform; + end; + + end; + node:=Next(node); + end; +end; + +function AlignShift(addr:Pointer;alignment:PtrUInt):PtrUInt; inline; +begin + if (alignment>1) then + begin + Result:=(PtrUInt(addr) mod alignment); + end else + begin + Result:=0; + end; +end; + +procedure TsrBufferList.AlignOffset(node:PsrBuffer;offset:PtrUint); +var + P:Pointer; +begin + P:=node^.key.pLayout^.GetData; + offset:=AlignShift(P,offset); + node^.align_offset:=offset; + node^.ShiftOffset(offset); +end; + +procedure TsrBufferList.AlignOffset; +var + node:PsrBuffer; +begin + 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; + end; + node:=Next(node); + end; +end; + +end. + diff --git a/spirv/srCFG.pas b/spirv/srCFG.pas new file mode 100644 index 0000000..44df54e --- /dev/null +++ b/spirv/srCFG.pas @@ -0,0 +1,626 @@ +unit srCFG; + +{$mode ObjFPC}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + srNodes, + srLabel; + +type + PsrCFGBlock=^TsrCFGBlock; + + TsrCFGBlockList=specialize TNodeList<PsrCFGBlock>; + + TsrCFGBlock=object + pParent,pPrev,pNext:PsrCFGBlock; + + FList:TsrCFGBlockList; + + pBLabel:PsrLabel; + pELabel:PsrLabel; + + bType:TsrBlockType; + + term_id:Integer; + + function IsEndOf(Adr:TSrcAdr):Boolean; + function IsBigOf(Adr:TSrcAdr):Boolean; + function IsContain(Adr:TSrcAdr):Boolean; + function FindBlock(Adr:TSrcAdr):PsrCFGBlock; + function DownBlock(Adr:TSrcAdr):PsrCFGBlock; + function UpBlock(Adr:TSrcAdr):PsrCFGBlock; + function FindUpLoop:PsrCFGBlock; + Procedure InsertBlockList(New,child:PsrCFGBlock); + function get_level:DWORD; + end; + + PsrCodeBlock=^TsrCodeBlock; + TsrCodeBlock=object + pNext:PsrCodeBlock; + //---- + Alloc:TfnAlloc; + Body:Pointer; + Size:ptruint; + FLabels:TsrLabels; + FTop:TsrCFGBlock; + Function FindLabel(Adr:TSrcAdr):PsrLabel; + Function FetchLabel(Adr:TSrcAdr):PsrLabel; + Function IsContain(P:Pointer):Boolean; + end; + + TsrCFGParser=object + FCursor:TsrLCursor; + pCode:PsrCodeBlock; + pBlock:PsrCFGBlock; + FSPI:TSPI; + procedure _print_label(Adr:TSrcAdr); + procedure Print(base:Pointer); + function Parse(base:Pointer):Byte; + function NextParse:Byte; + Procedure Finalize; + function CheckBlock:Boolean; + Procedure CheckLabel; + Procedure CheckTerm; + function emit_SOP1:Boolean; + function emit_SOPP:Boolean; + Function NewBlock:PsrCFGBlock; + Procedure PushBlock(New:PsrCFGBlock); + function PopBlock:Boolean; + procedure emit_S_BRANCH; + end; + +function parse_code_cfg(bType:TsrBlockType;base:Pointer;pCode:PsrCodeBlock):Byte; + +implementation + +function parse_code_cfg(bType:TsrBlockType;base:Pointer;pCode:PsrCodeBlock):Byte; +var + LParser:TsrCFGParser; +begin + pCode^.FTop.bType:=bType; + LParser:=Default(TsrCFGParser); + LParser.pCode:=pCode; + Result:=LParser.Parse(base); + + //LParser.Print(base); +end; + +function TsrCFGBlock.IsEndOf(Adr:TSrcAdr):Boolean; +begin + Result:=False; + if (pELabel<>nil) then + begin + Result:=(pELabel^.Adr.get_pc<=Adr.get_pc); + end; +end; + +function TsrCFGBlock.IsBigOf(Adr:TSrcAdr):Boolean; +begin + Result:=False; + if (pELabel<>nil) then + begin + Result:=(pELabel^.Adr.get_pc<Adr.get_pc); + end; +end; + +function TsrCFGBlock.IsContain(Adr:TSrcAdr):Boolean; +var + b,e:Boolean; +begin + b:=true; + if (pBLabel<>nil) then + begin + b:=(pBLabel^.Adr.get_pc<=Adr.get_pc); + end; + e:=true; + if (pELabel<>nil) then + begin + e:=(pELabel^.Adr.get_pc>Adr.get_pc); + end; + Result:=b and e; +end; + +function TsrCFGBlock.FindBlock(Adr:TSrcAdr):PsrCFGBlock; +var + node:PsrCFGBlock; +begin + Result:=nil; + node:=FList.pHead; + While (node<>nil) do + begin + if node^.IsContain(Adr) then Exit(node); + node:=node^.pNext; + end; +end; + +function TsrCFGBlock.DownBlock(Adr:TSrcAdr):PsrCFGBlock; +var + next:PsrCFGBlock; +begin + Result:=@Self; + repeat + next:=Result^.FindBlock(Adr); + if (next=nil) then Exit; + Result:=next; + until false; +end; + +function TsrCFGBlock.UpBlock(Adr:TSrcAdr):PsrCFGBlock; +var + next:PsrCFGBlock; +begin + Result:=@Self; + While (Result^.IsEndOf(Adr)) do + begin + next:=Result^.pParent; + if (next=nil) then Exit; + Result:=next; + end; +end; + +function TsrCFGBlock.FindUpLoop:PsrCFGBlock; +var + node:PsrCFGBlock; +begin + Result:=nil; + node:=@Self; + While (node<>nil) do + begin + if (node^.bType=btLoop) then Exit(node); + node:=node^.pParent; + end; +end; + +Procedure TsrCFGBlock.InsertBlockList(New,child:PsrCFGBlock); +var + next:PsrCFGBlock; +begin + if (New=nil) then Exit; + New^.pParent:=@Self; + While (child<>nil) do + begin + Assert(child^.pParent=@Self); + next:=child^.pNext; + FList.Remove(child); + New^.FList.Push_tail(child); + child^.pParent:=New; + child:=next; + end; + FList.Push_tail(New); +end; + +function TsrCFGBlock.get_level:DWORD; +var + node:PsrCFGBlock; +begin + node:=@Self; + Result:=0; + While (node<>nil) do + begin + Inc(Result); + node:=node^.pParent; + end; +end; + +procedure TsrCFGParser._print_label(Adr:TSrcAdr); +var + pLabel:PsrLabel; +begin + pLabel:=pCode^.FindLabel(Adr); + if (pLabel<>nil) then + begin + Write('label_',HexStr(Adr.Offdw*4,4),': ;'); + + if (ltBranch in pLabel^.lType) then Write('ltBranch '); + if (ltUnknow in pLabel^.lType) then Write('ltUnknow '); + if (ltBegAdr in pLabel^.lType) then Write('ltBegAdr '); + if (ltEndAdr in pLabel^.lType) then Write('ltEndAdr '); + if (ltBegCond in pLabel^.lType) then Write('ltBegCond '); + if (ltEndCond in pLabel^.lType) then Write('ltEndCond '); + if (ltBegLoop in pLabel^.lType) then Write('ltBegLoop '); + if (ltEndLoop in pLabel^.lType) then Write('ltEndLoop '); + + writeln; + end; +end; + +procedure TsrCFGParser.Print(base:Pointer); +var + Adr:TSrcAdr; + level:DWORD; + i:Byte; +begin + FCursor.Init(base); + pBlock:=@pCode^.FTop; + repeat + Adr:=FCursor.Adr; + + pBlock:=pBlock^.DownBlock(Adr); + + level:=pBlock^.get_level; + + _print_label(Adr); + + Write(' ',HexStr(FCursor.OFFSET_DW*4,4)); + Write(Space(level)); + + FSPI:=Default(TSPI); + i:=FCursor.Next(FSPI); + Case i of + 0,1:begin + + print_spi(FSPI); + + Adr:=FCursor.Adr; + pBlock:=pBlock^.UpBlock(Adr); + + end; + end; + + until (i<>0); + _print_label(Adr); +end; + +function TsrCFGParser.Parse(base:Pointer):Byte; +begin + if (pCode=nil) then Exit(4); + pCode^.Body:=base; + FCursor.Init(base); + pBlock:=@pCode^.FTop; + pCode^.FTop.pBLabel:=pCode^.FetchLabel(FCursor.Adr); + repeat + Result:=NextParse; + Case Result of + 0:; + 1:Break; + else + Break; + end; + until false; +end; + +function TsrCFGParser.NextParse:Byte; +begin + FSPI:=Default(TSPI); + Result:=FCursor.Next(FSPI); + Case Result of + 0,1:begin + Case FSPI.CMD.EN of + W_SOP1:if emit_SOP1 then Result:=1; + W_SOPP:if emit_SOPP then Result:=1; + end; + While (CheckBlock) do; + if (Result=0) then + begin + CheckTerm; + end; + CheckLabel; + if (Result=1) then + begin + Finalize; + end; + end; + end; +end; + +Procedure TsrCFGParser.Finalize; +begin + pCode^.FTop.pELabel:=pCode^.FetchLabel(FCursor.Adr); + pCode^.Size:=FCursor.OFFSET_DW*4; +end; + +function TsrCFGParser.CheckBlock:Boolean; +var + pLabel:PsrLabel; +begin + Result:=False; + if (pBlock=nil) then Exit; + Result:=pBlock^.IsEndOf(FCursor.Adr); + if Result then + begin + + Case pBlock^.bType of + btAdr: + begin + pLabel:=pBlock^.pELabel; + pLabel^.AddType(ltEndAdr); + end; + btLoop: + begin + pLabel:=pBlock^.pELabel; + pLabel^.AddType(ltEndLoop); + end; + else; + end; + + PopBlock; + end; +end; + +Procedure TsrCFGParser.CheckLabel; +var + c_adr:TSrcAdr; + pLabel:array[0..1] of PsrLabel; + node,prev:PsrCFGBlock; +begin + c_adr:=FCursor.Adr; + pLabel[0]:=pCode^.FindLabel(c_adr); + if (pLabel[0]=nil) then Exit; + + if not (pLabel[0]^.IsType(ltUnknow)) then Exit; + + prev:=pBlock^.FList.pTail; + While (prev<>nil) do + begin + if prev^.IsContain(c_adr) then Break; + prev:=prev^.pPrev; + end; + if (prev=nil) then Exit; + + if not (prev^.IsContain(c_adr)) then Exit; + + pLabel[1]:=prev^.pBLabel; + + pLabel[0]^.RemType(ltUnknow); //ltEndLoop later + pLabel[1]^.AddType(ltBegLoop); + + node:=NewBlock; + node^.pBLabel:=pLabel[1]; + node^.pELabel:=pLabel[0]; + node^.bType:=btLoop; + + pBlock^.InsertBlockList(node,prev); +end; + +Procedure TsrCFGParser.CheckTerm; +var + c_adr:TSrcAdr; + pLabel:array[0..1] of PsrLabel; + node,prev:PsrCFGBlock; +begin + With pBlock^ do + begin + if (term_id>=0) then Exit; + term_id:=Abs(term_id); + end; + + c_adr:=FCursor.Adr; + + pLabel[0]:=pCode^.FetchLabel(c_adr); + pLabel[1]:=nil; + pLabel[0]^.RemType(ltUnknow); + pLabel[0]^.AddType(ltBegAdr); + + prev:=pBlock^.pParent; + if (prev<>nil) then + begin + pLabel[1]:=prev^.pELabel; + end; + + node:=NewBlock; + node^.pBLabel:=pLabel[0]; + node^.pELabel:=pLabel[1]; + node^.bType:=btAdr; + PushBlock(node); +end; + +function TsrCFGParser.emit_SOP1:Boolean; +begin + Result:=False; + Case FSPI.SOP1.OP of + S_SETPC_B64:if (pBlock^.bType=btSetpc) then Result:=True; + end; +end; + +function TsrCFGParser.emit_SOPP:Boolean; +var + c_adr:TSrcAdr; + pLabel:PsrLabel; +begin + Result:=False; + Case FSPI.SOPP.OP of + + S_ENDPGM: + begin + + if (pBlock^.bType=btAdr) then + begin + c_adr:=FCursor.Adr; + pLabel:=pCode^.FetchLabel(c_adr); + pLabel^.AddType(ltEndAdr); + pBlock^.pELabel:=pLabel; + PopBlock; + end; + + With pBlock^ do + begin + term_id:=-(Abs(term_id)+1); + end; + + end; + + S_CBRANCH_SCC0 , + S_CBRANCH_SCC1 , + S_CBRANCH_VCCZ , + S_CBRANCH_VCCNZ , + S_CBRANCH_EXECZ , + S_CBRANCH_EXECNZ, + S_BRANCH :emit_S_BRANCH; + + else; + end; +end; + +Function TsrCodeBlock.FindLabel(Adr:TSrcAdr):PsrLabel; +var + node:TsrLabel; +begin + Result:=nil; + node:=Default(TsrLabel); + node.Adr:=Adr; + Result:=FLabels.FNTree.Find(@node); +end; + +Function TsrCodeBlock.FetchLabel(Adr:TSrcAdr):PsrLabel; +var + node:TsrLabel; +begin + Result:=nil; + node:=Default(TsrLabel); + node.Adr:=Adr; + Result:=FLabels.FNTree.Find(@node); + if (Result=nil) then + begin + Result:=Alloc(SizeOf(TsrLabel)); + Result^.Adr:=Adr; + FLabels.FNTree.Insert(Result); + //FLabels.FList.Push_tail(Result); + end; +end; + +Function TsrCodeBlock.IsContain(P:Pointer):Boolean; +begin + Result:=(Body<=P) and ((Body+Size)>P); +end; + +Function TsrCFGParser.NewBlock:PsrCFGBlock; +begin + Result:=pCode^.Alloc(SizeOf(TsrCFGBlock)); +end; + +Procedure TsrCFGParser.PushBlock(New:PsrCFGBlock); +begin + if (New=nil) then Exit; + pBlock^.FList.Push_tail(New); + New^.pParent:=pBlock; + pBlock:=New; +end; + +function TsrCFGParser.PopBlock:Boolean; +begin + Result:=False; + if (pBlock=nil) then Exit; + if (pBlock^.pParent=nil) then Exit; + pBlock:=pBlock^.pParent; + Result:=True; +end; + +procedure TsrCFGParser.emit_S_BRANCH; +var + pLabel:array[0..1] of PsrLabel; + c_adr,b_adr,t_adr:TSrcAdr; + node,child,prev,parent:PsrCFGBlock; +begin + c_adr:=FCursor.Adr; + b_adr:=c_adr; + b_adr.Offdw:=get_branch_offset(FSPI); + + pLabel[0]:=pCode^.FetchLabel(c_adr); + pLabel[1]:=pCode^.FetchLabel(b_adr); + pLabel[0]^.AddType(ltBranch); + + if (SmallInt(FSPI.SOPP.SIMM)<0) then //up + begin + + child:=nil; + parent:=pBlock; + + repeat + + if (parent^.pBLabel=nil) then + begin + t_adr:=c_adr; + t_adr.Offdw:=0; + end else + begin + t_adr:=parent^.pBLabel^.Adr; + end; + + if (parent^.bType=btLoop) and (t_adr.get_pc=b_adr.get_pc) then //is exist loop + begin + pLabel[0]^.RemType(ltUnknow); //ltEndLoop later + if (parent^.pELabel=nil) then + begin + parent^.pELabel:=pLabel[0]; //set end + end else + begin + t_adr:=parent^.pELabel^.Adr; + if (t_adr.get_pc<c_adr.get_pc) then + begin + parent^.pELabel:=pLabel[0]; //update end of loop + end; + end; + Exit; + end; + + if (t_adr.get_pc<=b_adr.get_pc) then Break; + + child:=parent; + parent:=parent^.pParent; + until false; + + if (child<>nil) then + repeat //up list + if child^.IsContain(t_adr) then Assert(false); + + prev:=child^.pPrev; + if (prev=nil) then Break; + + if (prev^.pELabel=nil) then + begin + t_adr:=c_adr; + end else + begin + t_adr:=prev^.pELabel^.Adr; + end; + + if (t_adr.get_pc<=b_adr.get_pc) then Break; + + child:=prev; + until false; + + //new loop block + + pLabel[0]^.RemType(ltUnknow); //ltEndLoop later + pLabel[1]^.AddType(ltBegLoop); + + node:=NewBlock; + node^.pBLabel:=pLabel[1]; + node^.pELabel:=pLabel[0]; + node^.bType:=btLoop; + + parent^.InsertBlockList(node,child); + + end else //down + begin + + if (pBlock^.pELabel<>nil) then + if (pBlock^.pELabel^.Adr.get_pc<b_adr.get_pc) then + begin + //push adr or loop end + if not pLabel[1]^.IsType(ltBegAdr) then + begin + pLabel[1]^.AddType(ltUnknow); + end; + Exit; + end; + + pLabel[0]^.AddType(ltBegCond); + pLabel[1]^.AddType(ltEndCond); + + node:=NewBlock; + node^.pBLabel:=pLabel[0]; + node^.pELabel:=pLabel[1]; + node^.bType:=btCond; + PushBlock(node); + + end; + +end; + +end. + diff --git a/spirv/srCap.pas b/spirv/srCap.pas new file mode 100644 index 0000000..74c7da5 --- /dev/null +++ b/spirv/srCap.pas @@ -0,0 +1,61 @@ +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; + + TsrCapList=object + type + TNodeFetch=specialize TNodeFetch<PSpirvCap,TSpirvCap>; + 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^.ID<n2^.ID); +end; + +procedure TsrCapList.Add(ID:DWORD); +var + fnode:TSpirvCap; + pnode:PSpirvCap; +begin + fnode:=Default(TSpirvCap); + fnode.ID:=ID; + if (FNTree.Find(@fnode)<>nil) 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/srConst.pas b/spirv/srConst.pas new file mode 100644 index 0000000..f2889eb --- /dev/null +++ b/spirv/srConst.pas @@ -0,0 +1,601 @@ +unit srConst; + +{$mode objfpc}{$H+} + +interface + +uses + srNodes, + srRefId, + 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; + end; + + TsrConstList=object + type + TNodeList=specialize TNodeList<PsrConst>; + TNodeFetch=specialize TNodeFetch<PsrConst,TsrConst>; + var + Alloc:TfnAlloc; + 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; + end; + +function get_soffset_const_int(SSRC:Word):Integer; +function is_const_soffset(SSRC:Byte):Boolean; inline; +function is_const_ssrc8(SSRC:Byte):Boolean; inline; +function is_const_ssrc9(SSRC:Word):Boolean; inline; +function CompareConst(r1,r2:PsrConst):Boolean; + +implementation + +function TsrConst.c(n1,n2:PsrConst):Integer; +var + count:DWORD; +begin + Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrConst.key)); + if (Result<>0) then Exit; + count:=n1^.key.count; + if (count=0) then + begin + Result:=Integer(n1^.Data>n2^.Data)-Integer(n1^.Data<n2^.Data); + end else + begin + Result:=ComparePtruint(@n1^.Data,@n2^.Data,count); + end; +end; + +Procedure TsrConst.mark_read; +begin + Inc(read_count); +end; + +Procedure TsrConst.mark_unread; +begin + Assert(read_count<>0); + if (read_count<>0) then Dec(read_count); +end; + +function TsrConst.GetCompItem(i:Byte):PsrConst; inline; +begin + Result:=PPsrConst(@Data)[i]; +end; + +Procedure TsrConst.SetCompItem(i:Byte;p:PsrConst); inline; +begin + PPsrConst(@Data)[i]:=p; +end; + +function TsrConst.GetData:QWORD; +begin + Result:=0; + case key.dtype of + dtVec2f: + begin + PSingle(@Result)[0]:=GetCompItem(0)^.AsFloat32; + PSingle(@Result)[1]:=GetCompItem(1)^.AsFloat32; + 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; + else + begin + Assert(key.count=0,'count<>0'); + Result:=data; + end; + end; +end; + +Function TsrConst.isZeroVal:Boolean; +begin + case key.dtype of + dtInt32 , + dtUint32 , + dtFloat32:Result:=(AsUint=0); + else + Result:=False; + end; +end; + +Function TsrConst.isBoolVal:Boolean; +begin + if (key.count<>0) then Exit(False); + Case Data 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; +var + i:DWORD; +begin + if (key.count<>0) then + For i:=0 to key.count-1 do + begin + GetCompItem(i)^.mark_read; + end; +end; + +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; + +Procedure TsrConst.Clear; +var + i:DWORD; +begin + if (key.count<>0) then + begin + For i:=0 to key.count-1 do + begin + GetCompItem(i)^.mark_unread; + end; + key.count:=0; + end; +end; + +function TsrConstList._Fetch(node:PsrConst):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); + FNTree.Insert(Result); + FList.Push_tail(Result); + end else + begin + node^._mark_unread_child; + end; +end; + +function TsrConstList.Fetch(dtype:TsrDataType;value:QWORD):PsrConst; +var + rec:record + node:TsrConst; + align:array[0..3] of Pointer; + end; + h:array[0..3] of PsrConst; +begin + Result:=nil; + rec.node:=Default(TsrConst); + + value:=value and GetTypeHigh(dtype); + + Case dtype of + dtUnknow, + dtBool, + dtFloat32, + dtHalf16, + dtInt32, + dtUint32, + dtInt64, + dtUint64: + + begin + rec.node.key.dtype:=dtype; + rec.node.Data:=value; + Result:=_Fetch(@rec.node); + Result^.mark_read; + end; + + dtStruct2u, + dtVec2u, + dtVec2i, + 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; + end; + + else + Assert(false); + end; + +end; + +function TsrConstList.Fetchb(value:Boolean):PsrConst; inline; +begin + Result:=Fetch(dtBool,QWORD(value)); +end; + +function TsrConstList.Fetchi(dtype:TsrDataType;value:Integer):PsrConst; inline; +begin + Result:=Fetch(dtype,PDWORD(@value)^); +end; + +Function TsrConstList.Fetchf(dtype:TsrDataType;value:Single):PsrConst; inline; +begin + Result:=Fetch(dtype,PDWORD(@value)^); +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); + 255:Result:=Fetch(dtUnknow,d2); + else + Result:=nil; + end; +end; + +function TsrConstList.Fetch_ssrc9_const(SSRC:Word;d2:DWORD;rtype:TsrDataType):PsrConst; +begin + Case SSRC of + 128:Result:=Fetch(rtype,0); + 129..192: + begin + if CompareType(dtUint32,rtype) then + begin + Result:=Fetch(dtUint32,SSRC-128); + end else + begin + Result:=Fetch(rtype,SSRC-128); + end; + end; + 193..208: + begin + if CompareType(dtInt32,rtype) then + begin + Result:=Fetchi(dtInt32,-(SSRC-192)); + end else + begin + Result:=Fetchi(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); + 255:Result:=Fetch(rtype,d2); + else + Result:=nil; + end; +end; + +function TsrConstList.Fetch_ssrc8_const(SSRC:Byte;d2:DWORD):PsrConst; inline; +begin + Result:=Fetch_ssrc9_const(SSRC,d2); +end; + +function TsrConstList.Fetch_ssrc8_const(SSRC:Byte;d2:DWORD;rtype:TsrDataType):PsrConst; inline; +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; +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; +end; + +function get_soffset_const_int(SSRC:Word):Integer; +type + TRec=packed record + Case byte of + 0:(i:Integer); + 1:(s:Single); + end; +begin + Case SSRC of + 128:Result:=0; + 129..192:Result:=SSRC-128; + 193..208:Result:=-(SSRC-192); + 240:TRec(Result).s:= 0.5; + 241:TRec(Result).s:=-0.5; + 242:TRec(Result).s:= 1.0; + 243:TRec(Result).s:=-1.0; + 244:TRec(Result).s:= 2.0; + 245:TRec(Result).s:=-2.0; + 246:TRec(Result).s:= 4.0; + 247:TRec(Result).s:=-4.0; + else + Result:=0; + end; +end; + +function is_const_soffset(SSRC:Byte):Boolean; inline; +begin + Case SSRC of + 128..192, + 193..208, + 240..247:Result:=True; + else + Result:=False; + end; +end; + +function is_const_ssrc8(SSRC:Byte):Boolean; inline; +begin + Case SSRC of + 128..192, + 193..208, + 240..247, + 255:Result:=True; + else + Result:=False; + end; +end; + +function is_const_ssrc9(SSRC:Word):Boolean; inline; +begin + Case SSRC of + 128..192, + 193..208, + 240..247, + 255:Result:=True; + else + Result:=False; + end; +end; + +function CompareConstCount(buf1,buf2:PPsrConst;count:PtrUint):Boolean; +begin + Result:=true; + While (count<>0) do + begin + Result:=CompareConst(buf1^,buf2^); + if not Result then Exit; + Inc(buf1); + Inc(buf2); + Dec(count); + end; +end; + +function CompareConst(r1,r2:PsrConst):Boolean; +begin + Result:=false; + if (r1<>nil) and (r2<>nil) then + begin + Result:=(r1=r2); + if Result then Exit; + if CompareType(r1^.key.dtype,r2^.key.dtype) and (r1^.key.count=r2^.key.count) then + begin + if (r1^.key.count=0) then + begin + Result:=(r1^.Data=r2^.Data); + end else + begin + Result:=CompareConstCount(@r1^.Data,@r2^.Data,r1^.key.count); + end; + end; + end; +end; + +end. + diff --git a/spirv/srDecorate.pas b/spirv/srDecorate.pas new file mode 100644 index 0000000..9ebc707 --- /dev/null +++ b/spirv/srDecorate.pas @@ -0,0 +1,80 @@ +unit srDecorate; + +{$mode ObjFPC}{$H+} + +interface + +uses + spirv, + srNodes, + srOp; + +type + 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); + end; + + PsrDebugInfoList=^TsrDebugInfoList; + TsrDebugInfoList=object(TsrOpBlockSimple) + procedure emit_source_extension(const n:RawByteString); + procedure emit_name(ntype:TsrNodeType;Data:Pointer;const n:RawByteString); + end; + +implementation + +procedure TsrDecorateList.emit_decorate(ntype:TsrNodeType;Data:Pointer;dec_id,param:DWORD); +var + node:PSpirvOp; +begin + node:=AddSpirvOp(Op.OpDecorate); + node^.AddParam(ntype,Data); + node^.AddLiteral(dec_id,Decoration.GetStr(dec_id)); + Case dec_id of + Decoration.BuiltIn: + node^.AddLiteral(param,BuiltIn.GetStr(param)); + + Decoration.ArrayStride, + Decoration.MatrixStride, + Decoration.Location, + Decoration.Index, + Decoration.Binding, + Decoration.DescriptorSet: + node^.AddLiteral(param); + + else; + end; +end; + +procedure TsrDecorateList.emit_member_decorate(ntype:TsrNodeType;Data:Pointer;index,offset:DWORD); +var + node:PSpirvOp; +begin + node:=AddSpirvOp(Op.OpMemberDecorate); + node^.AddParam(ntype,Data); + node^.AddLiteral(index); + node^.AddLiteral(Decoration.Offset,Decoration.GetStr(Decoration.Offset)); + node^.AddLiteral(offset); +end; + +procedure TsrDebugInfoList.emit_source_extension(const n:RawByteString); +var + node:PSpirvOp; +begin + node:=AddSpirvOp(Op.OpSourceExtension); + node^.AddString(n); +end; + +procedure TsrDebugInfoList.emit_name(ntype:TsrNodeType;Data:Pointer;const n:RawByteString); +var + node:PSpirvOp; +begin + node:=AddSpirvOp(Op.OpName); + node^.AddParam(ntype,Data); + node^.AddString(n); +end; + +end. + diff --git a/spirv/srFragLayout.pas b/spirv/srFragLayout.pas new file mode 100644 index 0000000..3d4c9d6 --- /dev/null +++ b/spirv/srFragLayout.pas @@ -0,0 +1,182 @@ +unit srFragLayout; + +{$mode ObjFPC}{$H+} + +interface + +uses + sysutils, + spirv, + srNodes, + srReg, + srOp, + srLayout, + srVariable, + srInput, + srDecorate; + +type + //itPerspSample, //Sample + //itPerspCenter, + //itPerspCentroid, //Centroid + //itLinearSample, //NoPerspective Sample + //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; + end; + + TsrFragLayoutList=object + type + TNodeFetch=specialize TNodeFetch<PsrFragLayout,TsrFragLayout>; + var + Alloc:TfnAlloc; + FNTree:TNodeFetch; + procedure Init(cb:TfnAlloc); + function Fetch(itype:TpsslInputType;location:DWORD):PsrFragLayout; + Function First:PsrFragLayout; + Function Next(node:PsrFragLayout):PsrFragLayout; + procedure AllocBinding(Decorates:PsrDecorateList); + procedure AllocEntryPoint(EntryPoint:PSpirvOp); + end; + +implementation + +function TsrFragLayout.c(n1,n2:PsrFragLayout):Integer; +begin + //first itype + Result:=Integer(n1^.itype>n2^.itype)-Integer(n1^.itype<n2^.itype); + //second location + Result:=Integer(n1^.FBinding>n2^.FBinding)-Integer(n1^.FBinding<n2^.FBinding); + //Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrFragLayout.key)); +end; + +function TsrFragLayout.GetName:RawByteString; +begin + Case itype of + itPerspSample: + Result:='itPSample'+IntToStr(FBinding); + itPerspCenter: + Result:='itParam'+IntToStr(FBinding); + itPerspCentroid: + Result:='itPCentroid'+IntToStr(FBinding); + itLinearSample: + Result:='itLSample'+IntToStr(FBinding); + itLinearCenter: + Result:='itLCenter'+IntToStr(FBinding); + itLinearCentroid: + Result:='itLCentroid'+IntToStr(FBinding); + else + Result:=''; + end; +end; + +procedure TsrFragLayoutList.Init(cb:TfnAlloc); +begin + Alloc:=cb; +end; + +function TsrFragLayoutList.Fetch(itype:TpsslInputType;location:DWORD):PsrFragLayout; +var + node:TsrFragLayout; +begin + node:=Default(TsrFragLayout); + node.itype:=itype; + node.FStorage:=StorageClass.Input; + node.FBinding:=location; + Result:=FNTree.Find(@node); + if (Result=nil) then + begin + Result:=Alloc(SizeOf(TsrFragLayout)); + Move(node,Result^,SizeOf(TsrFragLayout)); + FNTree.Insert(Result); + end; +end; + +Function TsrFragLayoutList.First:PsrFragLayout; +begin + Result:=FNTree.Min; +end; + +Function TsrFragLayoutList.Next(node:PsrFragLayout):PsrFragLayout; +begin + Result:=FNTree.Next(node); +end; + +procedure TsrFragLayoutList.AllocBinding(Decorates:PsrDecorateList); +var + node:PsrFragLayout; + pVar:PsrVariable; +begin + if (Decorates=nil) then Exit; + //interpolate param + node:=First; + While (node<>nil) do + begin + pVar:=node^.pVar; + if (pVar<>nil) then + begin + Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,node^.FBinding); + + case node^.itype of + itPerspSample: //Sample + begin + Decorates^.emit_decorate(ntVar,pVar,Decoration.Sample,0); + end; + itPerspCenter:; //default + itPerspCentroid: //Centroid + begin + Decorates^.emit_decorate(ntVar,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); + end; + itLinearCenter: //NoPerspective + begin + Decorates^.emit_decorate(ntVar,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); + end; + else + Assert(false,'AllocBinding'); + end; + + end; + node:=Next(node); + end; +end; + +procedure TsrFragLayoutList.AllocEntryPoint(EntryPoint:PSpirvOp); +var + node:PsrFragLayout; + pVar:PsrVariable; +begin + if (EntryPoint=nil) then Exit; + node:=First; + While (node<>nil) do + begin + pVar:=node^.pVar; + if (pVar<>nil) then + begin + EntryPoint^.AddParam(ntVar,pVar); + end; + node:=Next(node); + end; +end; + +end. + diff --git a/spirv/srInput.pas b/spirv/srInput.pas new file mode 100644 index 0000000..c17c508 --- /dev/null +++ b/spirv/srInput.pas @@ -0,0 +1,200 @@ +unit srInput; + +{$mode ObjFPC}{$H+} + +interface + +uses + typinfo, + sysutils, + spirv, + srNodes, + srReg, + srOp, + srLayout, + srVariable, + srDecorate; + +type + TpsslInputType=( + itUnknow, + + itVsState, + + itWriteIndex, + itOffset, + itWaveId, + itScratch, + + itVIndex, + itVInstance, + + itPsState, + itWaveCnt, + + itPerspSample, + itPerspCenter, + itPerspCentroid, + itPerspW, + itLinearSample, + itLinearCenter, + itLinearCentroid, + + itFloatPos, + itFrontFace, + itAncillary, + itSampleCoverage, + itPosFixed, + + itTgid, + itTgSize, + + itThreadId + + ); + + 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; + end; + + TsrInputList=object + type + TNodeFetch=specialize TNodeFetch<PsrInput,TsrInput>; + var + Alloc:TfnAlloc; + FNTree:TNodeFetch; + procedure Init(cb:TfnAlloc); + function Search(itype:TpsslInputType;id:Byte=0):PsrInput; + function Fetch(itype:TpsslInputType;id:Byte=0):PsrInput; + Function First:PsrInput; + Function Next(node:PsrInput):PsrInput; + procedure AllocBinding(Decorates:PsrDecorateList); + procedure AllocEntryPoint(EntryPoint:PSpirvOp); + end; + +implementation + +function TsrInput.c(n1,n2:PsrInput):Integer; +begin + Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrInput.key)); +end; + +function TsrInput.GetName:RawByteString; +begin + Result:=GetEnumName(TypeInfo(TpsslInputType),ord(key.itype))+IntToStr(key.typeid); +end; + +procedure TsrInputList.Init(cb:TfnAlloc); +begin + Alloc:=cb; +end; + +function TsrInputList.Search(itype:TpsslInputType;id:Byte=0):PsrInput; +var + node:TsrInput; +begin + node:=Default(TsrInput); + node.key.itype:=itype; + node.key.typeid:=id; + Result:=FNTree.Find(@node); +end; + +function TsrInputList.Fetch(itype:TpsslInputType;id:Byte=0):PsrInput; +var + node:TsrInput; +begin + node:=Default(TsrInput); + node.key.itype:=itype; + node.key.typeid:=id; + node.FStorage:=StorageClass.Input; + node.FBinding:=-1; + Result:=FNTree.Find(@node); + if (Result=nil) then + begin + Result:=Alloc(SizeOf(TsrInput)); + Move(node,Result^,SizeOf(TsrInput)); + FNTree.Insert(Result); + end; +end; + +Function TsrInputList.First:PsrInput; +begin + Result:=FNTree.Min; +end; + +Function TsrInputList.Next(node:PsrInput):PsrInput; +begin + Result:=FNTree.Next(node); +end; + +procedure TsrInputList.AllocBinding(Decorates:PsrDecorateList); +var + node:PsrInput; + pVar:PsrVariable; + +begin + if (Decorates=nil) then Exit; + node:=First; + While (node<>nil) do + begin + pVar:=node^.pVar; + if (pVar<>nil) then + begin + Case node^.key.itype of + itFloatPos: + begin + Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.FragCoord); + end; + itTgid: + begin + Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.WorkgroupId); + end; + itThreadId: + begin + Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.LocalInvocationID); + end; + itVIndex: + begin + Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.VertexIndex); + end; + else + Assert(false,'AllocBinding'); + end; + end; + node:=Next(node); + end; +end; + +procedure TsrInputList.AllocEntryPoint(EntryPoint:PSpirvOp); +var + node:PsrInput; + pVar:PsrVariable; +begin + if (EntryPoint=nil) then Exit; + node:=First; + While (node<>nil) do + begin + pVar:=node^.pVar; + if (pVar<>nil) then + begin + EntryPoint^.AddParam(ntVar,pVar); + end; + node:=Next(node); + end; +end; + +end. + diff --git a/spirv/srLabel.pas b/spirv/srLabel.pas new file mode 100644 index 0000000..c14834d --- /dev/null +++ b/spirv/srLabel.pas @@ -0,0 +1,111 @@ +unit srLabel; + +{$mode ObjFPC}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + srNodes; + +type + TSrcAdr=object + pBody:PDWORD; + Offdw:ptrint; + function get_pc:PDWORD; + end; + + TsrLCursor=object(TShaderParser) + private + function get_src_adr:TSrcAdr; + Procedure set_src_adr(src:TSrcAdr); + public + procedure Init(base:Pointer); + property Adr:TSrcAdr read get_src_adr write set_src_adr; + end; + + TsrLabelType=(ltBranch,ltUnknow,ltBegAdr,ltEndAdr,ltBegCond,ltEndCond,ltBegLoop,ltEndLoop); + + TsrSetLabelType=Set of TsrLabelType; + + TsrBlockType=(btMain,btAdr,btSetpc,btCond,btLoop,btOther); + + PsrLabel=^TsrLabel; + TsrLabel=object + pLeft,pRight:PsrLabel; + //---- + Adr:TSrcAdr; + lType:TsrSetLabelType; + function c(n1,n2:PsrLabel):Integer; static; + Procedure AddType(t:TsrLabelType); + Procedure RemType(t:TsrLabelType); + function IsType(t:TsrLabelType):Boolean; + end; + + TsrLabels=object + type + TNodeFetch=specialize TNodeFetch<PsrLabel,TsrLabel>; + var + FNTree:TNodeFetch; + end; + +function get_branch_offset(var FSPI:TSPI):ptrint; + +implementation + +function TSrcAdr.get_pc:PDWORD; +begin + Result:=pBody+Offdw; +end; + +procedure TsrLCursor.Init(base:Pointer); +begin + Body :=base; + OFFSET_DW:=0; +end; + +function TsrLCursor.get_src_adr:TSrcAdr; +begin + Result:=Default(TSrcAdr); + Result.pBody:=Body; + Result.Offdw:=OFFSET_DW; +end; + +Procedure TsrLCursor.set_src_adr(src:TSrcAdr); +begin + Body :=src.pBody; + OFFSET_DW:=src.Offdw; +end; + +function TsrLabel.c(n1,n2:PsrLabel):Integer; +var + p1,p2:Pointer; +begin + p1:=n1^.Adr.get_pc; + p2:=n2^.Adr.get_pc; + Result:=Integer(p1>p2)-Integer(p1<p2); +end; + +Procedure TsrLabel.AddType(t:TsrLabelType); +begin + lType:=lType+[t]; +end; + +Procedure TsrLabel.RemType(t:TsrLabelType); +begin + lType:=lType-[t]; +end; + +function TsrLabel.IsType(t:TsrLabelType):Boolean; +begin + Result:=t in lType; +end; + +function get_branch_offset(var FSPI:TSPI):ptrint; +begin + Result:=FSPI.OFFSET_DW+Smallint(FSPI.SOPP.SIMM)+1; +end; + +end. + diff --git a/spirv/srLayout.pas b/spirv/srLayout.pas new file mode 100644 index 0000000..447a735 --- /dev/null +++ b/spirv/srLayout.pas @@ -0,0 +1,515 @@ +unit srLayout; + +{$mode ObjFPC}{$H+} + +interface + +uses + ps4_shader, + srNodes, + srParser, + srCFG, + srTypes, + srReg, + srVariable, + srRefId, + srDecorate; + +type + TsrResourceType=( + rtBufPtr2, + rtFunPtr2, + rtVSharp4, + rtSSharp4, + rtTSharp4, + rtTSharp8 + ); + +type + PsrDataLayout=^TsrDataLayout; + + PsrChainExt=^TsrChainExt; + TsrChainExt=object + pIndex:PsrRegNode; + stride:PtrUint; + function c(n1,n2:PsrChainExt):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; + end; + + TsrChains=array[0..7] of PsrChain; + + //---- + + TsrDataLayout=object + type + TChainFetch=specialize TNodeFetch<PsrChain,TsrChain>; + var + pLeft,pRight:PsrDataLayout; + //---- + key:packed record + parent:PsrDataLayout; + offset:PtrUint; + rtype:TsrResourceType; + end; + pData:Pointer; + FID:Integer; + Alloc:TfnAlloc; + FList:TChainFetch; + function c(n1,n2:PsrDataLayout):Integer; static; + function Fetch(o,s:PtrUint;ext:PsrChainExt):PsrChain; + Function First:PsrChain; + Function Last:PsrChain; + Function Next(node:PsrChain):PsrChain; + Function Prev(node:PsrChain):PsrChain; + function GetData:Pointer; + function GetStride:PtrUint; + function GetTypeChar:Char; + function GetString:RawByteString; + function GetFuncString(LEN:DWORD):RawByteString; + end; + + TsrDataLayoutList=object + type + TNodeFetch=specialize TNodeFetch<PsrDataLayout,TsrDataLayout>; + var + FTop:TsrDataLayout; + FNTree:TNodeFetch; + procedure Init(cb:TfnAlloc); + procedure SetUserData(pData:Pointer); + 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; + Procedure AllocID; + procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList); + procedure AllocFuncExt(FDebugInfo:PsrDebugInfoList;var Heap:TsrCodeHeap); + end; + +//---- + + PsrDescriptor=^TsrDescriptor; + TsrDescriptor=object + pVar:PsrVariable; + FStorage:DWORD; + FBinding:Integer; + end; + +function is_consistents(const chains:TsrChains;count:Byte):Boolean; +function is_no_index_chains(const chains:TsrChains;count:Byte):Boolean; +function is_userdata_chains(const chains:TsrChains;count:Byte):Boolean; +function GetResourceSizeDw(r:TsrResourceType):Byte; + +implementation + +function TsrDataLayout.c(n1,n2:PsrDataLayout):Integer; +begin + //first parent + Result:=Integer(n1^.key.parent>n2^.key.parent)-Integer(n1^.key.parent<n2^.key.parent); + if (Result<>0) then Exit; + //second offset + Result:=Integer(n1^.key.offset>n2^.key.offset)-Integer(n1^.key.offset<n2^.key.offset); + if (Result<>0) then Exit; + //third rtype + Result:=Integer(n1^.key.rtype>n2^.key.rtype)-Integer(n1^.key.rtype<n2^.key.rtype); +end; + +function TsrDataLayout.Fetch(o,s:PtrUint;ext:PsrChainExt):PsrChain; +var + node:TsrChain; +begin + node:=Default(TsrChain); + node.key.offset:=o; + node.key.size :=s; + if (ext<>nil) then + begin + node.key.ext:=ext^; + 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'); + FList.Insert(Result); + end else + begin + if (ext<>nil) then + if (ext^.pIndex<>nil) then + begin + ext^.pIndex^.mark_unread; + end; + end; +end; + +Function TsrDataLayout.First:PsrChain; +begin + Result:=FList.Min; +end; + +Function TsrDataLayout.Last:PsrChain; +begin + Result:=FList.Max; +end; + +Function TsrDataLayout.Next(node:PsrChain):PsrChain; +begin + Result:=FList.Next(node); +end; + +Function TsrDataLayout.Prev(node:PsrChain):PsrChain; +begin + Result:=FList.Prev(node); +end; + +function TsrDataLayout.GetData:Pointer; +begin + Result:=nil; + if (pData<>nil) then + Case key.rtype of + rtBufPtr2, + rtFunPtr2:Result:=pData; + rtVSharp4:Result:={%H-}Pointer(PVSharpResource4(pData)^.base); + rtTSharp4, + rtTSharp8:Result:={%H-}Pointer(PTSharpResource4(pData)^.base shl 8); + else; + end; +end; + +function TsrDataLayout.GetStride:PtrUint; +begin + Result:=0; + if (pData<>nil) then + Case key.rtype of + rtBufPtr2:Result:=4; + rtVSharp4:Result:=PVSharpResource4(pData)^.stride; + else; + end; +end; + +function TsrDataLayout.GetTypeChar:Char; +begin + Result:=#0; + case key.rtype of + rtBufPtr2:Result:='B'; + rtFunPtr2:Result:='F'; + rtVSharp4:Result:='V'; + rtSSharp4:Result:='S'; + rtTSharp4:Result:='t'; + rtTSharp8:Result:='T'; + end; +end; + +function TsrDataLayout.GetString:RawByteString; +var + PID:DWORD; +begin + PID:=0; + if (key.parent<>nil) then + begin + PID:=key.parent^.FID; + end; + Result:='#'+GetTypeChar+ + ';PID='+HexStr(PID,8)+ + ';OFS='+HexStr(key.offset,8); +end; + +function TsrDataLayout.GetFuncString(LEN:DWORD):RawByteString; +begin + Result:='FF'+ + ';PID='+HexStr(FID,8)+ + ';LEN='+HexStr(LEN,8); +end; + +procedure TsrDataLayoutList.Init(cb:TfnAlloc); +begin + FTop.Alloc:=cb; + FNTree.Insert(@FTop); +end; + +procedure TsrDataLayoutList.SetUserData(pData:Pointer); +begin + FTop.pData:=pData; +end; + +function TsrDataLayoutList.Fetch(p:PsrDataLayout;o:PtrUint;t:TsrResourceType):PsrDataLayout; +var + node:TsrDataLayout; + pData:Pointer; +begin + node:=Default(TsrDataLayout); + node.Alloc:=FTop.Alloc; + 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)); + 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; + + end; +end; + +Function TsrDataLayoutList.First:PsrDataLayout; +begin + Result:=FNTree.Min; +end; + +Function TsrDataLayoutList.Next(node:PsrDataLayout):PsrDataLayout; +begin + Result:=FNTree.Next(node); +end; + +function GetResourceSizeDw(r:TsrResourceType):Byte; +begin + Result:=0; + Case r of + rtBufPtr2:Result:=2; + rtFunPtr2:Result:=2; + rtVSharp4:Result:=4; + rtSSharp4:Result:=4; + rtTSharp4:Result:=4; + rtTSharp8:Result:=8; + end; +end; + +function TsrDataLayoutList.Grouping(const chain:TsrChains;rtype:TsrResourceType):PsrDataLayout; +begin + Result:=nil; + + if not is_consistents(chain,GetResourceSizeDw(rtype)) then + begin + Assert(False,'inconsistent resources not supported'); + end; + + if not is_no_index_chains(chain,GetResourceSizeDw(rtype)) then + begin + Assert(False,'indexed chain not support'); + end; + + Result:=Fetch(chain[0]^.parent,chain[0]^.key.offset,rtype); +end; + +Procedure TsrDataLayoutList.AllocID; +var + node:PsrDataLayout; + FID:Integer; +begin + FID:=1; + node:=First; + While (node<>nil) do + begin + if (node^.FID=-1) then + begin + node^.FID:=FID; + Inc(FID); + end; + node:=Next(node); + end; +end; + +procedure TsrDataLayoutList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList); +var + node:PsrDataLayout; +begin + if (FDebugInfo=nil) then Exit; + node:=First; + While (node<>nil) do + begin + FDebugInfo^.emit_source_extension(node^.GetString); + node:=Next(node); + end; +end; + +procedure TsrDataLayoutList.AllocFuncExt(FDebugInfo:PsrDebugInfoList;var Heap:TsrCodeHeap); +var + node:PsrDataLayout; + block:PsrCodeBlock; +begin + node:=First; + While (node<>nil) do + begin + if (node^.key.rtype=rtFunPtr2) then + begin + block:=Heap.FindByPtr(node^.pData); + if (block<>nil) then + begin + FDebugInfo^.emit_source_extension(node^.GetFuncString(block^.Size)); + end; + end; + node:=Next(node); + end; +end; + +function TsrChainExt.c(n1,n2:PsrChainExt):Integer; +begin + //first pIndex forward + Result:=Integer(n1^.pIndex>n2^.pIndex)-Integer(n1^.pIndex<n2^.pIndex); + if (Result<>0) then Exit; + + //second stride forward + Result:=Integer(n1^.stride>n2^.stride)-Integer(n1^.stride<n2^.stride); +end; + +function TsrChain.c(n1,n2:PsrChain):Integer; +begin + //first ext + Result:=TsrChainExt.c(@n1^.key.ext,@n2^.key.ext); + if (Result<>0) then Exit; + + //second size backward + Result:=Integer(n1^.key.size<n2^.key.size)-Integer(n1^.key.size>n2^.key.size); + if (Result<>0) then Exit; + + //third offset forward + Result:=Integer(n1^.key.offset>n2^.key.offset)-Integer(n1^.key.offset<n2^.key.offset); +end; + +Procedure TsrChain.mark_read; +begin + Inc(read_count); +end; + +Procedure TsrChain.mark_unread; +begin + if (read_count<>0) then Dec(read_count); +end; + +Procedure TsrChain.mark_write; +begin + Inc(write_count); +end; + +Procedure TsrChain.SetRegType(rtype:TsrDataType); +var + node:PsrRegNode; +begin + node:=rSlot.pStory.pHead; + While (node<>nil) do + begin + node^.dtype:=rtype; + node:=node^.pNext; + end; +end; + +function TsrChain.GetRegType:TsrDataType; +var + pReg:PsrRegNode; +begin + Result:=dtUnknow; + pReg:=rSlot.current; + if (pReg=nil) then Exit; + Result:=pReg^.dtype; +end; + +function TsrChain.IsUsed:Boolean; +begin + Result:=((read_count<>0) or + (write_count<>0)) and + (rSlot.current<>nil); +end; + +function is_consistents(const chains:TsrChains;count:Byte):Boolean; +var + parent:PsrDataLayout; + offset,t:PtrUint; + i:Byte; +begin + offset:=0; + t:=0; + if (count<2) then Exit(True); + Result:=False; + if (chains[0]=nil) then Exit; + parent:=chains[0]^.parent; + offset:=chains[0]^.key.offset; + For i:=1 to count-1 do + begin + t:=chains[i-1]^.key.size; + offset:=offset+t; + if (chains[i]=nil) then Exit; + if (chains[i]^.parent<>parent) then Exit; + t:=chains[i]^.key.offset; + if (offset<>t) then Exit; + end; + Result:=True; +end; + +function is_no_index_chains(const chains:TsrChains;count:Byte):Boolean; +var + i:Byte; +begin + Result:=False; + if (count=0) then Exit; + For i:=0 to count-1 do + begin + if (chains[i]=nil) then Exit; + if (chains[i]^.key.ext.pIndex<>nil) then Exit; + end; + Result:=True; +end; + +function is_userdata_chains(const chains:TsrChains;count:Byte):Boolean; +var + parent:PsrDataLayout; + i:Byte; +begin + Result:=False; + if (count=0) then Exit; + For i:=0 to count-1 do + begin + if (chains[i]=nil) then Exit; + parent:=chains[i]^.parent; + if (parent=nil) then Exit; + if (parent^.key.parent<>nil) then Exit; + end; + Result:=True; +end; + +end. + diff --git a/spirv/srNodes.pas b/spirv/srNodes.pas new file mode 100644 index 0000000..ee37f35 --- /dev/null +++ b/spirv/srNodes.pas @@ -0,0 +1,570 @@ +unit srNodes; + +{$mode objfpc}{$H+} + +interface + +type + generic TNodeStack<PNode>=object + pHead:PNode; + procedure Push_head(Node:PNode); + function Pop_head:PNode; + procedure Move_from(var s:TNodeStack); + end; + + generic TNodeQueue<PNode>=object + pHead,pTail:PNode; + procedure Push_head(Node:PNode); + procedure Push_tail(Node:PNode); + function Pop_head:PNode; + procedure InsertAfter(node,new:PNode); + end; + + generic TNodeList<PNode>=object + pHead,pTail:PNode; + procedure Push_head(Node:PNode); + procedure Push_tail(Node:PNode); + function Pop_head:PNode; + function Pop_tail:PNode; + procedure InsertAfter(node,new:PNode); + procedure InsertBefore(node,new:PNode); + procedure Remove(node:PNode); + end; + + generic TNodeFetch<PNode,TNode>=object + var + pRoot:PNode; + function _Splay(node:PNode):Integer; + function Min:PNode; + function Max:PNode; + function Next(node:PNode):PNode; + function Prev(node:PNode):PNode; + function Find(node:PNode):PNode; + function Find_be(node:PNode):PNode; + function Find_le(node:PNode):PNode; + 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 ComparePtruint(buf1,buf2:PPtruint;count:PtrUint):Integer; + +implementation + +function TNodeFetch._Splay(node:PNode):Integer; +var + aux:TNode; + t,l,r,y:PNode; +begin + t:=pRoot; + l:=@aux; + r:=@aux; + aux.pLeft:=nil; + aux.pRight:=nil; + while (true) do + begin + Result:=TNode.c(t,node); + if (Result=0) then Break; + if (Result>0) then + begin + if (t^.pLeft=nil) then break; + if (TNode.c(node,t^.pLeft)<0) then + begin + y:=t^.pLeft; // rotate pRight + t^.pLeft:=y^.pRight; + y^.pRight:=t; + t:=y; + if (t^.pLeft=nil) then break; + end; + r^.pLeft:=t; // link pRight + r:=t; + t:=t^.pLeft; + end else + begin + if (t^.pRight=nil) then break; + if (TNode.c(node,t^.pRight)>0) then + begin + y:=t^.pRight; // rotate pLeft + t^.pRight:=y^.pLeft; + y^.pLeft:=t; + t:=y; + if (t^.pRight=nil) then break; + end; + l^.pRight:=t; // link pLeft + l:=t; + t:=t^.pRight; + end; + end; + l^.pRight:=t^.pLeft; // assemble + r^.pLeft :=t^.pRight; + t^.pLeft :=aux.pRight; + t^.pRight:=aux.pLeft; + pRoot:=t; +end; + +function TNodeFetch.Min:PNode; +var + node:PNode; +begin + Result:=nil; + node:=pRoot; + While (node<>nil) do + begin + Result:=node; + node:=node^.pLeft; + end; +end; + +function TNodeFetch.Max:PNode; +var + node:PNode; +begin + Result:=nil; + node:=pRoot; + While (node<>nil) do + begin + Result:=node; + node:=node^.pRight; + end; +end; + +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; + node:=node^.pRight; + While (node<>nil) do + begin + Result:=node; + node:=node^.pLeft; + end; +end; + +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; + node:=node^.pLeft; + While (node<>nil) do + begin + Result:=node; + node:=node^.pRight; + end; +end; + +function TNodeFetch.Find(node:PNode):PNode; +begin + Result:=nil; + if (pRoot=nil) or (node=nil) then Exit; + if (_Splay(node)=0) then Result:=pRoot; +end; + +function TNodeFetch.Find_be(node:PNode):PNode; +begin + Result:=nil; + if (pRoot=nil) or (node=nil) then Exit; + if (_Splay(node)<0) then + begin + Result:=Next(pRoot); + end else + begin + Result:=pRoot; + end; +end; + +function TNodeFetch.Find_le(node:PNode):PNode; +begin + Result:=nil; + if (pRoot=nil) or (node=nil) then Exit; + if (_Splay(node)>0) then + begin + Result:=Prev(pRoot); + end else + begin + Result:=pRoot; + end; +end; + +procedure TNodeFetch.Insert(new:PNode); +var + c:Integer; +begin + if (new=nil) then Exit; + if (pRoot=nil) then + begin + pRoot:=new; + end else + begin + c:=TNode.c(pRoot,new); + if (c<>0) then + begin + if (c<0) then + begin + new^.pRight:=pRoot^.pRight; + new^.pLeft :=pRoot; + pRoot^.pRight:=nil; + end else + begin + new^.pLeft :=pRoot^.pLeft; + new^.pRight:=pRoot; + pRoot^.pLeft:=nil; + end; + pRoot:=new; + end; + end; +end; + +//-- + +procedure TNodeStack.Push_head(Node:PNode); +begin + if (pHead=nil) then + begin + node^.pNext:=nil; + end else + begin + node^.pNext:=pHead; + end; + pHead:=node; +end; + +function TNodeStack.Pop_head:PNode; +begin + Result:=pHead; + if (pHead<>nil) then + begin + pHead:=pHead^.pNext; + end; + if (Result<>nil) then + begin + Result^.pNext:=nil; + end; +end; + +procedure TNodeStack.Move_from(var s:TNodeStack); +var + node:PNode; +begin + repeat + node:=s.Pop_head; + if (node=nil) then Break; + Push_head(node); + until false; +end; + +//-- + +procedure TNodeQueue.Push_head(Node:PNode); +begin + if (pHead=nil) then + begin + pTail:=node; + node^.pNext:=nil; + end else + begin + node^.pNext:=pHead; + end; + pHead:=node; +end; + +procedure TNodeQueue.Push_tail(Node:PNode); +begin + if (pTail=nil) then + begin + pHead:=node; + node^.pNext:=nil; + end else + begin + pTail^.pNext:=node; + end; + pTail:=node; +end; + +function TNodeQueue.Pop_head:PNode; +begin + if (pHead=nil) then + begin + Result:=nil; + end else + begin + Result:=pHead; + pHead:=pHead^.pNext; + if (pHead=nil) then + begin + pTail:=nil; + end; + Result^.pNext:=nil; + end; +end; + +procedure TNodeQueue.InsertAfter(node,new:PNode); +begin + if (node^.pNext=nil) then + begin + new^.pNext:=nil; + pTail:=new; + end else + begin + new^.pNext:=node^.pNext; + end; + node^.pNext:=new; +end; + +//-- + +procedure TNodeList.Push_head(Node:PNode); +begin + if (pHead=nil) then + begin + pTail:=node; + node^.pNext:=nil; + end else + begin + pHead^.pPrev:=node; + node^.pNext:=pHead; + end; + node^.pPrev:=nil; + pHead:=node; +end; + +procedure TNodeList.Push_tail(Node:PNode); +begin + if (pTail=nil) then + begin + pHead:=node; + node^.pPrev:=nil; + end else + begin + pTail^.pNext:=node; + node^.pPrev:=pTail; + end; + node^.pNext:=nil; + pTail:=node; +end; + +function TNodeList.Pop_head:PNode; +begin + if (pHead=nil) then + begin + Result:=nil; + end else + begin + Result:=pHead; + pHead:=pHead^.pNext; + if (pHead=nil) then + begin + pTail:=nil; + end else + begin + pHead^.pPrev:=nil; + end; + Result^.pPrev:=nil; + Result^.pNext:=nil; + end; +end; + +function TNodeList.Pop_tail:PNode; +begin + if (pTail=nil) then + begin + Result:=nil; + end else + begin + Result:=pTail; + pTail:=pTail^.pPrev; + if (pTail=nil) then + begin + pHead:=nil; + end else + begin + pTail^.pNext:=nil; + end; + Result^.pPrev:=nil; + Result^.pNext:=nil; + end; +end; + +procedure TNodeList.InsertAfter(node,new:PNode); +begin + new^.pPrev:=node; + if (node^.pNext=nil) then + begin + new^.pNext:=nil; + pTail:=new; + end else + begin + new^.pNext:=node^.pNext; + node^.pNext^.pPrev:=new; + end; + node^.pNext:=new; +end; + +procedure TNodeList.InsertBefore(node,new:PNode); +begin + new^.pNext:=node; + if (node^.pPrev=nil) then + begin + new^.pPrev:=nil; + pHead:=new; + end else + begin + new^.pPrev:=node^.pPrev; + node^.pPrev^.pNext:=new; + end; + node^.pPrev:=new; +end; + +procedure TNodeList.Remove(node:PNode); +begin + if (node^.pPrev=nil) then + begin + if (pHead=node) then + begin + pHead:=node^.pNext; + end; + end else + begin + node^.pPrev^.pNext:=node^.pNext; + end; + if (node^.pNext=nil) then + begin + if (pTail=node) then + begin + pTail:=node^.pPrev; + end; + end else + begin + node^.pNext^.pPrev:=node^.pPrev; + end; +end; + +procedure TOpParamSingle.SetParam(_ntype:TsrNodeType;_Data:Pointer); +begin + ntype:=_ntype; + pData:=_Data; +end; + +function TOpParamSingle.AsConst:Pointer; +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; +end; + +function ComparePtruint(buf1,buf2:PPtruint;count:PtrUint):Integer; +begin + Result:=0; + While (count<>0) do + begin + Result:=Integer(buf1^>buf2^)-Integer(buf1^<buf2^); + if (Result<>0) then Exit; + Inc(buf1); + Inc(buf2); + Dec(count); + end; +end; + +end. + diff --git a/spirv/srOp.pas b/spirv/srOp.pas new file mode 100644 index 0000000..e6e4a9e --- /dev/null +++ b/spirv/srOp.pas @@ -0,0 +1,534 @@ +unit srOp; + +{$mode objfpc}{$H+} + +interface + +uses + srNodes, + srLabel, + srCFG, + srParser, + srTypes, + srRefId, + srReg; + +type + POpParamNode=^TOpParamNode; + TOpParamNode=packed record + pNext:POpParamNode; + //---- + ntype:TsrNodeType; + Case Byte of + 0:(pData:Pointer); + 1:(Value:DWORD;name:record end); + end; + + TOpParamQueue=specialize TNodeQueue<POpParamNode>; + + 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); + end; + + TsrVolMark=(vmNone,vmEnd,vmBreak,vmCont); + + TsrBlockInfo=packed record + b_adr,e_adr:TSrcAdr; + bType:TsrBlockType; + end; + + TsrOpList=specialize TNodeList<PspirvOp>; + + TsrOpBlockSimple=object(TsrOpList) + Alloc:TfnAlloc; + procedure Init(cb:TfnAlloc); + function NewSpirvOp(OpId:DWORD):PSpirvOp; + function AddSpirvOp(node:PSpirvOp):PSpirvOp; + function AddSpirvOp(OpId:DWORD):PSpirvOp; + end; + + TsrOpBlock=object(TsrOpBlockSimple) + pParent:PsrOpBlock; + pUpLine:PSpirvOp; //from post + + Block:TsrBlockInfo; + + Labels:record + pBegOp:PspirvOp; + pEndOp:PspirvOp; + pMrgOp:PspirvOp; + end; + + FCursor:TsrCursor; + + Regs:record + pSnap:PsrRegsSnapshot; + FVolMark:TsrVolMark; + end; + + Cond:record + pReg:PsrRegNode; + FVal:Boolean; + FUseCont:Boolean; + end; + + FLevel:DWORD; + + 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; + 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; + end; + + TsrFuncList=object + type + TNodeList=specialize TNodeList<PSpirvFunc>; + TNodeFetch=specialize TNodeFetch<PSpirvFunc,TSpirvFunc>; + var + FList:TNodeList; + FNTree:TNodeFetch; + function Search(const name:RawByteString):PSpirvFunc; + procedure Insert(new:PSpirvFunc); + 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<PsrCacheOp,TsrCacheOp>; + var + Alloc:TfnAlloc; + FNTree:TNodeFetch; + function Fetch(place:PsrOpBlock;OpId:DWORD;rtype:TsrDataType;count:Byte;src:PPsrRegNode):PsrCacheOp; + end; + +implementation + +uses + SprvEmit; + +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; +end; + +procedure TspirvOp.Remove; +begin + Assert(pParent<>nil); + pParent^.Remove(@Self); + pParent:=nil; +end; + +function TspirvOp.ParamNode(i:Byte):POpParamNode; +var + node:POpParamNode; +begin + Result:=nil; + node:=pParam.pHead; + While (node<>nil) do + begin + if (i=0) then Exit(node); + Dec(i); + node:=node^.pNext; + end; +end; + +procedure TspirvOp.AddParam(const s:TOpParamSingle); +var + node:POpParamNode; +begin + node:=pParent^.Alloc(SizeOf(TOpParamNode)); + node^.ntype:=s.ntype; + node^.pData:=s.pData; + pParam.Push_tail(node); +end; + +procedure TspirvOp.AddParam(ntype:TsrNodeType;Data:Pointer); +var + node:POpParamNode; +begin + node:=pParent^.Alloc(SizeOf(TOpParamNode)); + node^.ntype:=ntype; + node^.pData:=Data; + pParam.Push_tail(node); +end; + +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); +end; + +procedure TspirvOp.AddLiteral(Value:PtrUint;const name:RawByteString=''); +var + node:POpParamNode; + l:ptruint; +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); +end; + +procedure TspirvOp.AddString(const name:RawByteString); +var + node:POpParamNode; + l:ptruint; +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); +end; + +Procedure TspirvOp.SetDstReg(r:Pointer); +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 + begin + Result:=pTail; + end; +end; + +procedure TsrOpBlock.SetCFGBlock(pLBlock:PsrCFGBlock); +begin + dummy.Adr :=pLBlock^.pBLabel^.Adr; + Block.b_adr:=pLBlock^.pBLabel^.Adr; + Block.e_adr:=pLBlock^.pELabel^.Adr; + Block.bType:=pLBlock^.bType; +end; + +procedure TsrOpBlock.SetInfo(const b:TsrBlockInfo); +begin + dummy.Adr :=b.b_adr; + Block.b_adr:=b.b_adr; + Block.e_adr:=b.e_adr; + Block.bType:=b.bType; +end; + +procedure TsrOpBlock.SetInfo(bType:TsrBlockType;b_adr,e_adr:TSrcAdr); +begin + dummy.Adr :=b_adr; + Block.b_adr:=b_adr; + Block.e_adr:=e_adr; + Block.bType:=bType; +end; + +procedure TsrOpBlock.SetLabels(pBegOp,pEndOp,pMrgOp:PspirvOp); +begin + Labels.pBegOp:=pBegOp; + Labels.pEndOp:=pEndOp; + Labels.pMrgOp:=pMrgOp; +end; + +procedure TsrOpBlock.SetCond(pReg:PsrRegNode;FVal:Boolean); +begin + Cond.pReg:=pReg; + Cond.FVal:=FVal; +end; + +function TsrOpBlock.IsEndOf(Adr:TSrcAdr):Boolean; +begin + Result:=(Block.e_adr.get_pc<=Adr.get_pc); +end; + +function TsrOpBlock.FindUpLoop:PsrOpBlock; +var + node:PsrOpBlock; +begin + Result:=nil; + node:=@Self; + While (node<>nil) do + begin + if (node^.Block.bType=btLoop) then Exit(node); + node:=node^.pParent; + end; +end; + +function TsrOpBlock.FindUpCond(pReg:PsrRegNode):PsrOpBlock; +var + node:PsrOpBlock; +begin + Result:=nil; + if (pReg=nil) then Exit; + pReg:=RegDown(pReg); + if pReg^.is_const then Exit; + node:=@Self; + While (node<>nil) do + begin + if (node^.Block.bType=btCond) and (pReg=RegDown(node^.Cond.pReg)) then Exit(node); + node:=node^.pParent; + end; +end; + +function TSpirvFunc.c(n1,n2:PSpirvFunc):Integer; +var + count1,count2:sizeint; +begin + Count1:=Length(n1^.name); + Count2:=Length(n2^.name); + Result:=Integer(Count1>Count2)-Integer(Count1<Count2); + if (Result=0) then + begin + Result:=CompareByte(PChar(n1^.name)^,PChar(n2^.name)^,Count1); + end; +end; + +Procedure TSpirvFunc.PushBlock(New:PsrOpBlock); +begin + if (New=nil) then Exit; + New^.pParent:=pBlock; + New^.FLevel :=pBlock^.FLevel+1; + pBlock:=New; +end; + +function TSpirvFunc.PopBlock:Boolean; +begin + Result:=False; + if (pBlock=nil) then Exit; + if (pBlock^.pParent=nil) then Exit; + pBlock:=pBlock^.pParent; + Result:=True; +end; + +function TSpirvFunc.line:PSpirvOp; +begin + Result:=nil; + if (pBlock<>nil) then + begin + Result:=pBlock^.pTail; + end; +end; + +Procedure TSpirvFunc.Init(const fname:RawByteString;Alloc:TfnAlloc); +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); +end; + +function TSpirvFunc.NewSpirvOp(OpId:DWORD):PSpirvOp; +begin + Result:=FTop.Alloc(SizeOf(TSpirvOp)); + Result^.OpId:=OpId; +end; + +function TSpirvFunc.AddSpirvOp(node:PSpirvOp):PSpirvOp; +begin + Result:=node; + if (node=nil) then Exit; + pBlock^.Push_tail(node); + node^.pParent:=pBlock; +end; + +function TSpirvFunc.AddSpirvOp(OpId:DWORD):PSpirvOp; +begin + Result:=AddSpirvOp(NewSpirvOp(OpId)); +end; + +// + +procedure TsrOpBlockSimple.Init(cb:TfnAlloc); +begin + Alloc:=cb; +end; + +function TsrOpBlockSimple.NewSpirvOp(OpId:DWORD):PSpirvOp; +begin + Result:=Alloc(SizeOf(TSpirvOp)); + Result^.OpId:=OpId; +end; + +function TsrOpBlockSimple.AddSpirvOp(node:PSpirvOp):PSpirvOp; +begin + Result:=node; + if (node=nil) then Exit; + Push_tail(node); + node^.pParent:=@Self; +end; + +function TsrOpBlockSimple.AddSpirvOp(OpId:DWORD):PSpirvOp; +begin + Result:=AddSpirvOp(NewSpirvOp(OpId)); +end; + +// + +function TsrFuncList.Search(const name:RawByteString):PSpirvFunc; +var + node:TSpirvFunc; +begin + node:=Default(TSpirvFunc); + node.name:=name; + Result:=FNTree.Find(@node); +end; + +procedure TsrFuncList.Insert(new:PSpirvFunc); +begin + FNTree.Insert(new); + FList.Push_head(new); +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^.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); + end; +end; + +end. + diff --git a/spirv/srOpUtils.pas b/spirv/srOpUtils.pas new file mode 100644 index 0000000..8ada5cc --- /dev/null +++ b/spirv/srOpUtils.pas @@ -0,0 +1,357 @@ +unit srOpUtils; + +{$mode objfpc}{$H+} +{$MODESWITCH ADVANCEDRECORDS} + +interface + +uses + spirv, + srNodes, + srTypes, + srReg, + srConst, + srLayout, + srVariable, + srOp; + +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 + + OpCUBEID =DWORD(-10); + OpCUBESC =DWORD(-11); + OpCUBETC =DWORD(-12); + OpCUBEMA =DWORD(-13); + + OpMakeCM =DWORD(-14); + +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; + +function InsSpirvOp(pLine,pNew:PspirvOp):PSpirvOp; +Procedure MarkUnreadParamSingle(const node:TOpParamSingle); +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); +function FindUpSameOp(pLine,node:PspirvOp):PspirvOp; + +function GreaterThanLine(p1,p2:PspirvOp):Boolean; //(p1>p2) +function GetMaxPlace(pLine:PSpirvOp;count:Byte;src:PPsrRegNode):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; +begin + Result:=nil; + Assert(pLine<>nil); + if (pLine=nil) or (pNew=nil) then Exit; + + if (pLine^.pNext<>nil) then + begin + pNew^.adr:=pLine^.adr; + end; + + pLine^.InsertAfter(pNew); + Result:=pNew; +end; + +Procedure MarkUnreadParamSingle(const node:TOpParamSingle); +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); + end; +end; + +function GreaterThanLine(p1,p2:PspirvOp):Boolean; //(p1>p2) +begin + Result:=False; + p2:=p2^.pNext; + While (p2<>nil) do + begin + if (p1=p2) then Exit(True); + p2:=p2^.pNext; + end; +end; + +Function ParentOf(pLine,pCurr:PsrOpBlock):Boolean; +begin + Result:=False; + While (pLine<>nil) do + begin + if (pLine=pCurr) then Exit(True); + pLine:=pLine^.pParent; + end; +end; + +function GetMaxPlace(pLine:PSpirvOp;count:Byte;src:PPsrRegNode):PSpirvOp; +var + m,t:PSpirvOp; + i:Byte; +begin + Result:=pLine; + if (count=0) or (src=nil) then Exit; + m:=nil; + For i:=0 to count-1 do + begin + t:=src[i]^.pLine; + if not src[i]^.is_const then + if ParentOf(pLine^.pParent,t^.pParent) then + begin + if (m=nil) then + begin + m:=t; + end else + if (m^.pParent=t^.pParent) then + begin + if GreaterThanLine(t,m) then + begin + m:=t; + end; + end else + if (t^.pParent^.FLevel>m^.pParent^.FLevel) then + begin + m:=t; + end; + end; + end; + if (m<>nil) then + begin + Result:=m; + end; +end; + +Function get_inverse_cmp_op(OpId:DWORD):DWORD; +begin + Result:=0; + Case OpId of + Op.OpFOrdLessThan :Result:=Op.OpFOrdGreaterThan ; + Op.OpFOrdEqual :Result:=Op.OpFOrdEqual ; + Op.OpFOrdLessThanEqual :Result:=Op.OpFOrdGreaterThanEqual ; + Op.OpFOrdGreaterThan :Result:=Op.OpFOrdLessThan ; + Op.OpFOrdNotEqual :Result:=Op.OpFOrdNotEqual ; + Op.OpFOrdGreaterThanEqual :Result:=Op.OpFOrdLessThanEqual ; + Op.OpOrdered :Result:=Op.OpOrdered ; + Op.OpUnordered :Result:=Op.OpUnordered ; + Op.OpFUnordLessThan :Result:=Op.OpFUnordGreaterThan ; + Op.OpFUnordEqual :Result:=Op.OpFUnordEqual ; + Op.OpFUnordLessThanEqual :Result:=Op.OpFUnordGreaterThanEqual; + Op.OpFUnordGreaterThan :Result:=Op.OpFUnordLessThan ; + Op.OpFUnordNotEqual :Result:=Op.OpFUnordNotEqual ; + Op.OpFUnordGreaterThanEqual:Result:=Op.OpFUnordLessThanEqual ; + + Op.OpSLessThan :Result:=Op.OpSGreaterThan ; + Op.OpIEqual :Result:=Op.OpIEqual ; + Op.OpSLessThanEqual :Result:=Op.OpSGreaterThanEqual ; + Op.OpSGreaterThan :Result:=Op.OpSLessThan ; + Op.OpINotEqual :Result:=Op.OpINotEqual ; + Op.OpSGreaterThanEqual :Result:=Op.OpSLessThanEqual ; + + Op.OpULessThan :Result:=Op.OpUGreaterThan ; + Op.OpULessThanEqual :Result:=Op.OpUGreaterThanEqual ; + Op.OpUGreaterThan :Result:=Op.OpULessThan ; + Op.OpUGreaterThanEqual :Result:=Op.OpULessThanEqual ; + else + Assert(false); + end; +end; + +Function is_term_op(OpId:DWORD):Boolean; +begin + Case OpId of + Op.OpBranch, + Op.OpBranchConditional, + Op.OpSwitch, + Op.OpReturn, + Op.OpReturnValue, + Op.OpKill, + Op.OpTerminateInvocation, + Op.OpDemoteToHelperInvocation, + Op.OpUnreachable:Result:=True; + else + Result:=False; + end; +end; + +Function is_merge_op(OpId:DWORD):Boolean; +begin + Case OpId of + Op.OpSelectionMerge, + Op.OpLoopMerge:Result:=True; + else + Result:=False; + end; +end; + +Function is_term_op(pLine:PspirvOp):Boolean; +begin + Result:=False; + 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; + end; + if (pLine=nil) then Exit; + until false; + + Result:=is_term_op(pLine^.OpId); +end; + +procedure _up_merge_line(var pLine:PspirvOp); +begin + repeat + if is_merge_op(pLine^.OpId) then + begin + pLine:=pLine^.pPrev; + Assert(pLine<>nil); + end else + begin + Break; + end; + until false; +end; + +function CompareParam(p1,p2:POpParamNode):Boolean; +begin + Result:=(p1^.ntype=p2^.ntype) and (p1^.pData=p2^.pData); +end; + +function CompareOp(p1,p2:PspirvOp):Boolean; +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; + + While (n1<>nil) do + begin + if (n2=nil) then Exit; + if not CompareParam(n1,n2) then Exit; + n1:=n1^.pNext; + n2:=n2^.pNext; + 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 + begin + pBlock:=pLine^.pParent; + if (pBlock=nil) then Exit; + tmp:=pBlock^.pUpLine; + if (tmp=nil) then + begin + pBlock:=pBlock^.pParent; + if (pBlock=nil) then Exit; + tmp:=pBlock^.pHead; + While (tmp<>nil) do + begin + if (tmp^.OpId=OpBlock) and (tmp^.dst.pData=pBlock) then + begin + tmp:=tmp^.pPrev; + Break; + end; + tmp:=tmp^.pNext; + end; + end else + begin + tmp:=tmp^.pPrev; + end; + end; + pLine:=tmp; + end; +end; + + +end. + diff --git a/spirv/srOutput.pas b/spirv/srOutput.pas new file mode 100644 index 0000000..2b84e7a --- /dev/null +++ b/spirv/srOutput.pas @@ -0,0 +1,140 @@ +unit srOutput; + +{$mode ObjFPC}{$H+} + +interface + +uses + typinfo, + spirv, + srNodes, + srOp, + srLayout, + srVariable, + srDecorate; + +type + TpsslExportType=( + etMrt0,etMrt1,etMrt2,etMrt3, + etMrt4,etMrt5,etMrt6,etMrt7, + etMrtz, + etNull, + etUnknow0,etUnknow1, + etPos0,etPos1,etPos2,etPos3, + etUnknow2,etUnknow3, + etUnknow4,etUnknow5, + etUnknow6,etUnknow7, + etUnknow8,etUnknow9, + etUnknow10,etUnknow11, + etUnknow12,etUnknow13, + etUnknow14,etUnknow15, + etUnknow16,etUnknow17, + etParam0 ,etParam1 ,etParam2 ,etParam3, + etParam4 ,etParam5 ,etParam6 ,etParam7, + etParam8 ,etParam9 ,etParam10,etParam11, + etParam12,etParam13,etParam14,etParam15, + etParam16,etParam17,etParam18,etParam19, + etParam20,etParam21,etParam22,etParam23, + etParam24,etParam25,etParam26,etParam27, + etParam28,etParam29,etParam30,etParam31 + ); + + PsrOutput=^TsrOutput; + TsrOutput=object(TsrDescriptor) + etype:TpsslExportType; + function GetName:RawByteString; + end; + + TsrOutputList=object + data:array[TpsslExportType] of TsrOutput; + Procedure Init; + function Fetch(etype:TpsslExportType):PsrOutput; + procedure AllocBinding(Decorates:PsrDecorateList); + procedure AllocEntryPoint(EntryPoint:PSpirvOp); + end; + +implementation + +function TsrOutput.GetName:RawByteString; +begin + Result:=GetEnumName(TypeInfo(TpsslExportType),ord(etype)); +end; + +Procedure TsrOutputList.Init; +var + i:TpsslExportType; +begin + For i:=Low(TpsslExportType) to High(TpsslExportType) do + begin + data[i].etype:=i; + data[i].FStorage:=StorageClass.Output; + data[i].FBinding:=-1; + end; +end; + +function TsrOutputList.Fetch(etype:TpsslExportType):PsrOutput; +begin + Result:=@data[etype]; +end; + +procedure TsrOutputList.AllocBinding(Decorates:PsrDecorateList); +var + i:TpsslExportType; + pVar:PsrVariable; + FLocation:Integer; +begin + if (Decorates=nil) then Exit; + For i:=Low(TpsslExportType) to High(TpsslExportType) do + begin + pVar:=data[i].pVar; + if (pVar<>nil) then + begin + Case i of + etMrt0..etMrt7: + begin + if (data[i].FBinding=-1) then //alloc + begin + FLocation:=ord(i)-ord(etMrt0); + Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,FLocation); + data[i].FBinding:=FLocation; + end; + //Decoration.Index; ??? + end; + //etMrtz, + etPos0: + begin + Decorates^.emit_decorate(ntVar,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); + data[i].FBinding:=FLocation; + end; + else + Assert(False,'AllocBinding'); + end; + end; + end; + +end; + +procedure TsrOutputList.AllocEntryPoint(EntryPoint:PSpirvOp); +var + i:TpsslExportType; + pVar:PsrVariable; +begin + if (EntryPoint=nil) then Exit; + For i:=Low(TpsslExportType) to High(TpsslExportType) do + begin + pVar:=data[i].pVar; + if (pVar<>nil) then + begin + EntryPoint^.AddParam(ntVar,pVar); + end; + end; +end; + +end. + diff --git a/spirv/srParser.pas b/spirv/srParser.pas new file mode 100644 index 0000000..3b30305 --- /dev/null +++ b/spirv/srParser.pas @@ -0,0 +1,84 @@ +unit srParser; + +{$mode ObjFPC}{$H+} + +interface + +uses + sysutils, + srLabel, + srCFG, + srNodes; + +type + TsrCursor=object(TsrLCursor) + pCode:PsrCodeBlock; + pBlock:PsrCFGBlock; + function PopBlock:Boolean; + end; + + TsrCodeList=specialize TNodeQueue<PsrCodeBlock>; + TsrCodeHeap=object(TsrCodeList) + Alloc:TfnAlloc; + function FindByPtr(base:Pointer):PsrCodeBlock; + function FetchByPtr(base:Pointer;bType:TsrBlockType):TsrCursor; + end; + +implementation + +// + +function TsrCodeHeap.FindByPtr(base:Pointer):PsrCodeBlock; +var + node:PsrCodeBlock; +begin + Result:=nil; + node:=pHead; + While (node<>nil) do + begin + if node^.IsContain(base) then + begin + Exit(node); + end; + node:=node^.pNext; + end; +end; + +function TsrCodeHeap.FetchByPtr(base:Pointer;bType:TsrBlockType):TsrCursor; +var + node:PsrCodeBlock; + adr:TSrcAdr; +begin + node:=FindByPtr(base); + if (node=nil) then + begin + node:=Alloc(SizeOf(TsrCodeBlock)); + node^.Alloc:=Alloc; + if parse_code_cfg(bType,base,node)>1 then Assert(False); + Push_tail(node); + end; + + Result:=Default(TsrCursor); + Result.Init(node^.Body); + Result.pCode :=node; + Result.pBlock:=@node^.FTop; + + adr:=Default(TSrcAdr); + adr.pBody:=node^.Body; + adr.Offdw:=(Pointer(base)-Pointer(adr.pBody)) div 4; + Result.Adr:=adr; + + Result.pBlock:=Result.pBlock^.DownBlock(adr); +end; + +function TsrCursor.PopBlock:Boolean; +begin + Result:=False; + if (pBlock=nil) then Exit; + if (pBlock^.pParent=nil) then Exit; + pBlock:=pBlock^.pParent; + Result:=True; +end; + +end. + diff --git a/spirv/srRefId.pas b/spirv/srRefId.pas new file mode 100644 index 0000000..0437765 --- /dev/null +++ b/spirv/srRefId.pas @@ -0,0 +1,49 @@ +unit srRefId; + +{$mode objfpc}{$H+} + +interface + +type + PsrRefId=^TsrRefId; + TsrRefId=packed object + ID:DWORD; + function Alloc:Boolean; inline; + end; + + PsrRefIdAlloc=^TsrRefIdAlloc; + TsrRefIdAlloc=object + FSpirvID:DWORD; + function FetchSpirvID:DWORD; inline; + procedure FetchSpirvID(P:PsrRefId); + function GetSpirvIDBound:DWORD; inline; + end; + +implementation + +function TsrRefId.Alloc:Boolean; inline; +begin + Result:=(ID<>0); +end; + +function TsrRefIdAlloc.FetchSpirvID:DWORD; inline; +begin + Inc(FSpirvID); + Result:=FSpirvID; +end; + +procedure TsrRefIdAlloc.FetchSpirvID(P:PsrRefId); +begin + if (P<>nil) and (not P^.Alloc) then + begin + P^.ID:=FetchSpirvID; + end; +end; + +function TsrRefIdAlloc.GetSpirvIDBound:DWORD; inline; +begin + Result:=FSpirvID+1; +end; + +end. + diff --git a/spirv/srReg.pas b/spirv/srReg.pas new file mode 100644 index 0000000..ef91047 --- /dev/null +++ b/spirv/srReg.pas @@ -0,0 +1,469 @@ +unit srReg; + +{$mode objfpc}{$H+} + +interface + +uses + srNodes, + srRefId, + srTypes, + srConst; + +type + 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); + function AsConst:PsrConst; + function AsOp:Pointer; + function AsReg:Pointer; + function is_const:Boolean; + function is_bool:Boolean; + function is_bool_or_const_bool:Boolean; + function is_unknow:Boolean; + end; + + TRegStory=specialize TNodeList<PsrRegNode>; + + TString5=string[5]; + + TsrRegSlot=object + Alloc:TfnAlloc; + pVar:Pointer; + pStory:TRegStory; + rid:TString5; + Procedure Init(a:TfnAlloc;const n:TString5); + function first:PsrRegNode; + function current:PsrRegNode; + function New(pLine:Pointer;rtype:TsrDataType):PsrRegNode; + function NewAfter(rtype:TsrDataType;r:PsrRegNode):PsrRegNode; + procedure Remove(r:PsrRegNode); + end; + + PsrRegsSnapshot=^TsrRegsSnapshot; + TsrRegsSnapshot=object + SGRP:array[0..103] of PsrRegNode; + VCC:array[0..1] of PsrRegNode; + M0:PsrRegNode; + EXEC:array[0..1] of PsrRegNode; + SCC:PsrRegNode; + VGRP:array[0..255] of PsrRegNode; + end; + + TForEachSlot=procedure(pSlot:PsrRegSlot) of object; + TForEachSnap=procedure(pSlot:PsrRegSlot;var old:PsrRegNode) of object; + + TsrRegsStory=object + SGRP:array[0..103] of TsrRegSlot; + VCC:array[0..1] of TsrRegSlot; + M0:TsrRegSlot; + EXEC:array[0..1] of TsrRegSlot; + SCC:TsrRegSlot; + VGRP:array[0..255] of TsrRegSlot; + FUnattach:TsrRegSlot; + Procedure Init(Alloc:TfnAlloc); + function get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean; + function get_sdst7(SDST:Byte):PsrRegSlot; + function get_ssrc8(SSRC:Byte):PsrRegSlot; + function get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean; + function get_ssrc9(SSRC:Word):PsrRegSlot; + 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; + +implementation + +Procedure TsrRegsStory.Init(Alloc:TfnAlloc); +var + i:Word; + n:TString5; +begin + FillChar(Self,SizeOf(TsrRegsStory),0); + For i:=0 to 103 do + begin + Str(i,n); + SGRP[i].Init(Alloc,'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'); + For i:=0 to 255 do + begin + Str(i,n); + VGRP[i].Init(Alloc,'V'+n); + end; + FUnattach.Init(Alloc,'UNATT'); +end; + +function TsrRegsStory.get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean; +begin + Result:=True; + if (dst=nil) then Exit(false); + Case SDST of + 0..102: + begin + dst[0]:=@SGRP[SDST]; + dst[1]:=@SGRP[SDST+1]; + end; + 106: + begin + dst[0]:=@VCC[0]; + dst[1]:=@VCC[1]; + end; + 126: + begin + dst[0]:=@EXEC[0]; + dst[1]:=@EXEC[1]; + end; + else + Result:=False; + 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 + 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'); + else + Result:=nil; + end; +end; + +function TsrRegsStory.get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean; +begin + Result:=True; + if (src=nil) then Exit(False); + Case SSRC of + 0..102: + begin + src[0]:=@SGRP[SSRC]; + src[1]:=@SGRP[SSRC+1]; + end; + 106: + begin + src[0]:=@VCC[0]; + src[1]:=@VCC[1]; + end; + 126: + begin + src[0]:=@EXEC[0]; + src[1]:=@EXEC[1]; + end; + 256..510: + begin + src[0]:=@VGRP[SSRC-256]; + src[1]:=@VGRP[SSRC-255]; + end; + else + Result:=False; + 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]; +end; + +function TsrRegsStory.get_vdst8(VDST:Byte):PsrRegSlot; +begin + Result:=@VGRP[VDST]; +end; + +//SBASE 0..63 +//SGRP:array[0..103] of TpsslRegSlot; +function TsrRegsStory.get_sbase(SBASE,count:Byte;src:PPsrRegSlot):Boolean; +var + i,p:Byte; +begin + Result:=True; + if (SBASE>63) or (count=0) or (src=nil) then Exit(False); + p:=SBASE*2; + if ((p+count)>104) then Exit(False); + For i:=0 to count-1 do + begin + src[i]:=@SGRP[p+i]; + end; +end; + +//SRSRC 0..31 +function TsrRegsStory.get_srsrc(SRSRC,count:Byte;src:PPsrRegSlot):Boolean; +var + i,p:Byte; +begin + Result:=True; + if (SRSRC>31) or (count=0) or (src=nil) then Exit(False); + p:=SRSRC*4; + if ((p+count)>104) then Exit(False); + For i:=0 to count-1 do + begin + src[i]:=@SGRP[p+i]; + end; +end; + +// + +function TsrRegsStory.get_snapshot:TsrRegsSnapshot; +var + i:Word; +begin + Result:=Default(TsrRegsSnapshot); + For i:=0 to 103 do + begin + Result.SGRP[i]:=SGRP[i].current; + end; + For i:=0 to 1 do + begin + Result.VCC[i] :=VCC[i].current; + end; + Result.M0 :=M0.current; + For i:=0 to 1 do + begin + Result.EXEC[i]:=EXEC[i].current; + end; + Result.SCC :=SCC.current; + For i:=0 to 255 do + begin + Result.VGRP[i]:=VGRP[i].current; + end; +end; + +procedure TsrRegsStory.ForEachSlot(cb:TForEachSlot); +var + i:Word; +begin + if (cb=nil) then Exit; + For i:=0 to 103 do + begin + cb(@SGRP[i]); + end; + For i:=0 to 1 do + begin + cb(@VCC[i]); + end; + cb(@M0); + For i:=0 to 1 do + begin + cb(@EXEC[i]); + end; + cb(@SCC); + For i:=0 to 255 do + begin + cb(@VGRP[i]); + end; +end; + +procedure TsrRegsStory.ForEachSnap(cb:TForEachSnap;old:PsrRegsSnapshot); +var + i:Word; +begin + if (cb=nil) or (old=nil) then Exit; + For i:=0 to 103 do + begin + cb(@SGRP[i],Old^.SGRP[i]); + end; + For i:=0 to 1 do + begin + cb(@VCC[i],Old^.VCC[i]); + end; + cb(@M0,Old^.M0); + For i:=0 to 1 do + begin + cb(@EXEC[i],Old^.EXEC[i]); + end; + cb(@SCC,Old^.SCC); + For i:=0 to 255 do + begin + cb(@VGRP[i],Old^.VGRP[i]); + end; +end; + +//-- + +function TsrRegNode.GetName:RawByteString; +begin + Result:=''; + if (pSlot<>nil) then Result:=pSlot^.rid; +end; + +Procedure TsrRegNode.mark_read; +begin + Inc(read_count); +end; + +Procedure TsrRegNode.mark_unread; +begin + Assert(read_count<>0); + if (read_count<>0) then Dec(read_count); +end; + +procedure TsrRegNode.SetConst(pConst:PsrConst); +begin + pWriter.SetParam(ntConst,pConst); + dtype:=pConst^.key.dtype; +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; +end; + +function TsrRegNode.AsReg:Pointer; +begin + Result:=nil; + if (@Self=nil) then Exit; + if (pWriter.ntype<>ntReg) then Exit; + Result:=pWriter.pData; +end; + +function TsrRegNode.is_const:Boolean; +begin + Result:=(pWriter.ntype=ntConst); +end; + +function TsrRegNode.is_bool:Boolean; +begin + Result:=(dtype=dtBool); +end; + +function TsrRegNode.is_bool_or_const_bool:Boolean; +begin + Result:=is_bool or + (is_const and (AsConst<>nil) and AsConst^.isBoolVal); +end; + +function TsrRegNode.is_unknow:Boolean; +begin + Result:=(dtype=dtUnknow); +end; + +//-- + +Procedure TsrRegSlot.Init(a:TfnAlloc;const n:TString5); +begin + Alloc:=a; + rid :=n; +end; + +function TsrRegSlot.first:PsrRegNode; +begin + Result:=pStory.pHead; +end; + +function TsrRegSlot.current:PsrRegNode; +begin + Result:=pStory.pTail; +end; + +function TsrRegSlot.New(pLine:Pointer;rtype:TsrDataType):PsrRegNode; +var + node:PsrRegNode; +begin + node:=Alloc(SizeOf(TsrRegNode)); + node^.pSlot:=@Self; + node^.dtype:=rtype; + node^.pLine:=pLine; + pStory.Push_tail(node); + Result:=node; +end; + +function TsrRegSlot.NewAfter(rtype:TsrDataType;r:PsrRegNode):PsrRegNode; +var + node:PsrRegNode; +begin + node:=Alloc(SizeOf(TsrRegNode)); + node^.pSlot:=@Self; + node^.dtype:=rtype; + node^.pLine:=r^.pLine; + pStory.InsertAfter(r,node); + Result:=node; +end; + +procedure TsrRegSlot.Remove(r:PsrRegNode); +begin + if (r=nil) then Exit; + pStory.Remove(r); +end; + +end. + diff --git a/spirv/srTypes.pas b/spirv/srTypes.pas new file mode 100644 index 0000000..2e4a153 --- /dev/null +++ b/spirv/srTypes.pas @@ -0,0 +1,952 @@ +unit srTypes; + +{$mode objfpc}{$H+} + +interface + +uses + bittype, + Half16, + spirv, + srNodes, + 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; + + 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; + end; + + TsrTypeList=object + type + TNodeList=specialize TNodeList<PsrType>; + TNodeFetch=specialize TNodeFetch<PsrType,TsrType>; + var + Alloc:TfnAlloc; + 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; + 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 + +function TsrType.c(n1,n2:PsrType):Integer; +begin + Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrType.key)); + if (Result<>0) then Exit; + Result:=ComparePtruint(@n1^.Data,@n2^.Data,n1^.key.count); +end; + +Procedure TsrType.mark_read; +begin + Inc(read_count); +end; + +Procedure TsrType.mark_unread; +begin + if (read_count<>0) then Dec(read_count); +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; +var + i:DWORD; +begin + if (key.count<>0) then + For i:=0 to key.count-1 do + begin + GetCompItem(i)^.mark_read; + end; +end; + +Procedure TsrType._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; + +Procedure TsrType.Clear; +var + i:DWORD; +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; + end; +end; + +function _GetNodeSize(count:DWORD):ptruint; inline; +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; + end; +end; + +function TsrTypeList._Fetch(node:PsrType):PsrType; +var + size:ptruint; +begin + Result:=FNTree.Find(node); + if (Result=nil) then + begin + size:=_GetNodeSize(node^.key.count); + Result:=Alloc(size); + Move(node^,Result^,Size); + 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; +var + rec:record + node:TsrType; + align:Pointer; + end; + child:PsrType; +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; +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; + end; + + dtInt8, + dtUint8, + dtInt16, + dtUint16, + dtInt32, + dtUint32, + 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; + end; + + dtFloat32, + dtHalf16: + 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; + end; + + dtTypeVoid: + begin + rec.node.dtype:=dtype; + rec.node.key.OpId:=Op.OpTypeVoid; + Result:=_Fetch(@rec.node); + Result^.mark_read; + end; + + dtTypeSampler: + begin + rec.node.dtype:=dtype; + rec.node.key.OpId:=Op.OpTypeSampler; + Result:=_Fetch(@rec.node); + Result^.mark_read; + end; + + // + + dtVec2b, + dtVec3b, + dtVec4b, + + dtVec2u8, + dtVec4u8, + + dtVec2i8, + dtVec4i8, + + dtVec2u16, + dtVec4u16, + + dtVec2i16, + dtVec4i16, + + dtVec2u, + dtVec3u, + dtVec4u, + + dtVec2i, + dtVec3i, + dtVec4i, + + dtVec2f, + dtVec3f, + dtVec4f, + + dtVec2h, + dtVec4h:Result:=_FetchVector(dtype,GetVecChild(dtype),GetVecCount(dtype)); + + // + + 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; + end; + + // + + else + Assert(false); + end; + +end; + +function TsrTypeList.FetchPointer(child:PsrType;storage_class:DWORD):PsrType; +var + rec:record + node:TsrType; + align:Pointer; + end; +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; +end; + +function TsrTypeList.FetchFunction(ret:PsrType):PsrType; +var + rec:record + node:TsrType; + align:Pointer; + end; +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; +end; + +function TsrTypeList.FetchFunction1(ret,param:PsrType):PsrType; +var + rec:record + node:TsrType; + align:array[0..1] of Pointer; + end; +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; +end; + +function TsrTypeList.FetchStruct(child:PsrType;pField:Pointer):PsrType; +var + rec:record + node:TsrType; + align:Pointer; + end; +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; +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; +var + aUint:PsrType; +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; +end; + +function TsrTypeList.FetchArray(child:PsrType;array_count,array_stride:DWORD):PsrType; +var + rec:record + node:TsrType; + align:array[0..1] of Pointer; + 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; +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; +end; + +function TsrTypeList.FetchSampledImage(child:PsrType):PsrType; +var + rec:record + node:TsrType; + align:Pointer; + end; +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; +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 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 new file mode 100644 index 0000000..0522dac --- /dev/null +++ b/spirv/srUniform.pas @@ -0,0 +1,183 @@ +unit srUniform; + +{$mode ObjFPC}{$H+} + +interface + +uses + spirv, + srNodes, + srTypes, + srLayout, + srReg, + srVariable, + srDecorate; + +type + String2=String[2]; + + PsrUniform=^TsrUniform; + TsrUniform=object(TsrDescriptor) + pLeft,pRight:PsrUniform; + //---- + + key:packed record + pLayout:PsrDataLayout; + pType:PsrType; + end; + + pReg:PsrRegNode; + + function c(n1,n2:PsrUniform):Integer; static; + function GetTypeChar:String2; + function GetString:RawByteString; + end; + + TsrUniformList=object + type + TNodeFetch=specialize TNodeFetch<PsrUniform,TsrUniform>; + var + Alloc:TfnAlloc; + FNTree:TNodeFetch; + procedure Init(cb:TfnAlloc); + 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); + end; + +implementation + +function TsrUniform.c(n1,n2:PsrUniform):Integer; +begin + //first pLayout + Result:=Integer(n1^.key.pLayout>n2^.key.pLayout)-Integer(n1^.key.pLayout<n2^.key.pLayout); + if (Result<>0) then Exit; + //second pType + Result:=Integer(n1^.key.pType>n2^.key.pType)-Integer(n1^.key.pType<n2^.key.pType); +end; + +function TsrUniform.GetTypeChar:String2; +begin + Result:=''; + if (key.pType<>nil) then + With key.pType^.key do + Case key.pType^.dtype of + dtTypeImage: + begin + if (ext.image.Dim=Dim.Buffer) then + begin + Case ext.image.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 + 1:Result:='UI'; //VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE + 2:Result:='SI'; //VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + else Result:='RI'; //runtime image + end; + end; + end; + dtTypeSampler:Result:='US'; //VK_DESCRIPTOR_TYPE_SAMPLER + else; + end; +end; + +function TsrUniform.GetString:RawByteString; +var + PID:DWORD; +begin + PID:=0; + if (key.pLayout<>nil) then + begin + PID:=key.pLayout^.FID; + end; + Result:=GetTypeChar+ + ';PID='+HexStr(PID,8)+ + ';BND='+HexStr(FBinding,8); +end; + +procedure TsrUniformList.Init(cb:TfnAlloc); +begin + Alloc:=cb; +end; + +function TsrUniformList.Fetch(s:PsrDataLayout;t:PsrType):PsrUniform; +var + node:TsrUniform; +begin + node:=Default(TsrUniform); + node.key.pLayout:=s; + node.key.pType:=t; + node.FStorage:=StorageClass.UniformConstant; + node.FBinding:=-1; + Result:=FNTree.Find(@node); + if (Result=nil) then + begin + Result:=Alloc(SizeOf(TsrUniform)); + Move(node,Result^,SizeOf(TsrUniform)); + FNTree.Insert(Result); + end else + begin + t^.mark_unread; + end; +end; + +Function TsrUniformList.First:PsrUniform; +begin + Result:=FNTree.Min; +end; + +Function TsrUniformList.Next(node:PsrUniform):PsrUniform; +begin + Result:=FNTree.Next(node); +end; + +procedure TsrUniformList.AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList); +var + node:PsrUniform; + pVar:PsrVariable; +begin + if (Decorates=nil) then Exit; + node:=First; + While (node<>nil) do + begin + pVar:=node^.pVar; + if (pVar<>nil) then + begin + if (node^.FBinding=-1) then //alloc + begin + Decorates^.emit_decorate(ntVar,pVar,Decoration.Binding,FBinding); + Decorates^.emit_decorate(ntVar,pVar,Decoration.DescriptorSet,Decorates^.FDescriptorSet); + node^.FBinding:=FBinding; + Inc(FBinding); + end; + end; + node:=Next(node); + end; +end; + +procedure TsrUniformList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList); +var + node:PsrUniform; + 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; + +end. + diff --git a/spirv/srVBufInfo.pas b/spirv/srVBufInfo.pas new file mode 100644 index 0000000..7800551 --- /dev/null +++ b/spirv/srVBufInfo.pas @@ -0,0 +1,447 @@ +unit srVBufInfo; + +{$mode ObjFPC}{$H+} + +interface + +uses + sysutils, + ps4_pssl, + srTypes, + srLayout, + spirv; + +type + //Destination channel select: + //0=0, 1=1, 4=R, 5=G, 6=B, 7=A + Tdst_sel=array[0..3] of Byte; + + TBuf_info=packed object + grp:PsrDataLayout; + dsel:Tdst_sel; + DFMT:Byte; //BUF_DATA_FORMAT_* + NFMT:Byte; //BUF_NUM_FORMAT_* + count:Byte; //count reg dst + function GetResultType:TsrDataType; + function GetElemType:TsrDataType; + function GetElemCount:Byte; inline; + function GetElemSize:Byte; inline; + function GetSizeFormat:Byte; inline; + function GetAlignSize:Byte; inline; + function IsComp:Boolean; + function IsExtFormat:Boolean; + function GetImageFormat:Byte; + function GetImageFormatElement:Byte; + function GetImageInfo:TsrImageInfo; + function GetImageInfoElement:TsrImageInfo; + end; + +const + dst_sel_identity:Tdst_sel=(4,5,6,7); + +function Buf_info(grp:PsrDataLayout;dsel:Tdst_sel;DFMT,NFMT,count:Byte):TBuf_info; inline; +function dst_sel(r,g,b,a:Byte):Tdst_sel; inline; +function get_reverse_dst_sel(dst:Tdst_sel):Tdst_sel; +function GetElemCount(DFMT:Byte):Byte; inline; + +implementation + +const + DFMT_ELEM_COUNT:array[0..15] of Byte=( + 0, //BUF_DATA_FORMAT_INVALID + 1, //BUF_DATA_FORMAT_8 + 1, //BUF_DATA_FORMAT_16 + 2, //BUF_DATA_FORMAT_8_8 + 1, //BUF_DATA_FORMAT_32 + 2, //BUF_DATA_FORMAT_16_16 + 3, //BUF_DATA_FORMAT_10_11_11 + 3, //BUF_DATA_FORMAT_11_11_10 + 4, //BUF_DATA_FORMAT_10_10_10_2 + 4, //BUF_DATA_FORMAT_2_10_10_10 + 4, //BUF_DATA_FORMAT_8_8_8_8 + 2, //BUF_DATA_FORMAT_32_32 + 4, //BUF_DATA_FORMAT_16_16_16_16 + 3, //BUF_DATA_FORMAT_32_32_32 + 4, //BUF_DATA_FORMAT_32_32_32_32 + 0); //BUF_DATA_FORMAT_RESERVED + + DFMT_ELEM_SIZE:array[0..15] of Byte=( + 0, //BUF_DATA_FORMAT_INVALID + 1, //BUF_DATA_FORMAT_8 + 2, //BUF_DATA_FORMAT_16 + 1, //BUF_DATA_FORMAT_8_8 + 4, //BUF_DATA_FORMAT_32 + 2, //BUF_DATA_FORMAT_16_16 + 4, //BUF_DATA_FORMAT_10_11_11 + 4, //BUF_DATA_FORMAT_11_11_10 + 4, //BUF_DATA_FORMAT_10_10_10_2 + 4, //BUF_DATA_FORMAT_2_10_10_10 + 1, //BUF_DATA_FORMAT_8_8_8_8 + 4, //BUF_DATA_FORMAT_32_32 + 2, //BUF_DATA_FORMAT_16_16_16_16 + 4, //BUF_DATA_FORMAT_32_32_32 + 4, //BUF_DATA_FORMAT_32_32_32_32 + 0); //BUF_DATA_FORMAT_RESERVED + + DFMT_SIZE:array[0..15] of Byte=( + 0, //BUF_DATA_FORMAT_INVALID + 1, //BUF_DATA_FORMAT_8 //shr 2 + 2, //BUF_DATA_FORMAT_16 //shr 2 + 2, //BUF_DATA_FORMAT_8_8 //shr 2 + 4, //BUF_DATA_FORMAT_32 //shr 2 + 4, //BUF_DATA_FORMAT_16_16 //shr 2 + 4, //BUF_DATA_FORMAT_10_11_11 //shr 2 + 4, //BUF_DATA_FORMAT_11_11_10 //shr 2 + 4, //BUF_DATA_FORMAT_10_10_10_2 //shr 2 + 4, //BUF_DATA_FORMAT_2_10_10_10 //shr 2 + 4, //BUF_DATA_FORMAT_8_8_8_8 //shr 2 + 8, //BUF_DATA_FORMAT_32_32 //shr 3 + 8, //BUF_DATA_FORMAT_16_16_16_16 //shr 3 + 12, //BUF_DATA_FORMAT_32_32_32 //div 12 + 16, //BUF_DATA_FORMAT_32_32_32_32 //shr 4 + 0); //BUF_DATA_FORMAT_RESERVED + +function Buf_info(grp:PsrDataLayout;dsel:Tdst_sel;DFMT,NFMT,count:Byte):TBuf_info; inline; +begin + Result.grp :=grp; + Result.dsel :=dsel; + Result.DFMT :=DFMT; + Result.NFMT :=NFMT; + Result.count:=count; +end; + +function dst_sel(r,g,b,a:Byte):Tdst_sel; inline; +begin + Result[0]:=r; + Result[1]:=g; + Result[2]:=b; + Result[3]:=a; +end; + +function get_reverse_dst_sel(dst:Tdst_sel):Tdst_sel; +var + i,f,d:Byte; +begin + Result:=Default(Tdst_sel); + For i:=0 to 3 do + For f:=0 to 3 do + begin + d:=dst[f]; + Case d of + 4..7: + begin + d:=d-4; + if (i=d) then + begin + Result[i]:=f+4; + Break; + end; + end; + else; + end; + end; +end; + +function TBuf_info.GetResultType:TsrDataType; +begin + Result:=dtFloat32; + Case NFMT of + BUF_NUM_FORMAT_UINT:Result:=dtUint32; + BUF_NUM_FORMAT_SINT:Result:=dtInt32; + else; + end; +end; + +function TBuf_info.GetElemType:TsrDataType; +begin + Result:=dtUnknow; + Case DFMT_ELEM_SIZE[DFMT] of + 1:Case NFMT of + BUF_NUM_FORMAT_SNORM , + BUF_NUM_FORMAT_SSCALED , + BUF_NUM_FORMAT_SINT , + BUF_NUM_FORMAT_SNORM_NZ:Result:=dtInt8; + else Result:=dtUint8; + end; + 2:Case NFMT of + BUF_NUM_FORMAT_SNORM , + BUF_NUM_FORMAT_SSCALED , + BUF_NUM_FORMAT_SINT , + BUF_NUM_FORMAT_SNORM_NZ:Result:=dtInt16; + BUF_NUM_FORMAT_FLOAT :Result:=dtHalf16; + else Result:=dtUint16; + end; + 4:Case NFMT of + BUF_NUM_FORMAT_SNORM , + BUF_NUM_FORMAT_SSCALED , + BUF_NUM_FORMAT_SINT , + BUF_NUM_FORMAT_SNORM_NZ:Result:=dtInt32; + BUF_NUM_FORMAT_FLOAT :Result:=dtFloat32; + else Result:=dtUint32; + end; + else; + end; +end; + +function GetElemCount(DFMT:Byte):Byte; inline; +begin + Result:=DFMT_ELEM_COUNT[DFMT]; +end; + +function TBuf_info.GetElemCount:Byte; inline; +begin + Result:=DFMT_ELEM_COUNT[DFMT]; +end; + +function TBuf_info.GetElemSize:Byte; inline; +begin + Result:=DFMT_ELEM_SIZE[DFMT]; +end; + +function TBuf_info.GetSizeFormat:Byte; inline; +begin + Result:=DFMT_SIZE[DFMT]; +end; + +function Min(a,b:PtrInt):PtrInt; inline; +begin + if (a<b) then Result:=a else Result:=b; +end; + +function TBuf_info.GetAlignSize:Byte; inline; +begin + Result:=Min(4,GetSizeFormat); +end; + +function TBuf_info.IsComp:Boolean; +begin + Case DFMT of + BUF_DATA_FORMAT_8 , + BUF_DATA_FORMAT_16 , + BUF_DATA_FORMAT_8_8 , + BUF_DATA_FORMAT_16_16 , + BUF_DATA_FORMAT_10_11_11 , + BUF_DATA_FORMAT_11_11_10 , + BUF_DATA_FORMAT_10_10_10_2 , + BUF_DATA_FORMAT_2_10_10_10 , + BUF_DATA_FORMAT_8_8_8_8 , + BUF_DATA_FORMAT_16_16_16_16:Result:=True; + else + Result:=False; + end; +end; + +function TBuf_info.IsExtFormat:Boolean; +begin + Case DFMT of + BUF_DATA_FORMAT_10_11_11 , + BUF_DATA_FORMAT_11_11_10 , + BUF_DATA_FORMAT_10_10_10_2 , + BUF_DATA_FORMAT_2_10_10_10 :Result:=True; + else + Result:=False; + end; +end; + +function TBuf_info.GetImageFormat:Byte; +begin + Result:=ImageFormat.Unknown; + Case DFMT of + BUF_DATA_FORMAT_8 : //R8 R8Snorm R8ui R8i + Case NFMT of + BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.R8; + BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.R8Snorm; + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.R8ui; + BUF_NUM_FORMAT_SINT :Result:=ImageFormat.R8i; + BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.R8i; + else; + end; + BUF_DATA_FORMAT_16 : //R16 R16Snorm R16ui R16i R16f + Case NFMT of + BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.R16; + BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.R16Snorm; + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.R16ui; + BUF_NUM_FORMAT_SINT :Result:=ImageFormat.R16i; + BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.R16i; + BUF_NUM_FORMAT_USCALED , + BUF_NUM_FORMAT_SSCALED , + BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.R16f; + end; + BUF_DATA_FORMAT_8_8 : //Rg8 Rg8Snorm Rg8ui Rg8i + Case NFMT of + BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.Rg8; + BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.Rg8Snorm; + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rg8ui; + BUF_NUM_FORMAT_SINT :Result:=ImageFormat.Rg8i; + BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.Rg8i; + else; + end; + BUF_DATA_FORMAT_32 : //R32ui R32i R32f + Case NFMT of + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.R32ui; + BUF_NUM_FORMAT_SINT :Result:=ImageFormat.R32i; + BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.R32i; + BUF_NUM_FORMAT_USCALED , + BUF_NUM_FORMAT_SSCALED , + BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.R32f; + else; + end; + BUF_DATA_FORMAT_16_16 : //Rg16 Rg16Snorm Rg16ui Rg16i Rg16f + Case NFMT of + BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.Rg16; + BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.Rg16Snorm; + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rg16ui; + BUF_NUM_FORMAT_SINT :Result:=ImageFormat.Rg16i; + BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.Rg16i; + BUF_NUM_FORMAT_USCALED , + BUF_NUM_FORMAT_SSCALED , + BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.Rg16f; + end; + BUF_DATA_FORMAT_10_11_11 , + BUF_DATA_FORMAT_11_11_10 : //R11fG11fB10f + Case NFMT of + BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.R11fG11fB10f; + else; + end; + BUF_DATA_FORMAT_10_10_10_2 , + BUF_DATA_FORMAT_2_10_10_10 : //Rgb10A2 Rgb10a2ui + Case NFMT of + BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.Rgb10A2; + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rgb10a2ui; + else; + end; + BUF_DATA_FORMAT_8_8_8_8 : //Rgba8 Rgba8Snorm Rgba8ui Rgba8i + Case NFMT of + BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.Rgba8; + BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.Rgba8Snorm; + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rgba8ui; + BUF_NUM_FORMAT_SINT :Result:=ImageFormat.Rgba8i; + BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.Rgba8i; + else; + end; + BUF_DATA_FORMAT_32_32 : //Rg32ui Rg32i Rg32f + Case NFMT of + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rg32ui; + BUF_NUM_FORMAT_SINT :Result:=ImageFormat.Rg32i; + BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.Rg32i; + BUF_NUM_FORMAT_USCALED , + BUF_NUM_FORMAT_SSCALED , + BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.Rg32f; + else; + end; + BUF_DATA_FORMAT_16_16_16_16: //Rgba16 Rgba16Snorm Rgba16ui Rgba16i Rgba16f + Case NFMT of + BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.Rgba16; + BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.Rgba16Snorm; + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rgba16ui; + BUF_NUM_FORMAT_SINT :Result:=ImageFormat.Rgba16i; + BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.Rgba16i; + BUF_NUM_FORMAT_USCALED , + BUF_NUM_FORMAT_SSCALED , + BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.Rgba16f; + end; + BUF_DATA_FORMAT_32_32_32 , + BUF_DATA_FORMAT_32_32_32_32: //Rgba32ui Rgba32i Rgba32f + Case NFMT of + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rgba32ui; + BUF_NUM_FORMAT_SINT :Result:=ImageFormat.Rgba32i; + BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.Rgba32i; + BUF_NUM_FORMAT_USCALED , + BUF_NUM_FORMAT_SSCALED , + BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.Rgba32f; + else; + end; + else; + end; +end; + +// + +function TBuf_info.GetImageFormatElement:Byte; +begin + Result:=ImageFormat.Unknown; + Case DFMT of + BUF_DATA_FORMAT_8 , + BUF_DATA_FORMAT_8_8 , + BUF_DATA_FORMAT_8_8_8_8 : //R8 R8Snorm R8ui R8i + Case NFMT of + BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.R8; + BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.R8Snorm; + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.R8ui; + BUF_NUM_FORMAT_SINT :Result:=ImageFormat.R8i; + BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.R8i; + else; + end; + BUF_DATA_FORMAT_16 , + BUF_DATA_FORMAT_16_16 , + BUF_DATA_FORMAT_16_16_16_16: //R16 R16Snorm R16ui R16i R16f + Case NFMT of + BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.R16; + BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.R16Snorm; + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.R16ui; + BUF_NUM_FORMAT_SINT :Result:=ImageFormat.R16i; + BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.R16i; + BUF_NUM_FORMAT_USCALED , + BUF_NUM_FORMAT_SSCALED , + BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.R16f; + end; + BUF_DATA_FORMAT_32 , //R32ui R32i R32f + BUF_DATA_FORMAT_32_32 , + BUF_DATA_FORMAT_32_32_32 , + BUF_DATA_FORMAT_32_32_32_32: + Case NFMT of + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.R32ui; + BUF_NUM_FORMAT_SINT :Result:=ImageFormat.R32i; + BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.R32i; + BUF_NUM_FORMAT_USCALED , + BUF_NUM_FORMAT_SSCALED , + BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.R32f; + else; + end; + BUF_DATA_FORMAT_10_11_11 , + BUF_DATA_FORMAT_11_11_10 : //R11fG11fB10f + Case NFMT of + BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.R11fG11fB10f; + else; + end; + BUF_DATA_FORMAT_10_10_10_2 , + BUF_DATA_FORMAT_2_10_10_10 : //Rgb10A2 Rgb10a2ui + Case NFMT of + BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.Rgb10A2; + BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rgb10a2ui; + else; + end; + else; + end; +end; + +// + +function TBuf_info.GetImageInfo:TsrImageInfo; +begin + Result:=Default(TsrImageInfo); + Result.dtype:=GetResultType; + + Result.tinfo.Dim :=Dim.Buffer; + Result.tinfo.Depth :=2; + Result.tinfo.Arrayed:=0; + Result.tinfo.MS :=0; + Result.tinfo.Sampled:=2; + Result.tinfo.Format :=GetImageFormat; +end; + +function TBuf_info.GetImageInfoElement:TsrImageInfo; +begin + Result:=Default(TsrImageInfo); + Result.dtype:=GetResultType; + + Result.tinfo.Dim :=Dim.Buffer; + Result.tinfo.Depth :=2; + Result.tinfo.Arrayed:=0; + Result.tinfo.MS :=0; + Result.tinfo.Sampled:=2; + Result.tinfo.Format :=GetImageFormatElement; +end; + +end. + diff --git a/spirv/srVariable.pas b/spirv/srVariable.pas new file mode 100644 index 0000000..f655c32 --- /dev/null +++ b/spirv/srVariable.pas @@ -0,0 +1,118 @@ +unit srVariable; + +{$mode ObjFPC}{$H+} + +interface + +uses + spirv, + srNodes, + srTypes, + srRefId; + +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; + end; + + TsrVariableList=specialize TNodeList<PsrVariable>; + +implementation + +uses + srLayout, + srVertLayout, + srFragLayout, + srInput, + srOutput; + +Procedure TsrVariable.mark_read; +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'); + end; +end; + +Procedure TsrVariable.Clear; +begin + if (pType<>nil) then + begin + pType^.mark_unread; + pType:=nil; + end; + if (pSource.pData<>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; + end; + end; +end; + +end. + diff --git a/spirv/srVertLayout.pas b/spirv/srVertLayout.pas new file mode 100644 index 0000000..0f40949 --- /dev/null +++ b/spirv/srVertLayout.pas @@ -0,0 +1,164 @@ +unit srVertLayout; + +{$mode ObjFPC}{$H+} + +interface + +uses + sysutils, + spirv, + srNodes, + 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; + end; + + TsrVertLayoutList=object + type + TNodeFetch=specialize TNodeFetch<PsrVertLayout,TsrVertLayout>; + var + Alloc:TfnAlloc; + FNTree:TNodeFetch; + procedure Init(cb:TfnAlloc); + function Fetch(p:PsrDataLayout):PsrVertLayout; + Function First:PsrVertLayout; + Function Next(node:PsrVertLayout):PsrVertLayout; + procedure AllocBinding(Decorates:PsrDecorateList); + procedure AllocEntryPoint(EntryPoint:PSpirvOp); + procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList); + end; + +implementation + +function TsrVertLayout.c(n1,n2:PsrVertLayout):Integer; +begin + Result:=Integer(n1^.pLayout>n2^.pLayout)-Integer(n1^.pLayout<n2^.pLayout); + //Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrVertLayout.key)); +end; + +function TsrVertLayout.GetString:RawByteString; +var + PID:DWORD; +begin + PID:=0; + if (pLayout<>nil) then + begin + PID:=pLayout^.FID; + end; + Result:='VA;PID='+HexStr(PID,8)+ + ';BND='+HexStr(FBinding,8); +end; + +function TsrVertLayout.GetName:RawByteString; +begin + Result:='atParam'+IntToStr(FBinding); +end; + +procedure TsrVertLayoutList.Init(cb:TfnAlloc); +begin + Alloc:=cb; +end; + +function TsrVertLayoutList.Fetch(p:PsrDataLayout):PsrVertLayout; +var + node:TsrVertLayout; +begin + node:=Default(TsrVertLayout); + node.pLayout:=p; + Result:=FNTree.Find(@node); + if (Result=nil) then + begin + Result:=Alloc(SizeOf(TsrVertLayout)); + Result^.pLayout:=p; + Result^.FStorage:=StorageClass.Input; + Result^.FBinding:=-1; + FNTree.Insert(Result); + end; +end; + +Function TsrVertLayoutList.First:PsrVertLayout; +begin + Result:=FNTree.Min; +end; + +Function TsrVertLayoutList.Next(node:PsrVertLayout):PsrVertLayout; +begin + Result:=FNTree.Next(node); +end; + +procedure TsrVertLayoutList.AllocBinding(Decorates:PsrDecorateList); +var + node:PsrVertLayout; + pVar:PsrVariable; + FBinding:Integer; +begin + if (Decorates=nil) then Exit; + FBinding:=0; + node:=First; + While (node<>nil) do + begin + pVar:=node^.pVar; + if (pVar<>nil) then + begin + if (node^.FBinding=-1) then //alloc + begin + Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,FBinding); + node^.FBinding:=FBinding; + Inc(FBinding); + end; + end; + node:=Next(node); + end; +end; + +procedure TsrVertLayoutList.AllocEntryPoint(EntryPoint:PSpirvOp); +var + node:PsrVertLayout; + pVar:PsrVariable; +begin + if (EntryPoint=nil) then Exit; + node:=First; + While (node<>nil) do + begin + pVar:=node^.pVar; + if (pVar<>nil) then + begin + EntryPoint^.AddParam(ntVar,pVar); + end; + node:=Next(node); + end; +end; + +procedure TsrVertLayoutList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList); +var + node:PsrVertLayout; + 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; + +end. + diff --git a/spirv/srVolatile.pas b/spirv/srVolatile.pas new file mode 100644 index 0000000..3697ed5 --- /dev/null +++ b/spirv/srVolatile.pas @@ -0,0 +1,468 @@ +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<PsrVolatile>; + 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 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^.pWriter.SetParam(ntReg,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 (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 + st_tmp.pHead:=tmp^.pWriter.pData; + Assert(st_tmp.pHead<>nil); + + st.Move_from(st_tmp); + + src^.mark_read; + tmp^.pWriter.SetParam(ntReg,src); + + //tmp^.pLine:=dst; + //writeln; + //PrepVolatile(pReg^.pLine,pReg); + + node^.pReg:=nil; + Continue; + 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); + + {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 + 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. +