fpPS4/spirv/srTypes.pas
2022-12-06 21:12:24 +03:00

766 lines
16 KiB
ObjectPascal

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<PsrType>;
TNodeFetch=specialize TNodeFetch<PsrType,TsrType>;
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^.fOpId<n2^.fOpId);
if (Result<>0) then Exit;
//second fCount
Result:=Integer(n1^.fCount>n2^.fCount)-Integer(n1^.fCount<n2^.fCount);
if (Result<>0) 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.