unit srTypes; {$mode objfpc}{$H+} interface uses sysutils, spirv, srType, ginodes, srNode, srLiteral, srRefId; type PsrTypeKey=^TsrTypeKey; TsrTypeKey=packed record fdtype:TsrDataType; fsize :DWORD; fOpId :WORD; fcount:WORD; pData :PPsrNode; end; PPsrType=^TsrType; TsrType=class(TsrNode) public pPrev,pNext,pLeft,pRight:TsrType; class function c(n1,n2:PsrTypeKey):Integer; static; private ID:TsrRefId; //post id key:TsrTypeKey; public // Procedure _zero_read ; override; Procedure _zero_unread ; override; function _Next :TsrNode; override; function _Prev :TsrNode; override; function _GetPrintName:RawByteString; override; function _GetRef :Pointer; override; // property size:DWORD read key.fsize; property OpId:WORD read key.fOpId; property count:WORD read key.fcount; property ItemCount:WORD read key.fcount; function dtype:TsrDataType; function GetItem(i:Word):TsrNode; function GetDWORD(i:Word):DWORD; function array_stride:DWORD; function is_array_image:Boolean; function array_image_info:TsrTypeImageInfo; function array_count:DWORD; function storage_class:DWORD; function is_image:Boolean; function image_info:TsrTypeImageInfo; function GetPrintName:RawByteString; end; ntType=TsrType; PsrTypeList=^TsrTypeList; TsrTypeList=object type TNodeList=specialize TNodeListClass; TNodeTree=specialize TNodeTreeClass; var FEmit:TCustomEmit; FList:TNodeList; FTree:TNodeTree; Procedure Init(Emit:TCustomEmit); function _Insert(key:PsrTypeKey;copy:Boolean):TsrType; function _Fetch(key:PsrTypeKey;copy:Boolean):TsrType; function _Fetch0(dtype:TsrDataType;OpId:DWORD):TsrType; function _FetchVector(dtype:TsrDataType):TsrType; function _FetchInt(dtype:TsrDataType):TsrType; function _FetchFloat(dtype:TsrDataType):TsrType; function _FetchStruct2(dtype:TsrDataType):TsrType; function _FetchConst(dtype:TsrDataType;Value:QWORD):TsrType; function Fetch(dtype:TsrDataType):TsrType; function FetchPointer(child:TsrType;storage_class:DWORD):TsrType; function FetchFunction(ret:TsrType):TsrType; function FetchFunction(copy:Boolean;count:Byte;pData:PPsrType):TsrType; function FetchStruct (count:Word;pData:PPsrType;copy:Boolean;_size:QWORD):TsrType; function InsertStruct(count:Word;pData:PPsrType;copy:Boolean;_size:QWORD):TsrType; function FetchArray(child:TsrType;array_count:DWORD):TsrType; function FetchRuntimeArray(child:TsrType):TsrType; function FetchImage(child:TsrType;image_info:TsrTypeImageInfo):TsrType; function FetchSampledImage(child:TsrType):TsrType; function First:TsrType; inline; end; operator := (i:TsrNode):TsrType; inline; implementation operator := (i:TsrNode):TsrType; inline; begin Result:=TsrType(Pointer(i)); //typecast hack end; // Procedure TsrType._zero_read; var i:DWORD; begin if (count<>0) then For i:=0 to count-1 do begin GetItem(i).mark_read(Self); end; end; Procedure TsrType._zero_unread; var i:DWORD; begin if (count<>0) then For i:=0 to count-1 do begin GetItem(i).mark_unread(Self); end; end; function TsrType._Next:TsrNode; begin Result:=pNext; end; function TsrType._Prev:TsrNode; begin Result:=pPrev; end; function TsrType._GetPrintName:RawByteString; begin Result:=GetPrintName; end; function TsrType._GetRef:Pointer; begin Result:=@ID; end; // class function TsrType.c(n1,n2:PsrTypeKey):Integer; begin //first OpId Result:=ord(n1^.fOpId>n2^.fOpId)-ord(n1^.fOpId0) then Exit; //second fCount Result:=ord(n1^.fCount>n2^.fCount)-ord(n1^.fCount0) then Exit; //third pData (order sort) Result:=CompareNodes(n1^.pData,n2^.pData,n1^.fCount); end; function TsrType.dtype:TsrDataType; begin Result:=dtUnknow; if (Self=nil) then Exit; Result:=key.fdtype; end; function TsrType.GetItem(i:Word):TsrNode; begin if (i>Count) then Exit(nil); Result:=key.pData[i]; end; function TsrType.GetDWORD(i:Word):DWORD; var pCount:TsrLiteral; begin Result:=0; if (i>Count) then Exit; pCount:=key.pData[i].specialize AsType; if (pCount=nil) then Exit; Result:=pCount.Value; end; function TsrType.array_stride:DWORD; var child:TsrType; begin Result:=0; if not (dtype in [dtTypeArray,dtTypeRuntimeArray]) then Exit; child:=GetItem(0).specialize AsType; if (child=nil) then Exit; Result:=child.size; end; function TsrType.is_array_image:Boolean; var child:TsrType; begin Result:=False; if not (dtype in [dtTypeArray,dtTypeRuntimeArray]) then Exit; child:=GetItem(0).specialize AsType; if (child=nil) then Exit; Result:=child.is_image; end; function TsrType.array_image_info:TsrTypeImageInfo; var child:TsrType; begin Result:=Default(TsrTypeImageInfo); if not (dtype in [dtTypeArray,dtTypeRuntimeArray]) then Exit; child:=GetItem(0).specialize AsType; if (child=nil) then Exit; Result:=child.image_info; end; function TsrType.array_count:DWORD; var pConst:TsrType; begin Result:=0; if (dtype<>dtTypeArray) then Exit; pConst:=GetItem(1).specialize AsType; if (pConst=nil) then Exit; Result:=pConst.GetDWORD(1); end; function TsrType.storage_class:DWORD; begin Result:=0; if (dtype<>dtTypePointer) then Exit; Result:=GetDWORD(0); end; function TsrType.is_image:Boolean; begin Result:=(dtype=dtTypeImage); end; function TsrType.image_info:TsrTypeImageInfo; begin Result:=Default(TsrTypeImageInfo); if (dtype<>dtTypeImage) then Exit; if (Count<>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:TsrType):RawByteString; var R:PsrRefId; child:TsrType; 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).specialize AsType; 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).specialize AsType; 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).specialize AsType; 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).specialize AsType; 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:TsrType):RawByteString; var child:TsrType; begin case node.dtype of dtTypePointer: begin child:=node.GetItem(1).specialize AsType; 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(key:PsrTypeKey;copy:Boolean):TsrType; var size:ptruint; begin Result:=FEmit.specialize New; Result.key:=key^; if copy and (key^.fCount<>0) then begin size:=SizeOf(Pointer)*key^.fCount; Result.key.pData:=FEmit.Alloc(size); Move(key^.pData^,Result.key.pData^,Size); end; FList.Push_tail(Result); end; function TsrTypeList._Fetch(key:PsrTypeKey;copy:Boolean):TsrType; begin Result:=FTree.Find(key); if (Result=nil) then begin Result:=_Insert(key,copy); FTree.Insert(Result); end; end; function TsrTypeList._Fetch0(dtype:TsrDataType;OpId:DWORD):TsrType; var key:TsrTypeKey; begin Result:=nil; // key:=Default(TsrTypeKey); key.fdtype:=dtype; key.fsize :=dtype.BitSize div 8; key.fOpId :=OpId; // Result:=_Fetch(@key,True); end; function TsrTypeList._FetchVector(dtype:TsrDataType):TsrType; var pLiteralList:PsrLiteralList; key:TsrTypeKey; item:array[0..1] of TsrNode; begin Result:=nil; pLiteralList:=FEmit.GetLiteralList; // item[0]:=Fetch(dtype.Child); item[1]:=pLiteralList^.FetchLiteral(dtype.Count,nil); // key:=Default(TsrTypeKey); key.fdtype:=dtype; key.fsize :=dtype.BitSize div 8; key.fOpId :=Op.OpTypeVector; key.fCount:=2; key.pData :=@item; // Result:=_Fetch(@key,True); end; function TsrTypeList._FetchInt(dtype:TsrDataType):TsrType; var pLiteralList:PsrLiteralList; key:TsrTypeKey; item:array[0..1] of TsrNode; begin Result:=nil; pLiteralList:=FEmit.GetLiteralList; // item[0]:=pLiteralList^.FetchLiteral(dtype.BitSize,nil); item[1]:=pLiteralList^.FetchLiteral(dtype.Sign ,nil); // key:=Default(TsrTypeKey); key.fdtype:=dtype; key.fsize :=dtype.BitSize div 8; key.fOpId :=Op.OpTypeInt; key.fCount:=2; key.pData :=@item; // Result:=_Fetch(@key,True); end; function TsrTypeList._FetchFloat(dtype:TsrDataType):TsrType; var pLiteralList:PsrLiteralList; key:TsrTypeKey; item:array[0..0] of TsrNode; begin Result:=nil; pLiteralList:=FEmit.GetLiteralList; // item[0]:=pLiteralList^.FetchLiteral(dtype.BitSize,nil); // key:=Default(TsrTypeKey); key.fdtype:=dtype; key.fsize :=dtype.BitSize div 8; key.fOpId :=Op.OpTypeFloat; key.fCount:=1; key.pData :=@item; // Result:=_Fetch(@key,True); end; function TsrTypeList._FetchStruct2(dtype:TsrDataType):TsrType; var key:TsrTypeKey; item:array[0..1] of TsrNode; begin Result:=nil; item[0]:=Fetch(dtype.Child); item[1]:=item[0]; // key:=Default(TsrTypeKey); key.fdtype:=dtype; key.fsize :=dtype.BitSize div 8; key.fOpId :=Op.OpTypeStruct; key.fCount:=2; key.pData :=@item; // Result:=_Fetch(@key,True); end; function TsrTypeList._FetchConst(dtype:TsrDataType;Value:QWORD):TsrType; var pLiteralList:PsrLiteralList; key:TsrTypeKey; item:array[0..1] of TsrNode; begin Result:=nil; pLiteralList:=FEmit.GetLiteralList; // item[0]:=Fetch(dtype); item[1]:=pLiteralList^.FetchConst(dtype,Value); // key:=Default(TsrTypeKey); key.fdtype:=dtConstant; key.fsize :=dtype.BitSize div 8; key.fOpId :=Op.OpConstant; key.fCount:=2; key.pData :=@item; // Result:=_Fetch(@key,True); end; function TsrTypeList.Fetch(dtype:TsrDataType):TsrType; 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, dtStruct2i64, dtStruct2u64: begin Result:=_FetchStruct2(dtype); end; // else Assert(false); end; end; function TsrTypeList.FetchPointer(child:TsrType;storage_class:DWORD):TsrType; var pLiteralList:PsrLiteralList; key:TsrTypeKey; item:array[0..1] of TsrNode; begin Assert(child<>nil); pLiteralList:=FEmit.GetLiteralList; // item[0]:=pLiteralList^.FetchLiteral(storage_class,PChar(StorageClass.GetStr(storage_class))); item[1]:=child; // key:=Default(TsrTypeKey); key.fdtype:=dtTypePointer; key.fOpId :=Op.OpTypePointer; key.fCount:=2; key.pData :=@item; // Result:=_Fetch(@key,True); end; function TsrTypeList.FetchFunction(ret:TsrType):TsrType; var key:TsrTypeKey; begin Assert(ret<>nil); // key:=Default(TsrTypeKey); key.fdtype:=dtTypeFunction; key.fOpId :=Op.OpTypeFunction; key.fCount:=1; key.pData :=@ret; // Result:=_Fetch(@key,True); end; function TsrTypeList.FetchFunction(copy:Boolean;count:Byte;pData:PPsrType):TsrType; var key:TsrTypeKey; begin Assert(count<>0); Assert(pData<>nil); // key:=Default(TsrTypeKey); key.fdtype:=dtTypeFunction; key.fOpId :=Op.OpTypeFunction; key.fCount:=count; key.pData :=Pointer(pData); // Result:=_Fetch(@key,copy); end; function TsrTypeList.FetchStruct(count:Word;pData:PPsrType;copy:Boolean;_size:QWORD):TsrType; var key:TsrTypeKey; begin Assert(count<>0); Assert(pData<>nil); Assert(_size<>0); // key:=Default(TsrTypeKey); key.fdtype:=dtTypeStruct; key.fsize :=_size; key.fOpId :=Op.OpTypeStruct; key.fCount:=count; key.pData :=Pointer(pData); // Result:=_Fetch(@key,copy); end; function TsrTypeList.InsertStruct(count:Word;pData:PPsrType;copy:Boolean;_size:QWORD):TsrType; var key:TsrTypeKey; begin Assert(count<>0); Assert(pData<>nil); Assert(_size<>0); // key:=Default(TsrTypeKey); key.fdtype:=dtTypeStruct; key.fsize :=_size; key.fOpId :=Op.OpTypeStruct; key.fCount:=count; key.pData :=Pointer(pData); // Result:=_Insert(@key,copy); end; function TsrTypeList.FetchArray(child:TsrType;array_count:DWORD):TsrType; var key:TsrTypeKey; item:array[0..1] of TsrType; begin Assert(child<>nil); // item[0]:=child; item[1]:=_FetchConst(dtUInt32,array_count); // key:=Default(TsrTypeKey); key.fdtype:=dtTypeArray; key.fsize :=child.size*array_count; key.fOpId :=Op.OpTypeArray; key.fCount:=2; key.pData :=@item; // Result:=_Fetch(@key,True); end; function TsrTypeList.FetchRuntimeArray(child:TsrType):TsrType; var key:TsrTypeKey; begin Assert(child<>nil); // key:=Default(TsrTypeKey); key.fdtype:=dtTypeRuntimeArray; key.fsize :=DWORD(-1); key.fOpId :=Op.OpTypeRuntimeArray; key.fCount:=1; key.pData :=@child; // Result:=_Fetch(@key,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:TsrType;image_info:TsrTypeImageInfo):TsrType; var pLiteralList:PsrLiteralList; key:TsrTypeKey; item:array[0..6] of TsrNode; 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))); // key:=Default(TsrTypeKey); key.fdtype:=dtTypeImage; key.fOpId :=Op.OpTypeImage; key.fCount:=7; key.pData :=@item; // Result:=_Fetch(@key,True); end; function TsrTypeList.FetchSampledImage(child:TsrType):TsrType; var key:TsrTypeKey; begin Assert(child<>nil); // key:=Default(TsrTypeKey); key.fdtype:=dtTypeSampledImage; key.fOpId :=Op.OpTypeSampledImage; key.fCount:=1; key.pData :=@child; // Result:=_Fetch(@key,True); end; function TsrTypeList.First:TsrType; inline; begin Result:=FList.pHead; end; end.