FPPS4/spirv/srTypes.pas

804 lines
17 KiB
Plaintext

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<TsrType>;
TNodeTree=specialize TNodeTreeClass<TsrType>;
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^.fOpId<n2^.fOpId);
if (Result<>0) then Exit;
//second fCount
Result:=ord(n1^.fCount>n2^.fCount)-ord(n1^.fCount<n2^.fCount);
if (Result<>0) 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<ntLiteral>;
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<ntType>;
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<ntType>;
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<ntType>;
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<ntType>;
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<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).specialize 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).specialize 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).specialize 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:TsrType):RawByteString;
var
child:TsrType;
begin
case node.dtype of
dtTypePointer:
begin
child:=node.GetItem(1).specialize 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(key:PsrTypeKey;copy:Boolean):TsrType;
var
size:ptruint;
begin
Result:=FEmit.specialize New<TsrType>;
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.