fpPS4/spirv/emit_bin.pas

364 lines
6.2 KiB
ObjectPascal
Raw Permalink Normal View History

2022-05-31 07:17:14 +00:00
unit emit_bin;
{$mode ObjFPC}{$H+}
interface
uses
SySutils,
Classes,
spirv,
2022-09-05 13:30:24 +00:00
srNode,
srType,
2022-05-31 07:17:14 +00:00
srTypes,
srConst,
srVariable,
srOp,
srOpUtils,
2022-09-05 13:30:24 +00:00
srCapability,
2022-05-31 07:17:14 +00:00
srRefId,
2022-09-05 13:30:24 +00:00
emit_fetch;
2022-05-31 07:17:14 +00:00
type
TSPIRVHeader=packed record
MAGIC:DWORD;
VERSION:packed record
MINOR:WORD;
MAJOR:WORD;
end;
TOOL_VERSION:WORD;
TOOL_ID:WORD;
BOUND:DWORD;
2022-09-05 13:30:24 +00:00
SCHEMA:DWORD;
2022-05-31 07:17:14 +00:00
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);
2022-09-05 13:30:24 +00:00
Procedure Reset;
2022-05-31 07:17:14 +00:00
Procedure Flush(Stream:TStream);
2022-09-05 13:30:24 +00:00
procedure AddParam(P:DWORD);
procedure AddNode(node:PsrNode);
2022-05-31 07:17:14 +00:00
end;
2022-09-05 13:30:24 +00:00
TSprvEmit_bin=class(TEmitFetch)
2022-05-31 07:17:14 +00:00
procedure SaveToStream(Stream:TStream);
procedure SaveHeader(Stream:TStream;var Header:TSPIRVHeader);
procedure SaveCaps(Stream:TStream);
2022-09-05 13:30:24 +00:00
procedure SaveOpBlock(Stream:TStream;pBlock:PsrOpBlock);
2022-05-31 07:17:14 +00:00
procedure SaveHeaderInfo(Stream:TStream);
procedure SaveTypes(Stream:TStream);
procedure SaveConst(Stream:TStream);
procedure SaveVariable(Stream:TStream);
procedure SaveFunc(Stream:TStream);
procedure SaveOp(Stream:TStream;node:PSpirvOp);
end;
implementation
Procedure TSVInstrBuffer.AllocData;
begin
if (Length(Data)<COUNT) then
begin
SetLength(Data,COUNT);
end;
end;
Procedure TSVInstrBuffer.NewOp(OpId:WORD);
var
I:TSPIRVInstruction;
begin
Assert(COUNT=0,'prev op not flushed');
COUNT:=1;
AllocData;
I.OP:=OpId;
I.COUNT:=0;
Data[0]:=DWORD(I);
end;
2022-09-05 13:30:24 +00:00
Procedure TSVInstrBuffer.Reset;
begin
COUNT:=0;
end;
2022-05-31 07:17:14 +00:00
Procedure TSVInstrBuffer.Flush(Stream:TStream);
begin
if (Stream=nil) or (COUNT=0) then Exit;
TSPIRVInstruction(Data[0]).COUNT:=COUNT;
Stream.Write(Data[0],COUNT*SizeOf(DWORD));
2022-09-05 13:30:24 +00:00
Reset;
2022-05-31 07:17:14 +00:00
end;
2022-09-05 13:30:24 +00:00
procedure TSVInstrBuffer.AddParam(P:DWORD);
2022-05-31 07:17:14 +00:00
var
I:DWORD;
begin
Assert(COUNT<>0,'new op not created');
I:=COUNT;
Inc(COUNT);
AllocData;
Data[i]:=P;
end;
2022-09-05 13:30:24 +00:00
procedure TSVInstrBuffer.AddNode(node:PsrNode);
2022-05-31 07:17:14 +00:00
var
2022-09-05 13:30:24 +00:00
R:PsrRefId;
2022-05-31 07:17:14 +00:00
I,L,D:DWORD;
begin
2022-09-05 13:30:24 +00:00
Assert(node<>nil);
2022-05-31 07:17:14 +00:00
Assert(COUNT<>0,'new op not created');
2022-09-05 13:30:24 +00:00
R:=node^.GetRef;
if (R<>nil) then
begin
I:=COUNT;
Inc(COUNT);
AllocData;
Data[i]:=R^.ID;
end else
begin
L:=node^.GetData(nil); //get size
D:=(L+(SizeOf(DWORD)-1)) div 4; //align
Assert(D<>0,'AddNode:'+node^.ntype.ClassName);
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
I:=COUNT;
COUNT:=COUNT+D;
AllocData;
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
FillDWord(Data[i],D,0);
node^.GetData(@Data[i]);
2022-05-31 07:17:14 +00:00
end;
end;
procedure TSprvEmit_bin.SaveToStream(Stream:TStream);
var
Header:TSPIRVHeader;
begin
if (Stream=nil) then Exit;
Header:=Default(TSPIRVHeader);
2022-09-05 13:30:24 +00:00
Header.MAGIC :=MagicNumber;
DWORD(Header.VERSION) :=Config.SpvVersion;
Header.TOOL_VERSION:=2;
Header.TOOL_ID :=0;
Header.BOUND :=RefIdAlloc.GetSpirvIDBound;
Header.SCHEMA :=0;
2022-05-31 07:17:14 +00:00
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;
2022-09-05 13:30:24 +00:00
node:PsrCapability;
2022-05-31 07:17:14 +00:00
begin
buf:=Default(TSVInstrBuffer);
2022-09-05 13:30:24 +00:00
node:=CapabilityList.First;
2022-05-31 07:17:14 +00:00
While (node<>nil) do
begin
buf.NewOp(Op.OpCapability);
2022-09-05 13:30:24 +00:00
buf.AddParam(node^.ID);
2022-05-31 07:17:14 +00:00
buf.Flush(Stream);
2022-09-05 13:30:24 +00:00
node:=CapabilityList.Next(node);
2022-05-31 07:17:14 +00:00
end;
end;
2022-09-05 13:30:24 +00:00
procedure TSprvEmit_bin.SaveOpBlock(Stream:TStream;pBlock:PsrOpBlock);
var
node:PSpirvOp;
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
if (pBlock=nil) then Exit;
node:=pBlock^.First;
2022-05-31 07:17:14 +00:00
While (node<>nil) do
begin
2022-09-05 13:30:24 +00:00
if node^.IsType(ntOp) then
begin
SaveOp(Stream,node);
end;
node:=flow_down_next_up(node);
2022-05-31 07:17:14 +00:00
end;
end;
procedure TSprvEmit_bin.SaveHeaderInfo(Stream:TStream);
begin
2022-09-05 13:30:24 +00:00
SaveOpBlock(Stream,@HeaderList);
SaveOpBlock(Stream,@DebugInfoList);
SaveOpBlock(Stream,@DecorateList);
2022-05-31 07:17:14 +00:00
end;
procedure TSprvEmit_bin.SaveTypes(Stream:TStream);
var
buf:TSVInstrBuffer;
node:PsrType;
2022-09-05 13:30:24 +00:00
i:Word;
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
node:=TypeList.First;
2022-05-31 07:17:14 +00:00
While (node<>nil) do
begin
2022-09-05 13:30:24 +00:00
buf.NewOp(node^.OpId);
buf.AddNode(node);
2022-05-31 07:17:14 +00:00
2022-09-05 13:30:24 +00:00
if (node^.ItemCount<>0) then
begin
For i:=0 to node^.ItemCount-1 do
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
buf.AddNode(node^.GetItem(i));
2022-05-31 07:17:14 +00:00
end;
2022-09-05 13:30:24 +00:00
end;
2022-05-31 07:17:14 +00:00
buf.Flush(Stream);
2022-09-05 13:30:24 +00:00
node:=node^.Next;
2022-05-31 07:17:14 +00:00
end;
end;
procedure TSprvEmit_bin.SaveConst(Stream:TStream);
var
buf:TSVInstrBuffer;
node:PsrConst;
2022-09-05 13:30:24 +00:00
i:Word;
2022-05-31 07:17:14 +00:00
begin
buf:=Default(TSVInstrBuffer);
2022-09-05 13:30:24 +00:00
node:=ConstList.FList.pHead;
2022-05-31 07:17:14 +00:00
While (node<>nil) do
begin
2022-09-05 13:30:24 +00:00
if (node^.dtype<>dtUnknow) then
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
buf.NewOp(node^.OpId);
buf.AddNode(node^.pType);
buf.AddNode(node);
if (node^.dtype<>dtBool) and (node^.ItemCount<>0) then
begin
For i:=0 to node^.ItemCount-1 do
begin
buf.AddNode(node^.GetItem(i));
end;
end;
2022-05-31 07:17:14 +00:00
buf.Flush(Stream);
end;
2022-09-05 13:30:24 +00:00
node:=node^.Next;
2022-05-31 07:17:14 +00:00
end;
end;
procedure TSprvEmit_bin.SaveVariable(Stream:TStream);
var
buf:TSVInstrBuffer;
node:PsrVariable;
begin
buf:=Default(TSVInstrBuffer);
2022-09-05 13:30:24 +00:00
node:=VariableList.First;
2022-05-31 07:17:14 +00:00
While (node<>nil) do
begin
if (node^.pType<>nil) then
begin
buf.NewOp(Op.OpVariable);
2022-09-05 13:30:24 +00:00
buf.AddNode(node^.pType);
buf.AddNode(node);
buf.AddParam(node^.GetStorageClass);
2022-05-31 07:17:14 +00:00
buf.Flush(Stream);
end;
2022-09-05 13:30:24 +00:00
node:=node^.Next;
2022-05-31 07:17:14 +00:00
end;
end;
procedure TSprvEmit_bin.SaveFunc(Stream:TStream);
var
pFunc:PSpirvFunc;
begin
2022-09-05 13:30:24 +00:00
pFunc:=FuncList.First;
2022-05-31 07:17:14 +00:00
While (pFunc<>nil) do
begin
2022-09-05 13:30:24 +00:00
SaveOpBlock(Stream,pFunc^.pTop);
pFunc:=pFunc^.Next;
2022-05-31 07:17:14 +00:00
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
2022-09-05 13:30:24 +00:00
Assert(node^.pType<>nil,'SaveOp$1');
if (node^.pType<>nil) then
begin
buf.AddNode(node^.pType);
end else
begin
buf.Reset;
Exit;
end;
2022-05-31 07:17:14 +00:00
end;
if Info.result then //dst
begin
2022-09-05 13:30:24 +00:00
Assert(node^.pDst<>nil,'SaveOp$2');
if (node^.pDst<>nil) then
begin
buf.AddNode(node^.pDst);
end else
begin
buf.Reset;
Exit;
end;
2022-05-31 07:17:14 +00:00
end else
begin //no dst
2022-09-05 13:30:24 +00:00
if (node^.pDst<>nil) then
2022-05-31 07:17:14 +00:00
begin
2022-09-05 13:30:24 +00:00
buf.AddNode(node^.pDst);
2022-05-31 07:17:14 +00:00
end;
end;
2022-09-05 13:30:24 +00:00
Param:=node^.ParamFirst;
2022-05-31 07:17:14 +00:00
While (Param<>nil) do
begin
2022-09-05 13:30:24 +00:00
buf.AddNode(Param^.Value);
Param:=Param^.Next;
2022-05-31 07:17:14 +00:00
end;
buf.Flush(Stream);
end;
end.