unit srTypes; {$mode objfpc}{$H+} interface uses sysutils, spirv, srType, ginodes, srNode, srLiteral, srRefId; type ntType=class(TsrNodeVmt) class Procedure zero_read (node:PsrNode); override; class Procedure zero_unread (node:PsrNode); override; class function Next (node:PsrNode):Pointer; override; class function Prev (node:PsrNode):Pointer; override; class function GetPrintName(node:PsrNode):RawByteString; override; class function GetRef (node:PsrNode):Pointer; override; end; PPsrType=^PsrType; PsrType=^TsrType; TsrType=packed object(TsrNode) private pPrev,pNext,pLeft,pRight:PsrType; // ID:TsrRefId; //post id fdtype:TsrDataType; fsize:DWORD; fOpId:WORD; fcount:WORD; pData:PPsrNode; function c(n1,n2:PsrType):Integer; static; public property size:DWORD read fsize; property OpId:WORD read fOpId; property ItemCount:WORD read fcount; Procedure Init; inline; function dtype:TsrDataType; function GetItem(i:Word):PsrNode; function GetDWORD(i:Word):DWORD; function array_stride:DWORD; function array_count:DWORD; function storage_class:DWORD; function image_info:TsrTypeImageInfo; function GetPrintName:RawByteString; end; PsrTypeList=^TsrTypeList; TsrTypeList=object type TNodeList=specialize TNodeList; TNodeFetch=specialize TNodeFetch; var FEmit:TCustomEmit; FList:TNodeList; FNTree:TNodeFetch; Procedure Init(Emit:TCustomEmit); function _Insert(node:PsrType;copy:Boolean):PsrType; function _Fetch(node:PsrType;copy:Boolean):PsrType; function _Fetch0(dtype:TsrDataType;OpId:DWORD):PsrType; function _FetchVector(dtype:TsrDataType):PsrType; function _FetchInt(dtype:TsrDataType):PsrType; function _FetchFloat(dtype:TsrDataType):PsrType; function _FetchStruct2(dtype:TsrDataType):PsrType; function _FetchConst(dtype:TsrDataType;Value:QWORD):PsrType; function Fetch(dtype:TsrDataType):PsrType; function FetchPointer(child:PsrType;storage_class:DWORD):PsrType; function FetchFunction(ret:PsrType):PsrType; function FetchFunction(copy:Boolean;count:Byte;pData:PPsrType):PsrType; function FetchStruct (count:Word;pData:PPsrType;copy:Boolean;_size:DWORD):PsrType; function InsertStruct(count:Word;pData:PPsrType;copy:Boolean;_size:DWORD):PsrType; function FetchArray(child:PsrType;array_count:DWORD):PsrType; function FetchRuntimeArray(child:PsrType):PsrType; function FetchImage(child:PsrType;image_info:TsrTypeImageInfo):PsrType; function FetchSampledImage(child:PsrType):PsrType; function First:PsrType; inline; end; implementation // class Procedure ntType.zero_read(node:PsrNode); var i:DWORD; begin With PsrType(node)^ do begin if (fcount<>0) then For i:=0 to fcount-1 do begin GetItem(i)^.mark_read(node); end; end; end; class Procedure ntType.zero_unread(node:PsrNode); var i:DWORD; begin With PsrType(node)^ do begin if (fcount<>0) then For i:=0 to fcount-1 do begin GetItem(i)^.mark_unread(node); end; end; end; class function ntType.Next(node:PsrNode):Pointer; begin Result:=PsrType(node)^.pNext; end; class function ntType.Prev(node:PsrNode):Pointer; begin Result:=PsrType(node)^.pPrev; end; class function ntType.GetPrintName(node:PsrNode):RawByteString; begin Result:=PsrType(node)^.GetPrintName; end; class function ntType.GetRef(node:PsrNode):Pointer; begin Result:=@PsrType(node)^.ID; end; // Procedure TsrType.Init; inline; begin fntype:=ntType; end; function TsrType.c(n1,n2:PsrType):Integer; begin //first OpId Result:=Integer(n1^.fOpId>n2^.fOpId)-Integer(n1^.fOpId0) then Exit; //second fCount Result:=Integer(n1^.fCount>n2^.fCount)-Integer(n1^.fCount0) then Exit; //third pData Result:=ComparePtruint(PPtruint(n1^.pData),PPtruint(n2^.pData),n1^.fCount); end; function TsrType.dtype:TsrDataType; begin Result:=dtUnknow; if (@Self=nil) then Exit; Result:=fdtype; end; function TsrType.GetItem(i:Word):PsrNode; begin if (i>fCount) then Exit(nil); Result:=pData[i]; end; function TsrType.GetDWORD(i:Word):DWORD; var pCount:PsrLiteral; begin Result:=0; if (i>fCount) then Exit; pCount:=pData[i]^.AsType(ntLiteral); if (pCount=nil) then Exit; Result:=pCount^.Value; end; function TsrType.array_stride:DWORD; var child:PsrType; begin Result:=0; Case fdtype of dtTypeArray:; dtTypeRuntimeArray:; else Exit; end; child:=GetItem(0)^.AsType(ntType); if (child=nil) then Exit; Result:=child^.fsize; end; function TsrType.array_count:DWORD; var pConst:PsrType; begin Result:=0; if (fdtype<>dtTypeArray) then Exit; pConst:=GetItem(1)^.AsType(ntType); if (pConst=nil) then Exit; Result:=pConst^.GetDWORD(1); end; function TsrType.storage_class:DWORD; begin Result:=0; if (fdtype<>dtTypePointer) then Exit; Result:=GetDWORD(0); end; function TsrType.image_info:TsrTypeImageInfo; begin Result:=Default(TsrTypeImageInfo); if (fdtype<>dtTypeImage) then Exit; if (fCount<>7) then Exit; // Result.Dim :=GetDWORD(1); Result.Depth :=GetDWORD(2); Result.Arrayed:=GetDWORD(3); Result.MS :=GetDWORD(4); Result.Sampled:=GetDWORD(5); Result.Format :=GetDWORD(6); end; function type_get_base_name2(node:PsrType):RawByteString; var R:PsrRefId; child:PsrType; begin Result:=''; case node^.dtype of dtTypeImage: begin R:=node^.GetRef; Assert(R<>nil ,'type_get_base_name2$1'); Assert(R^.Alloc,'type_get_base_name2$2'); Result:='ti'+IntToStr(R^.ID); end; dtTypeSampledImage: begin child:=node^.GetItem(0)^.AsType(ntType); if (child=nil) then Exit; Result:=type_get_base_name2(child); if (Result='') then Exit; Result:='tm'+Result; end; dtTypeArray: begin child:=node^.GetItem(0)^.AsType(ntType); if (child=nil) then Exit; Result:=type_get_base_name2(child); if (Result='') then Exit; Result:='ta'+Result+IntToStr(node^.array_count); end; dtTypeRuntimeArray: begin child:=node^.GetItem(0)^.AsType(ntType); if (child=nil) then Exit; Result:=type_get_base_name2(child); if (Result='') then Exit; Result:='tr'+Result; end; dtTypeStruct: begin Assert(node^.ID.Alloc); Result:='ts'+IntToStr(node^.ID.ID); end; dtTypeFunction: begin child:=node^.GetItem(0)^.AsType(ntType); if (child=nil) then Exit; Result:=type_get_base_name2(child); if (Result='') then Exit; Result:='tf'+Result; end; dtConstant: begin Result:='tc'+IntToStr(node^.GetDWORD(1)); end; else Result:=type_get_base_name1(node^.dtype); end; end; function type_get_base_name3(node:PsrType):RawByteString; var child:PsrType; begin case node^.dtype of dtTypePointer: begin child:=node^.GetItem(1)^.AsType(ntType); if (child=nil) then Exit; Result:=type_get_base_name2(child); if (Result='') then Exit; Case node^.storage_class of StorageClass.UniformConstant :Result:='p'+Result+'_uc'; StorageClass.Input :Result:='p'+Result+'_in'; StorageClass.Uniform :Result:='p'+Result+'_uf'; StorageClass.Output :Result:='p'+Result+'_ot'; StorageClass.Workgroup :Result:='p'+Result+'_wg'; StorageClass.CrossWorkgroup :Result:='p'+Result+'_cw'; StorageClass.Private_ :Result:='p'+Result+'_pv'; StorageClass.Function_ :Result:='p'+Result+'_fc'; StorageClass.PushConstant :Result:='p'+Result+'_pc'; StorageClass.Image :Result:='p'+Result+'_im'; StorageClass.StorageBuffer :Result:='p'+Result+'_sb'; else Exit(''); end; end; else begin Result:=type_get_base_name2(node); end; end; end; function TsrType.GetPrintName:RawByteString; begin Result:=type_get_base_name3(@Self); if (Result='') then begin Assert(ID.Alloc); Result:='t'+IntToStr(ID.ID); end; end; // Procedure TsrTypeList.Init(Emit:TCustomEmit); begin FEmit:=Emit; end; function TsrTypeList._Insert(node:PsrType;copy:Boolean):PsrType; var size:ptruint; begin Result:=FEmit.Alloc(SizeOf(TsrType)); Move(node^,Result^,SizeOf(TsrType)); if copy and (node^.fCount<>0) then begin size:=SizeOf(Pointer)*node^.fCount; Result^.pData:=FEmit.Alloc(size); Move(node^.pData^,Result^.pData^,Size); end; FList.Push_tail(Result); end; function TsrTypeList._Fetch(node:PsrType;copy:Boolean):PsrType; begin Result:=FNTree.Find(node); if (Result=nil) then begin Result:=_Insert(node,copy); FNTree.Insert(Result); end; end; function TsrTypeList._Fetch0(dtype:TsrDataType;OpId:DWORD):PsrType; var node:TsrType; begin Result:=nil; // node:=Default(TsrType); node.Init; node.fdtype:=dtype; node.fsize :=dtype.BitSize div 8; node.fOpId :=OpId; Result:=_Fetch(@node,True); end; function TsrTypeList._FetchVector(dtype:TsrDataType):PsrType; var pLiteralList:PsrLiteralList; node:TsrType; item:array[0..1] of PsrNode; begin Result:=nil; pLiteralList:=FEmit.GetLiteralList; // item[0]:=Fetch(dtype.Child); item[1]:=pLiteralList^.FetchLiteral(dtype.Count,nil); // node:=Default(TsrType); node.Init; node.fdtype:=dtype; node.fsize :=dtype.BitSize div 8; node.fOpId :=Op.OpTypeVector; node.fCount:=2; node.pData :=@item; Result:=_Fetch(@node,True); end; function TsrTypeList._FetchInt(dtype:TsrDataType):PsrType; var pLiteralList:PsrLiteralList; node:TsrType; item:array[0..1] of PsrNode; begin Result:=nil; pLiteralList:=FEmit.GetLiteralList; // item[0]:=pLiteralList^.FetchLiteral(dtype.BitSize,nil); item[1]:=pLiteralList^.FetchLiteral(dtype.Sign ,nil); // node:=Default(TsrType); node.Init; node.fdtype:=dtype; node.fsize :=dtype.BitSize div 8; node.fOpId :=Op.OpTypeInt; node.fCount:=2; node.pData :=@item; Result:=_Fetch(@node,True); end; function TsrTypeList._FetchFloat(dtype:TsrDataType):PsrType; var pLiteralList:PsrLiteralList; node:TsrType; item:array[0..0] of PsrNode; begin Result:=nil; pLiteralList:=FEmit.GetLiteralList; // item[0]:=pLiteralList^.FetchLiteral(dtype.BitSize,nil); // node:=Default(TsrType); node.Init; node.fdtype:=dtype; node.fsize :=dtype.BitSize div 8; node.fOpId :=Op.OpTypeFloat; node.fCount:=1; node.pData :=@item; Result:=_Fetch(@node,True); end; function TsrTypeList._FetchStruct2(dtype:TsrDataType):PsrType; var node:TsrType; item:array[0..1] of PsrNode; begin Result:=nil; item[0]:=Fetch(dtype.Child); item[1]:=item[0]; // node:=Default(TsrType); node.Init; node.fdtype:=dtype; node.fsize :=dtype.BitSize div 8; node.fOpId :=Op.OpTypeStruct; node.fCount:=2; node.pData :=@item; Result:=_Fetch(@node,True); end; function TsrTypeList._FetchConst(dtype:TsrDataType;Value:QWORD):PsrType; var pLiteralList:PsrLiteralList; node:TsrType; item:array[0..1] of PsrNode; begin Result:=nil; pLiteralList:=FEmit.GetLiteralList; // item[0]:=Fetch(dtype); item[1]:=pLiteralList^.FetchConst(dtype,Value); // node:=Default(TsrType); node.Init; node.fdtype:=dtConstant; node.fsize :=dtype.BitSize div 8; node.fOpId :=Op.OpConstant; node.fCount:=2; node.pData :=@item; Result:=_Fetch(@node,True); end; function TsrTypeList.Fetch(dtype:TsrDataType):PsrType; begin Result:=nil; Case dtype of dtUnknow:; dtBool: begin Result:=_Fetch0(dtype,Op.OpTypeBool); end; // dtInt8, dtUint8, dtInt16, dtUint16, dtInt32, dtUint32, dtInt64, dtUint64: begin Result:=_FetchInt(dtype); end; dtHalf16, dtFloat32, dtFloat64: begin Result:=_FetchFloat(dtype); end; dtTypeVoid: begin Result:=_Fetch0(dtype,Op.OpTypeVoid); end; dtTypeSampler: begin Result:=_Fetch0(dtype,Op.OpTypeSampler); end; // dtVec2b, dtVec3b, dtVec4b, dtVec2u8, dtVec4u8, dtVec2i8, dtVec4i8, dtVec2u16, dtVec4u16, dtVec2i16, dtVec4i16, dtVec2u, dtVec3u, dtVec4u, dtVec2i, dtVec3i, dtVec4i, dtVec2h, dtVec4h, dtVec2f, dtVec3f, dtVec4f: begin Result:=_FetchVector(dtype); end; // dtStruct2i, dtStruct2u: begin Result:=_FetchStruct2(dtype); end; // else Assert(false); end; end; function TsrTypeList.FetchPointer(child:PsrType;storage_class:DWORD):PsrType; var pLiteralList:PsrLiteralList; node:TsrType; item:array[0..1] of PsrNode; begin Assert(child<>nil); pLiteralList:=FEmit.GetLiteralList; // item[0]:=pLiteralList^.FetchLiteral(storage_class,PChar(StorageClass.GetStr(storage_class))); item[1]:=child; // node:=Default(TsrType); node.Init; node.fdtype:=dtTypePointer; node.fOpId :=Op.OpTypePointer; node.fCount:=2; node.pData :=@item; Result:=_Fetch(@node,True); end; function TsrTypeList.FetchFunction(ret:PsrType):PsrType; var node:TsrType; begin Assert(ret<>nil); node:=Default(TsrType); node.Init; node.fdtype:=dtTypeFunction; node.fOpId :=Op.OpTypeFunction; node.fCount:=1; node.pData :=@ret; Result:=_Fetch(@node,True); end; function TsrTypeList.FetchFunction(copy:Boolean;count:Byte;pData:PPsrType):PsrType; var node:TsrType; begin Assert(count<>0); Assert(pData<>nil); node:=Default(TsrType); node.Init; node.fdtype:=dtTypeFunction; node.fOpId :=Op.OpTypeFunction; node.fCount:=count; node.pData :=Pointer(pData); Result:=_Fetch(@node,copy); end; function TsrTypeList.FetchStruct(count:Word;pData:PPsrType;copy:Boolean;_size:DWORD):PsrType; var node:TsrType; begin Assert(count<>0); Assert(pData<>nil); Assert(_size<>0); node:=Default(TsrType); node.Init; node.fdtype:=dtTypeStruct; node.fsize :=_size; node.fOpId :=Op.OpTypeStruct; node.fCount:=count; node.pData :=Pointer(pData); Result:=_Fetch(@node,copy); end; function TsrTypeList.InsertStruct(count:Word;pData:PPsrType;copy:Boolean;_size:DWORD):PsrType; var node:TsrType; begin Assert(count<>0); Assert(pData<>nil); Assert(_size<>0); node:=Default(TsrType); node.Init; node.fdtype:=dtTypeStruct; node.fsize :=_size; node.fOpId :=Op.OpTypeStruct; node.fCount:=count; node.pData :=Pointer(pData); Result:=_Insert(@node,copy); end; function TsrTypeList.FetchArray(child:PsrType;array_count:DWORD):PsrType; var node:TsrType; item:array[0..1] of PsrType; begin Assert(child<>nil); // item[0]:=child; item[1]:=_FetchConst(dtUInt32,array_count); // node:=Default(TsrType); node.Init; node.fdtype:=dtTypeArray; node.fsize :=child^.fsize*array_count; node.fOpId :=Op.OpTypeArray; node.fCount:=2; node.pData :=@item; Result:=_Fetch(@node,True); end; function TsrTypeList.FetchRuntimeArray(child:PsrType):PsrType; var node:TsrType; begin Assert(child<>nil); node:=Default(TsrType); node.Init; node.fdtype:=dtTypeRuntimeArray; node.fsize :=DWORD(-1); node.fOpId :=Op.OpTypeRuntimeArray; node.fCount:=1; node.pData :=@child; Result:=_Fetch(@node,True); end; function Dim_GetStr(w:Word):PChar; begin Result:=''; Case w of Dim.Dim1D :Result:='1D'; Dim.Dim2D :Result:='2D'; Dim.Dim3D :Result:='3D'; Dim.Cube :Result:='Cube'; Dim.Rect :Result:='Rect'; Dim.Buffer :Result:='Buffer'; Dim.SubpassData:Result:='SubpassData'; else; end; end; function TsrTypeList.FetchImage(child:PsrType;image_info:TsrTypeImageInfo):PsrType; var pLiteralList:PsrLiteralList; node:TsrType; item:array[0..6] of PsrNode; begin Assert(child<>nil); pLiteralList:=FEmit.GetLiteralList; // item[0]:=child; item[1]:=pLiteralList^.FetchLiteral(image_info.Dim ,Dim_GetStr(image_info.Dim)); item[2]:=pLiteralList^.FetchLiteral(image_info.Depth ,nil); item[3]:=pLiteralList^.FetchLiteral(image_info.Arrayed,nil); item[4]:=pLiteralList^.FetchLiteral(image_info.MS ,nil); item[5]:=pLiteralList^.FetchLiteral(image_info.Sampled,nil); item[6]:=pLiteralList^.FetchLiteral(image_info.Format ,PChar(ImageFormat.GetStr(image_info.Format))); // node:=Default(TsrType); node.Init; node.fdtype:=dtTypeImage; node.fOpId :=Op.OpTypeImage; node.fCount:=7; node.pData :=@item; Result:=_Fetch(@node,True); end; function TsrTypeList.FetchSampledImage(child:PsrType):PsrType; var node:TsrType; begin Assert(child<>nil); node:=Default(TsrType); node.Init; node.fdtype:=dtTypeSampledImage; node.fOpId :=Op.OpTypeSampledImage; node.fCount:=1; node.pData :=@child; Result:=_Fetch(@node,True); end; function TsrTypeList.First:PsrType; inline; begin Result:=FList.pHead; end; end.