mirror of
https://github.com/red-prig/fpPS4.git
synced 2024-10-07 03:33:20 +00:00
add shader recompiler
This commit is contained in:
parent
030ef0c198
commit
d0f86ddcac
62
spirv/Half16.pas
Normal file
62
spirv/Half16.pas
Normal file
@ -0,0 +1,62 @@
|
||||
unit Half16;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
PHalf16=^THalf16;
|
||||
THalf16=bitpacked record
|
||||
man:0..1023;
|
||||
exp:0..31;
|
||||
sgn:0..1;
|
||||
end;
|
||||
|
||||
operator := (i:THalf16):Single;
|
||||
operator := (i:Single):THalf16;
|
||||
|
||||
implementation
|
||||
|
||||
operator := (i:THalf16):Single;
|
||||
var
|
||||
t1,t2,t3:DWORD;
|
||||
begin
|
||||
t1:=Word(i) and $7fff; // Non-sign bits
|
||||
t2:=Word(i) and $8000; // Sign bit
|
||||
t3:=Word(i) and $7c00; // Exponent
|
||||
|
||||
t1:=t1 shl 13; // Align mantissa on MSB
|
||||
t2:=t2 shl 16; // Shift sign bit into position
|
||||
|
||||
t1:=t1+$38000000; // Adjust bias
|
||||
|
||||
if (t3=0) then t1:=0; // Denormals-as-zero
|
||||
|
||||
t1:=t1 or t2; // Re-insert sign bit
|
||||
|
||||
PDWORD(@Result)^:=t1;
|
||||
end;
|
||||
|
||||
operator := (i:Single):THalf16;
|
||||
var
|
||||
t1,t2,t3:DWORD;
|
||||
begin
|
||||
t1:=PDWORD(@i)^ and $7fffffff; // Non-sign bits
|
||||
t2:=PDWORD(@i)^ and $80000000; // Sign bit
|
||||
t3:=PDWORD(@i)^ and $7f800000; // Exponent
|
||||
|
||||
t1:=t1 shr 13; // Align mantissa on MSB
|
||||
t2:=t2 shr 16; // Shift sign bit into position
|
||||
|
||||
t1:=t1-$1c000; // Adjust bias
|
||||
|
||||
if (t3<$38800000) then t1:=0; // Flush-to-zero
|
||||
if (t3>$47000000) then t1:=$7bff; // Clamp-to-max
|
||||
|
||||
t1:=t1 or t2; // Re-insert sign bit
|
||||
|
||||
Word(Result):=Word(t1);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
1749
spirv/SprvEmit.pas
Normal file
1749
spirv/SprvEmit.pas
Normal file
File diff suppressed because it is too large
Load Diff
441
spirv/emit_alloc.pas
Normal file
441
spirv/emit_alloc.pas
Normal file
@ -0,0 +1,441 @@
|
||||
unit emit_alloc;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srConst,
|
||||
srRefId,
|
||||
srReg,
|
||||
srLayout,
|
||||
srBuffer,
|
||||
srVariable,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
SprvEmit;
|
||||
|
||||
type
|
||||
TSprvEmit_alloc=object(TSprvEmit)
|
||||
procedure Alloc;
|
||||
procedure AllocSpirvID(P:PsrRefId);
|
||||
procedure AllocBinding;
|
||||
procedure AllocTypeBinding;
|
||||
procedure AllocSourceExtension;
|
||||
procedure AllocTypeName;
|
||||
Procedure AllocVarName;
|
||||
procedure AllocEntryPoint;
|
||||
procedure AllocHeader;
|
||||
procedure AllocOpListId(node:PspirvOp);
|
||||
procedure AllocHeaderId;
|
||||
procedure AllocTypesId;
|
||||
procedure AllocConstId;
|
||||
procedure AllocVariableId;
|
||||
procedure AllocOpSingle(const Param:TOpParamSingle);
|
||||
procedure AllocOpParamNode(node:POpParamNode);
|
||||
procedure AllocFuncId;
|
||||
procedure AllocOpId(node:PSpirvOp);
|
||||
procedure AllocOpBlock(pBlock:PsrOpBlock);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TSprvEmit_alloc.Alloc;
|
||||
begin
|
||||
AllocBinding;
|
||||
AllocTypeBinding;
|
||||
|
||||
AllocHeader;
|
||||
|
||||
AllocSourceExtension;
|
||||
AllocTypeName;
|
||||
AllocVarName;
|
||||
|
||||
AllocHeaderId;
|
||||
|
||||
AllocTypesId;
|
||||
AllocConstId;
|
||||
AllocVariableId;
|
||||
AllocFuncId;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocSpirvID(P:PsrRefId);
|
||||
begin
|
||||
FSpirvIdAlloc.FetchSpirvID(P);
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocBinding;
|
||||
var
|
||||
FBinding:Integer;
|
||||
begin
|
||||
FInputs .AllocBinding(@FDecorates);
|
||||
FOutputs .AllocBinding(@FDecorates);
|
||||
FVertLayouts.AllocBinding(@FDecorates);
|
||||
FFragLayouts.AllocBinding(@FDecorates);
|
||||
|
||||
FBinding:=0;
|
||||
FUniforms.AllocBinding(FBinding,@FDecorates);
|
||||
FBuffers .AllocBinding(FBinding,@FDecorates);
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocTypeBinding;
|
||||
var
|
||||
node:PsrType;
|
||||
pField:PsrField;
|
||||
begin
|
||||
node:=FSpirvTypes.FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
|
||||
case node^.dtype of
|
||||
dtTypeStruct:
|
||||
begin
|
||||
pField:=node^.key.ext.pField;
|
||||
if (pField<>nil) then
|
||||
begin
|
||||
if (pField^.GetStructDecorate<>DWORD(-1)) then
|
||||
begin
|
||||
FDecorates.emit_decorate(ntType,node,pField^.GetStructDecorate,0);
|
||||
end;
|
||||
pField^.AllocBinding(node,@FDecorates);
|
||||
end;
|
||||
end;
|
||||
|
||||
dtTypeArray,
|
||||
dtTypeRuntimeArray:
|
||||
begin
|
||||
FDecorates.emit_decorate(ntType,node,Decoration.ArrayStride,node^.key.ext.array_stride);
|
||||
end;
|
||||
|
||||
else;
|
||||
end;
|
||||
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocSourceExtension;
|
||||
begin
|
||||
FDataLayouts.AllocSourceExtension(@FDebugInfo);
|
||||
FDataLayouts.AllocFuncExt(@FDebugInfo,FCodeHeap);
|
||||
FVertLayouts.AllocSourceExtension(@FDebugInfo);
|
||||
FUniforms .AllocSourceExtension(@FDebugInfo);
|
||||
FBuffers .AllocSourceExtension(@FDebugInfo);
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocTypeName;
|
||||
var
|
||||
node:PsrType;
|
||||
pField:PsrField;
|
||||
begin
|
||||
node:=FSpirvTypes.FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
|
||||
case node^.dtype of
|
||||
dtTypeStruct:
|
||||
begin
|
||||
pField:=node^.key.ext.pField;
|
||||
if (pField<>nil) and
|
||||
(pField^.parent=nil) and
|
||||
(pField^.pBuffer<>nil) then
|
||||
begin
|
||||
FDebugInfo.emit_name(ntType,node,pField^.pBuffer^.GetStructName);
|
||||
end;
|
||||
end;
|
||||
|
||||
else;
|
||||
end;
|
||||
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TSprvEmit_alloc.AllocVarName;
|
||||
var
|
||||
node:PsrVariable;
|
||||
n:RawByteString;
|
||||
begin
|
||||
node:=FVariables.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.pType<>nil) then
|
||||
begin
|
||||
n:=node^.GetName;
|
||||
if (n<>'') then
|
||||
begin
|
||||
FDebugInfo.emit_name(ntVar,node,n);
|
||||
end;
|
||||
end;
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocOpListId(node:PspirvOp);
|
||||
begin
|
||||
While (node<>nil) do
|
||||
begin
|
||||
AllocOpId(node);
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocEntryPoint;
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
node:=FHeader.AddSpirvOp(Op.OpEntryPoint);
|
||||
|
||||
node^.AddLiteral(FExecutionModel,ExecutionModel.GetStr(FExecutionModel));
|
||||
|
||||
node^.AddParam(ntFunc,FMain);
|
||||
node^.AddString(FMain^.name);
|
||||
|
||||
FInputs .AllocEntryPoint(node);
|
||||
FVertLayouts.AllocEntryPoint(node);
|
||||
FFragLayouts.AllocEntryPoint(node);
|
||||
FOutputs .AllocEntryPoint(node);
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocHeader;
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
node:=FHeader.AddSpirvOp(Op.OpMemoryModel);
|
||||
node^.AddLiteral(AddressingModel.Logical,AddressingModel.GetStr(AddressingModel.Logical));
|
||||
node^.AddLiteral(MemoryModel.GLSL450,MemoryModel.GetStr(MemoryModel.GLSL450));
|
||||
|
||||
AllocEntryPoint;
|
||||
|
||||
Case FExecutionModel of
|
||||
ExecutionModel.Fragment:
|
||||
begin
|
||||
node:=FHeader.AddSpirvOp(Op.OpExecutionMode);
|
||||
node^.AddParam(ntFunc,FMain);
|
||||
node^.AddLiteral(ExecutionMode.OriginUpperLeft,ExecutionMode.GetStr(ExecutionMode.OriginUpperLeft));
|
||||
end;
|
||||
ExecutionModel.GLCompute:
|
||||
begin
|
||||
node:=FHeader.AddSpirvOp(Op.OpExecutionMode);
|
||||
node^.AddParam(ntFunc,FMain);
|
||||
node^.AddLiteral(ExecutionMode.LocalSize,ExecutionMode.GetStr(ExecutionMode.LocalSize));
|
||||
node^.AddLiteral(FLocalSize.x);
|
||||
node^.AddLiteral(FLocalSize.y);
|
||||
node^.AddLiteral(FLocalSize.z);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocHeaderId;
|
||||
begin
|
||||
AllocOpListId(FHeader.pHead);
|
||||
AllocOpListId(FDebugInfo.pHead);
|
||||
AllocOpListId(FDecorates.pHead);
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocTypesId;
|
||||
var
|
||||
node:PsrType;
|
||||
pConst:PsrConst;
|
||||
begin
|
||||
node:=FSpirvTypes.FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
case node^.dtype of
|
||||
dtTypeArray:
|
||||
begin
|
||||
//find a const
|
||||
pConst:=FConsts.Fetchi(dtUInt32,node^.key.ext.array_count);
|
||||
if (pConst^.pType=nil) then
|
||||
begin
|
||||
pConst^.pType:=FSpirvTypes.Fetch(pConst^.key.dtype);
|
||||
AllocSpirvID(@pConst^.pType^.ID);
|
||||
end;
|
||||
FConsts.FList.Remove(pConst);
|
||||
AllocSpirvID(@pConst^.ID);
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
AllocSpirvID(@node^.ID);
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocConstId;
|
||||
var
|
||||
node:PsrConst;
|
||||
begin
|
||||
node:=FConsts.FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.key.dtype<>dtUnknow) then
|
||||
begin
|
||||
AllocSpirvID(@node^.ID)
|
||||
end;
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocVariableId;
|
||||
var
|
||||
node:PsrVariable;
|
||||
begin
|
||||
node:=FVariables.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.pType<>nil) then
|
||||
begin
|
||||
AllocSpirvID(@node^.ID);
|
||||
AllocSpirvID(@node^.pType^.ID);
|
||||
end;
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocOpSingle(const Param:TOpParamSingle);
|
||||
var
|
||||
pReg:PsrRegNode;
|
||||
begin
|
||||
Assert(Param.pData<>nil,'AllocOpSingle$1');
|
||||
Case Param.ntype of
|
||||
|
||||
ntFunc:
|
||||
begin
|
||||
AllocSpirvID(@PSpirvFunc(Param.pData)^.ID);
|
||||
end;
|
||||
|
||||
ntRefId:
|
||||
begin
|
||||
AllocSpirvID(Param.pData);
|
||||
end;
|
||||
|
||||
ntType:
|
||||
begin
|
||||
AllocSpirvID(@PsrType(Param.pData)^.ID);
|
||||
end;
|
||||
|
||||
ntReg:
|
||||
begin
|
||||
pReg:=Param.pData;
|
||||
Case pReg^.pWriter.ntype of
|
||||
ntConst:;
|
||||
ntOp:AllocSpirvID(@pReg^.ID);
|
||||
else
|
||||
Assert(false,'AllocOpSingle$2');
|
||||
end;
|
||||
end;
|
||||
|
||||
ntVar:
|
||||
begin
|
||||
AllocSpirvID(@PsrVariable(Param.pData)^.ID);
|
||||
end;
|
||||
|
||||
ntChain:
|
||||
begin
|
||||
AllocSpirvID(@PsrChain(Param.pData)^.ID);
|
||||
end;
|
||||
|
||||
ntConst:
|
||||
begin
|
||||
AllocSpirvID(@PsrConst(Param.pData)^.ID)
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(false,'AllocOpSingle$3');
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocOpParamNode(node:POpParamNode);
|
||||
begin
|
||||
Case node^.ntype of
|
||||
ntLiteral:;
|
||||
ntString :;
|
||||
else
|
||||
begin
|
||||
AllocOpSingle(node^.AsParam);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocFuncId;
|
||||
var
|
||||
pFunc:PSpirvFunc;
|
||||
begin
|
||||
pFunc:=FSpirvFuncs.FList.pHead;
|
||||
While (pFunc<>nil) do
|
||||
begin
|
||||
AllocOpBlock(@pFunc^.FTop);
|
||||
pFunc:=pFunc^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocOpId(node:PSpirvOp);
|
||||
var
|
||||
Param:POpParamNode;
|
||||
Info:Op.TOpInfo;
|
||||
begin
|
||||
if (node=nil) then Exit;
|
||||
|
||||
Info:=Op.GetInfo(node^.OpId);
|
||||
|
||||
if Info.result then //dst
|
||||
begin
|
||||
Assert(node^.dst.ntype<>ntUnknow,'AllocOp$1');
|
||||
Assert(node^.dst.pData<>nil ,'AllocOp$2');
|
||||
AllocOpSingle(node^.dst);
|
||||
end else
|
||||
begin //no dst
|
||||
if (node^.dst.ntype<>ntUnknow) then
|
||||
begin
|
||||
Assert(node^.dst.pData<>nil,'AllocOp$3');
|
||||
AllocOpSingle(node^.dst);
|
||||
end;
|
||||
end;
|
||||
|
||||
if Info.rstype then //dst type
|
||||
begin
|
||||
Assert(node^.dst_type<>nil,'AllocOp$4');
|
||||
end;
|
||||
|
||||
Param:=node^.pParam.pHead;
|
||||
While (Param<>nil) do
|
||||
begin
|
||||
AllocOpParamNode(Param);
|
||||
Param:=Param^.pNext;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocOpBlock(pBlock:PsrOpBlock);
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
if (pBlock=nil) then Exit;
|
||||
node:=pBlock^.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
|
||||
if (node^.OpId=OpBlock) then
|
||||
begin
|
||||
if (node^.dst.ntype=ntBlock) then
|
||||
begin
|
||||
AllocOpBlock(node^.dst.pData);
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
AllocOpId(node);
|
||||
end;
|
||||
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
555
spirv/emit_bin.pas
Normal file
555
spirv/emit_bin.pas
Normal file
@ -0,0 +1,555 @@
|
||||
unit emit_bin;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
SySutils,
|
||||
Classes,
|
||||
spirv,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
srCap,
|
||||
srRefId,
|
||||
SprvEmit;
|
||||
|
||||
type
|
||||
TSPIRVHeader=packed record
|
||||
MAGIC:DWORD;
|
||||
VERSION:packed record
|
||||
MINOR:WORD;
|
||||
MAJOR:WORD;
|
||||
end;
|
||||
TOOL_VERSION:WORD;
|
||||
TOOL_ID:WORD;
|
||||
BOUND:DWORD;
|
||||
RESERVED:DWORD;
|
||||
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);
|
||||
Procedure Flush(Stream:TStream);
|
||||
procedure AddParamId(P:DWORD);
|
||||
procedure AddString(const name:PChar);
|
||||
procedure AddRefId(P:PsrRefId);
|
||||
procedure AddConstId(P:PsrConst);
|
||||
procedure AddVarId(P:PsrVariable);
|
||||
procedure AddTypeId(P:PsrType);
|
||||
procedure AddFuncId(P:PSpirvFunc);
|
||||
procedure AddChainId(P:PsrChain);
|
||||
procedure AddRegId(P:PsrRegNode);
|
||||
end;
|
||||
|
||||
TSprvEmit_bin=object(TSprvEmit)
|
||||
procedure SaveToStream(Stream:TStream);
|
||||
procedure SaveHeader(Stream:TStream;var Header:TSPIRVHeader);
|
||||
procedure SaveCaps(Stream:TStream);
|
||||
procedure SaveOpList(Stream:TStream;node:PspirvOp);
|
||||
procedure SaveHeaderInfo(Stream:TStream);
|
||||
procedure SaveTypes(Stream:TStream);
|
||||
procedure SaveConst(var buf:TSVInstrBuffer;node:PsrConst);
|
||||
procedure SaveConst(Stream:TStream);
|
||||
procedure SaveVariable(Stream:TStream);
|
||||
procedure SaveFunc(Stream:TStream);
|
||||
procedure SaveOp(Stream:TStream;node:PSpirvOp);
|
||||
procedure SaveOpBlock(Stream:TStream;pBlock:PsrOpBlock);
|
||||
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;
|
||||
|
||||
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));
|
||||
COUNT:=0;
|
||||
end;
|
||||
|
||||
procedure TSVInstrBuffer.AddParamId(P:DWORD);
|
||||
var
|
||||
I:DWORD;
|
||||
begin
|
||||
Assert(COUNT<>0,'new op not created');
|
||||
I:=COUNT;
|
||||
Inc(COUNT);
|
||||
AllocData;
|
||||
Data[i]:=P;
|
||||
end;
|
||||
|
||||
procedure TSVInstrBuffer.AddString(const name:PChar);
|
||||
var
|
||||
I,L,D:DWORD;
|
||||
begin
|
||||
Assert(name<>nil);
|
||||
Assert(COUNT<>0,'new op not created');
|
||||
|
||||
L:=StrLen(name);
|
||||
D:=(L+SizeOf(DWORD)) div SizeOf(DWORD);
|
||||
|
||||
I:=COUNT;
|
||||
COUNT:=COUNT+D;
|
||||
AllocData;
|
||||
|
||||
FillDWord(Data[i],D,0);
|
||||
Move(PChar(name)^,Data[i],L);
|
||||
end;
|
||||
|
||||
procedure TSVInstrBuffer.AddRefId(P:PsrRefId);
|
||||
begin
|
||||
Assert(P<>nil ,'AddRefId$1');
|
||||
Assert(P^.Alloc,'AddRefId$2');
|
||||
AddParamId(P^.ID);
|
||||
end;
|
||||
|
||||
procedure TSVInstrBuffer.AddConstId(P:PsrConst);
|
||||
begin
|
||||
Assert(P<>nil,'AddConstId');
|
||||
AddRefId(@P^.ID);
|
||||
end;
|
||||
|
||||
procedure TSVInstrBuffer.AddVarId(P:PsrVariable);
|
||||
begin
|
||||
Assert(P<>nil,'AddVarId');
|
||||
AddRefId(@P^.ID);
|
||||
end;
|
||||
|
||||
procedure TSVInstrBuffer.AddTypeId(P:PsrType);
|
||||
begin
|
||||
Assert(P<>nil,'AddTypeId');
|
||||
AddRefId(@P^.ID);
|
||||
end;
|
||||
|
||||
procedure TSVInstrBuffer.AddFuncId(P:PSpirvFunc);
|
||||
begin
|
||||
Assert(P<>nil,'AddFuncId');
|
||||
AddRefId(@P^.ID);
|
||||
end;
|
||||
|
||||
procedure TSVInstrBuffer.AddChainId(P:PsrChain);
|
||||
begin
|
||||
Assert(P<>nil,'AddChainId');
|
||||
AddRefId(@P^.ID);
|
||||
end;
|
||||
|
||||
procedure TSVInstrBuffer.AddRegId(P:PsrRegNode);
|
||||
begin
|
||||
Assert(P<>nil,'AddRegId$1');
|
||||
Case P^.pWriter.ntype of
|
||||
ntConst:
|
||||
begin
|
||||
AddConstId(P^.pWriter.pData);
|
||||
end;
|
||||
ntOp:
|
||||
begin
|
||||
AddRefId(@P^.ID);
|
||||
end;
|
||||
else
|
||||
Assert(false,'AddRegId$2');
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_bin.SaveToStream(Stream:TStream);
|
||||
var
|
||||
Header:TSPIRVHeader;
|
||||
begin
|
||||
if (Stream=nil) then Exit;
|
||||
|
||||
Header:=Default(TSPIRVHeader);
|
||||
|
||||
Header.MAGIC:=spirv.MagicNumber;
|
||||
DWORD(Header.VERSION):=FBuffers.cfg.SpvVersion;
|
||||
Header.TOOL_VERSION:=1;
|
||||
Header.BOUND:=FSpirvIdAlloc.GetSpirvIDBound;
|
||||
|
||||
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;
|
||||
node:PSpirvCap;
|
||||
begin
|
||||
buf:=Default(TSVInstrBuffer);
|
||||
node:=FSpirvCaps.First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
buf.NewOp(Op.OpCapability);
|
||||
buf.AddParamId(node^.ID);
|
||||
buf.Flush(Stream);
|
||||
node:=FSpirvCaps.Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_bin.SaveOpList(Stream:TStream;node:PspirvOp);
|
||||
begin
|
||||
While (node<>nil) do
|
||||
begin
|
||||
SaveOp(Stream,node);
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_bin.SaveHeaderInfo(Stream:TStream);
|
||||
begin
|
||||
SaveOpList(Stream,FHeader.pHead);
|
||||
SaveOpList(Stream,FDebugInfo.pHead);
|
||||
SaveOpList(Stream,FDecorates.pHead);
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_bin.SaveTypes(Stream:TStream);
|
||||
var
|
||||
buf:TSVInstrBuffer;
|
||||
node:PsrType;
|
||||
pConst:PsrConst;
|
||||
i:dword;
|
||||
ie:Boolean;
|
||||
begin
|
||||
buf:=Default(TSVInstrBuffer);
|
||||
node:=FSpirvTypes.FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
ie:=True;
|
||||
|
||||
pConst:=nil;
|
||||
case node^.dtype of
|
||||
dtTypeArray:
|
||||
begin
|
||||
//find a const
|
||||
pConst:=FConsts.Fetchi(dtUInt32,node^.key.ext.array_count);
|
||||
SaveConst(buf,pConst);
|
||||
buf.Flush(Stream);
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
|
||||
buf.NewOp(node^.key.OpId);
|
||||
buf.AddTypeId(node);
|
||||
|
||||
case node^.key.OpId of
|
||||
|
||||
Op.OpTypeFloat:
|
||||
begin
|
||||
buf.AddParamId(node^.key.ext.float_size);
|
||||
end;
|
||||
|
||||
Op.OpTypeInt:
|
||||
begin
|
||||
buf.AddParamId(node^.key.ext.int_size);
|
||||
buf.AddParamId(node^.key.ext.int_sign);
|
||||
end;
|
||||
|
||||
Op.OpTypeVector:
|
||||
begin
|
||||
ie:=False;
|
||||
buf.AddTypeId(node^.GetCompItem(0));
|
||||
buf.AddParamId(node^.key.ext.array_count);
|
||||
end;
|
||||
|
||||
Op.OpTypePointer:
|
||||
begin
|
||||
buf.AddParamId(node^.key.ext.Storage_Class);
|
||||
end;
|
||||
|
||||
Op.OpTypeArray:
|
||||
begin
|
||||
ie:=False;
|
||||
buf.AddTypeId(node^.GetCompItem(0));
|
||||
buf.AddConstId(pConst);
|
||||
end;
|
||||
|
||||
Op.OpTypeRuntimeArray:
|
||||
begin
|
||||
ie:=False;
|
||||
buf.AddTypeId(node^.GetCompItem(0));
|
||||
end;
|
||||
|
||||
Op.OpTypeImage:
|
||||
begin
|
||||
ie:=False;
|
||||
buf.AddTypeId(node^.GetCompItem(0));
|
||||
With node^.key.ext.image do
|
||||
begin
|
||||
buf.AddParamId(Dim);
|
||||
buf.AddParamId(Depth);
|
||||
buf.AddParamId(Arrayed);
|
||||
buf.AddParamId(MS);
|
||||
buf.AddParamId(Sampled);
|
||||
buf.AddParamId(Format);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end;
|
||||
|
||||
if ie then
|
||||
if (node^.key.count<>0) then
|
||||
begin
|
||||
For i:=0 to node^.key.count-1 do
|
||||
begin
|
||||
buf.AddTypeId(node^.GetCompItem(i));
|
||||
end;
|
||||
end;
|
||||
|
||||
buf.Flush(Stream);
|
||||
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_bin.SaveConst(var buf:TSVInstrBuffer;node:PsrConst);
|
||||
var
|
||||
i:dword;
|
||||
begin
|
||||
|
||||
if (node^.key.count=0) then
|
||||
begin
|
||||
if (node^.key.dtype=dtBool) then
|
||||
begin
|
||||
Case node^.AsBool of
|
||||
True :buf.NewOp(Op.OpConstantTrue);
|
||||
False:buf.NewOp(Op.OpConstantFalse);
|
||||
end;
|
||||
|
||||
buf.AddTypeId(node^.pType);
|
||||
buf.AddConstId(node);
|
||||
end else
|
||||
begin
|
||||
buf.NewOp(Op.OpConstant);
|
||||
buf.AddTypeId(node^.pType);
|
||||
buf.AddConstId(node);
|
||||
|
||||
Case BitSizeType(node^.key.dtype) of
|
||||
8:buf.AddParamId(node^.AsByte);
|
||||
16:buf.AddParamId(node^.AsWord);
|
||||
32:buf.AddParamId(node^.AsUint);
|
||||
64:begin
|
||||
buf.AddParamId(Lo(node^.AsUint64));
|
||||
buf.AddParamId(Hi(node^.AsUint64));
|
||||
end;
|
||||
else
|
||||
Assert(false,'SaveConst');
|
||||
end;
|
||||
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
buf.NewOp(Op.OpConstantComposite);
|
||||
buf.AddTypeId(node^.pType);
|
||||
buf.AddConstId(node);
|
||||
|
||||
For i:=0 to node^.key.count-1 do
|
||||
begin
|
||||
buf.AddConstId(node^.GetCompItem(i));
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_bin.SaveConst(Stream:TStream);
|
||||
var
|
||||
buf:TSVInstrBuffer;
|
||||
node:PsrConst;
|
||||
begin
|
||||
buf:=Default(TSVInstrBuffer);
|
||||
node:=FConsts.FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.key.dtype<>dtUnknow) then
|
||||
begin
|
||||
SaveConst(buf,node);
|
||||
buf.Flush(Stream);
|
||||
end;
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_bin.SaveVariable(Stream:TStream);
|
||||
var
|
||||
buf:TSVInstrBuffer;
|
||||
node:PsrVariable;
|
||||
begin
|
||||
buf:=Default(TSVInstrBuffer);
|
||||
node:=FVariables.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.pType<>nil) then
|
||||
begin
|
||||
buf.NewOp(Op.OpVariable);
|
||||
buf.AddTypeId(node^.pType);
|
||||
buf.AddVarId(node);
|
||||
buf.AddParamId(node^.GetStorageClass);
|
||||
buf.Flush(Stream);
|
||||
end;
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure SaveOpSingle(var buf:TSVInstrBuffer;const Param:TOpParamSingle);
|
||||
begin
|
||||
Assert(Param.pData<>nil,'SaveOpSingle$1');
|
||||
Case Param.ntype of
|
||||
ntFunc :buf.AddFuncId(Param.pData);
|
||||
ntRefId:buf.AddRefId(Param.pData);
|
||||
ntType :buf.AddTypeId(Param.pData);
|
||||
ntReg :buf.AddRegId(Param.pData);
|
||||
ntVar :buf.AddVarId(Param.pData);
|
||||
ntChain:buf.AddChainId(Param.pData);
|
||||
ntConst:buf.AddConstId(Param.pData);
|
||||
else
|
||||
Assert(false,'PrintOpSingle$3');
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure SaveOpParamNode(var buf:TSVInstrBuffer;node:POpParamNode);
|
||||
begin
|
||||
Case node^.ntype of
|
||||
ntLiteral:
|
||||
begin
|
||||
buf.AddParamId(node^.Value);
|
||||
end;
|
||||
ntString:
|
||||
begin
|
||||
buf.AddString(@node^.name);
|
||||
end;
|
||||
else
|
||||
begin
|
||||
SaveOpSingle(buf,node^.AsParam);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_bin.SaveFunc(Stream:TStream);
|
||||
var
|
||||
pFunc:PSpirvFunc;
|
||||
begin
|
||||
pFunc:=FSpirvFuncs.FList.pHead;
|
||||
While (pFunc<>nil) do
|
||||
begin
|
||||
SaveOpBlock(Stream,@pFunc^.FTop);
|
||||
pFunc:=pFunc^.pNext;
|
||||
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
|
||||
Assert(node^.dst_type<>nil,'SaveOp$4');
|
||||
buf.AddTypeId(node^.dst_type);
|
||||
end;
|
||||
|
||||
if Info.result then //dst
|
||||
begin
|
||||
Assert(node^.dst.ntype<>ntUnknow,'SaveOp$1');
|
||||
Assert(node^.dst.pData<>nil,'SaveOp$2');
|
||||
SaveOpSingle(buf,node^.dst);
|
||||
end else
|
||||
begin //no dst
|
||||
if (node^.dst.ntype<>ntUnknow) then
|
||||
begin
|
||||
Assert(node^.dst.pData<>nil,'SaveOp$3');
|
||||
SaveOpSingle(buf,node^.dst);
|
||||
end;
|
||||
end;
|
||||
|
||||
Param:=node^.pParam.pHead;
|
||||
While (Param<>nil) do
|
||||
begin
|
||||
SaveOpParamNode(buf,Param);
|
||||
Param:=Param^.pNext;
|
||||
end;
|
||||
|
||||
buf.Flush(Stream);
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_bin.SaveOpBlock(Stream:TStream;pBlock:PsrOpBlock);
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
if (pBlock=nil) then Exit;
|
||||
node:=pBlock^.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
|
||||
if (node^.OpId=OpBlock) then
|
||||
begin
|
||||
if (node^.dst.ntype=ntBlock) then
|
||||
begin
|
||||
SaveOpBlock(Stream,node^.dst.pData);
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
SaveOp(Stream,node);
|
||||
end;
|
||||
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
||||
|
168
spirv/emit_exp.pas
Normal file
168
spirv/emit_exp.pas
Normal file
@ -0,0 +1,168 @@
|
||||
unit emit_EXP;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srNodes,
|
||||
srLabel,
|
||||
srTypes,
|
||||
srReg,
|
||||
srVariable,
|
||||
srOutput,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_EXP=object(TEmitOp)
|
||||
procedure _emit_EXP;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_EXP._emit_EXP;
|
||||
Var
|
||||
exc:PsrRegNode;
|
||||
node:PSpirvOp;
|
||||
pOpBlock:PsrOpBlock;
|
||||
|
||||
dout:PsrVariable;
|
||||
dst:PsrRegNode;
|
||||
src:array[0..3] of PsrRegNode;
|
||||
rtype:TsrDataType;
|
||||
f,i,p:Byte;
|
||||
|
||||
begin
|
||||
//if (VM<>0) and (EXEC<>0) = set pixel else (if DONE=1) discard pixel /(PS only)
|
||||
|
||||
pOpBlock:=nil;
|
||||
if (FSPI.EXP.VM<>0) and (FSPI.EXP.DONE<>0) then
|
||||
begin
|
||||
pOpBlock:=AllocBlockOp;
|
||||
pOpBlock^.SetInfo(btOther,FCursor.Adr,FCursor.Adr);
|
||||
PushBlockOp(line,pOpBlock,nil);
|
||||
|
||||
exc:=MakeRead(@FRegsStory.EXEC[0],dtBool);
|
||||
node:=AddSpirvOp(OpMakeExp);
|
||||
node^.AddParam(ntReg,exc); //<-fetch read
|
||||
end;
|
||||
|
||||
//before
|
||||
if (TpsslExportType(FSPI.EXP.TGT)=etNull) //only set kill mask
|
||||
or (FSPI.EXP.EN=0) then //nop
|
||||
begin
|
||||
if (pOpBlock<>nil) then //is pushed
|
||||
begin
|
||||
FMain^.PopBlock;
|
||||
end;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
pOpBlock:=AllocBlockOp; //down
|
||||
pOpBlock^.SetInfo(btOther,FCursor.Adr,FCursor.Adr);
|
||||
PushBlockOp(line,pOpBlock,nil);
|
||||
|
||||
//output
|
||||
|
||||
src[0]:=nil;
|
||||
src[1]:=nil;
|
||||
src[2]:=nil;
|
||||
src[3]:=nil;
|
||||
|
||||
f:=FSPI.EXP.EN;
|
||||
|
||||
if (FSPI.EXP.COMPR=0) then //float32
|
||||
begin
|
||||
|
||||
p:=PopCnt(f);
|
||||
|
||||
if (p=1) then
|
||||
begin
|
||||
Case f of
|
||||
$1:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC0,dtFloat32);
|
||||
$2:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC1,dtFloat32);
|
||||
$4:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC2,dtFloat32);
|
||||
$8:src[0]:=fetch_vsrc8(FSPI.EXP.VSRC3,dtFloat32);
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),dtFloat32); //output in FSPI.EXP.TGT
|
||||
emit_OpStore(line,dout,src[0]);
|
||||
end else
|
||||
begin
|
||||
|
||||
Case p of
|
||||
0:Assert(false);
|
||||
2:rtype:=dtVec2f;
|
||||
3:rtype:=dtVec3f;
|
||||
4:rtype:=dtVec4f;
|
||||
end;
|
||||
|
||||
i:=0;
|
||||
if (f and $1<>0) then
|
||||
begin
|
||||
src[i]:=fetch_vsrc8(FSPI.EXP.VSRC0,dtFloat32);
|
||||
Inc(i);
|
||||
end;
|
||||
if (f and $2<>0) then
|
||||
begin
|
||||
src[i]:=fetch_vsrc8(FSPI.EXP.VSRC1,dtFloat32);
|
||||
Inc(i);
|
||||
end;
|
||||
if (f and $4<>0) then
|
||||
begin
|
||||
src[i]:=fetch_vsrc8(FSPI.EXP.VSRC2,dtFloat32);
|
||||
Inc(i);
|
||||
end;
|
||||
if (f and $8<>0) then
|
||||
begin
|
||||
src[i]:=fetch_vsrc8(FSPI.EXP.VSRC3,dtFloat32);
|
||||
Inc(i);
|
||||
end;
|
||||
|
||||
dst:=emit_OpMakeVec(line,rtype,p,@src);
|
||||
dst^.mark_read;
|
||||
|
||||
dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),rtype); //output in FSPI.EXP.TGT
|
||||
emit_OpStore(line,dout,dst);
|
||||
end;
|
||||
|
||||
end else
|
||||
begin //half16
|
||||
Case f of
|
||||
3,
|
||||
$F:
|
||||
begin
|
||||
fetch_vsrc8_vec2h(FSPI.EXP.VSRC0,src[0],src[1]);
|
||||
fetch_vsrc8_vec2h(FSPI.EXP.VSRC1,src[2],src[3]);
|
||||
end;
|
||||
$C:
|
||||
begin
|
||||
fetch_vsrc8_vec2h(FSPI.EXP.VSRC2,src[0],src[1]);
|
||||
fetch_vsrc8_vec2h(FSPI.EXP.VSRC3,src[2],src[3]);
|
||||
end;
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
dst:=emit_OpMakeVec(line,dtVec4h,4,@src);
|
||||
dst^.mark_read;
|
||||
|
||||
dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),dtVec4h); //output in FSPI.EXP.TGT
|
||||
emit_OpStore(line,dout,dst);
|
||||
end;
|
||||
|
||||
if (pOpBlock<>nil) then //is pushed
|
||||
begin
|
||||
FMain^.PopBlock;
|
||||
FMain^.PopBlock;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
705
spirv/emit_mimg.pas
Normal file
705
spirv/emit_mimg.pas
Normal file
@ -0,0 +1,705 @@
|
||||
unit emit_MIMG;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
si_ci_vi_merged_enum,
|
||||
ps4_shader,
|
||||
ps4_pssl,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
srLayout,
|
||||
srOp,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_MIMG=object(TEmitOp)
|
||||
procedure _emit_MIMG;
|
||||
procedure _DistribDmask(dst:PsrRegNode;telem:TsrDataType);
|
||||
Function _GatherCoord_f(var offset:DWORD;dim_id:Byte):PsrRegNode;
|
||||
Function _GatherCoord_u(var offset:DWORD;dim_id:Byte):PsrRegNode;
|
||||
Function _Gather_packed_offset(var offset:DWORD;dim:Byte):PsrRegNode;
|
||||
procedure _emit_image_sample(Tgrp:PsrRegNode;info:PsrImageInfo);
|
||||
procedure _emit_image_load(Tgrp:PsrRegNode;info:PsrImageInfo);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function GetImageFormat(PT:PTSharpResource4):Byte;
|
||||
begin
|
||||
Result:=ImageFormat.Unknown;
|
||||
if (PT=nil) then Exit;
|
||||
Case PT^.nfmt of
|
||||
IMG_NUM_FORMAT_UNORM,
|
||||
IMG_NUM_FORMAT_SRGB:
|
||||
begin //R8, Rg8,Rg16, Rgba8,Rgba16,Rgb10A2
|
||||
|
||||
Case PT^.dfmt of
|
||||
|
||||
IMG_DATA_FORMAT_8 :Result:=ImageFormat.R8;
|
||||
IMG_DATA_FORMAT_ETC2_R :Result:=ImageFormat.R8;
|
||||
IMG_DATA_FORMAT_BC4 :Result:=ImageFormat.R8;
|
||||
IMG_DATA_FORMAT_1 :Result:=ImageFormat.R8;
|
||||
IMG_DATA_FORMAT_32_AS_8 :Result:=ImageFormat.R8;
|
||||
|
||||
IMG_DATA_FORMAT_8_8 :Result:=ImageFormat.Rg8;
|
||||
IMG_DATA_FORMAT_16_16 :Result:=ImageFormat.Rg16;
|
||||
IMG_DATA_FORMAT_ETC2_RG :Result:=ImageFormat.Rg8;
|
||||
IMG_DATA_FORMAT_BC5 :Result:=ImageFormat.Rg8;
|
||||
IMG_DATA_FORMAT_4_4 :Result:=ImageFormat.Rg8;
|
||||
IMG_DATA_FORMAT_32_AS_8_8 :Result:=ImageFormat.Rg8;
|
||||
|
||||
IMG_DATA_FORMAT_10_11_11 :Result:=ImageFormat.Rgb10A2;
|
||||
IMG_DATA_FORMAT_11_11_10 :Result:=ImageFormat.Rgb10A2;
|
||||
IMG_DATA_FORMAT_5_6_5 :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_ETC2_RGB :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_GB_GR :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_BG_RG :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_BC1 :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_BC6 :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_6_5_5 :Result:=ImageFormat.Rgba8;
|
||||
|
||||
IMG_DATA_FORMAT_10_10_10_2 :Result:=ImageFormat.Rgb10A2;
|
||||
IMG_DATA_FORMAT_2_10_10_10 :Result:=ImageFormat.Rgb10A2;
|
||||
IMG_DATA_FORMAT_8_8_8_8 :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_1_5_5_5 :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_5_5_5_1 :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_4_4_4_4 :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_ETC2_RGBA :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_ETC2_RGBA1 :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_5_9_9_9 :Result:=ImageFormat.Rgba16;
|
||||
IMG_DATA_FORMAT_BC2 :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_BC3 :Result:=ImageFormat.Rgba8;
|
||||
IMG_DATA_FORMAT_BC7 :Result:=ImageFormat.Rgba8;
|
||||
|
||||
else;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
IMG_NUM_FORMAT_SNORM:
|
||||
begin //R8Snorm, Rg8Snorm,Rg16Snorm, Rgba8Snorm,Rgba16Snorm
|
||||
|
||||
Case PT^.dfmt of
|
||||
|
||||
IMG_DATA_FORMAT_8 :Result:=ImageFormat.R8Snorm;
|
||||
IMG_DATA_FORMAT_ETC2_R :Result:=ImageFormat.R8Snorm;
|
||||
IMG_DATA_FORMAT_BC4 :Result:=ImageFormat.R8Snorm;
|
||||
IMG_DATA_FORMAT_1 :Result:=ImageFormat.R8Snorm;
|
||||
IMG_DATA_FORMAT_32_AS_8 :Result:=ImageFormat.R8Snorm;
|
||||
|
||||
IMG_DATA_FORMAT_8_8 :Result:=ImageFormat.Rg8Snorm;
|
||||
IMG_DATA_FORMAT_16_16 :Result:=ImageFormat.Rg16Snorm;
|
||||
IMG_DATA_FORMAT_ETC2_RG :Result:=ImageFormat.Rg8Snorm;
|
||||
IMG_DATA_FORMAT_BC5 :Result:=ImageFormat.Rg8Snorm;
|
||||
IMG_DATA_FORMAT_4_4 :Result:=ImageFormat.Rg8Snorm;
|
||||
IMG_DATA_FORMAT_32_AS_8_8 :Result:=ImageFormat.Rg8Snorm;
|
||||
|
||||
IMG_DATA_FORMAT_10_11_11 :Result:=ImageFormat.Rgba16Snorm;
|
||||
IMG_DATA_FORMAT_11_11_10 :Result:=ImageFormat.Rgba16Snorm;
|
||||
IMG_DATA_FORMAT_5_6_5 :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_ETC2_RGB :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_GB_GR :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_BG_RG :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_BC1 :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_BC6 :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_6_5_5 :Result:=ImageFormat.Rgba8Snorm;
|
||||
|
||||
IMG_DATA_FORMAT_10_10_10_2 :Result:=ImageFormat.Rgba16Snorm;
|
||||
IMG_DATA_FORMAT_2_10_10_10 :Result:=ImageFormat.Rgba16Snorm;
|
||||
IMG_DATA_FORMAT_8_8_8_8 :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_1_5_5_5 :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_5_5_5_1 :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_4_4_4_4 :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_ETC2_RGBA :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_ETC2_RGBA1 :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_5_9_9_9 :Result:=ImageFormat.Rgba16Snorm;
|
||||
IMG_DATA_FORMAT_BC2 :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_BC3 :Result:=ImageFormat.Rgba8Snorm;
|
||||
IMG_DATA_FORMAT_BC7 :Result:=ImageFormat.Rgba8Snorm;
|
||||
|
||||
else;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
IMG_NUM_FORMAT_UINT:
|
||||
begin //R8ui,R16ui,R32ui, Rg8ui,Rg16ui,Rg32ui, Rgba8ui,Rgba16ui,Rgba32ui,Rgb10a2ui
|
||||
|
||||
Case PT^.dfmt of
|
||||
|
||||
IMG_DATA_FORMAT_8 :Result:=ImageFormat.R8ui;
|
||||
IMG_DATA_FORMAT_16 :Result:=ImageFormat.R16ui;
|
||||
IMG_DATA_FORMAT_32 :Result:=ImageFormat.R32ui;
|
||||
IMG_DATA_FORMAT_ETC2_R :Result:=ImageFormat.R8ui;
|
||||
IMG_DATA_FORMAT_BC4 :Result:=ImageFormat.R8ui;
|
||||
IMG_DATA_FORMAT_1 :Result:=ImageFormat.R8ui;
|
||||
IMG_DATA_FORMAT_32_AS_8 :Result:=ImageFormat.R8ui;
|
||||
|
||||
IMG_DATA_FORMAT_8_8 :Result:=ImageFormat.Rg8ui;
|
||||
IMG_DATA_FORMAT_16_16 :Result:=ImageFormat.Rg16ui;
|
||||
IMG_DATA_FORMAT_32_32 :Result:=ImageFormat.Rg32ui;
|
||||
IMG_DATA_FORMAT_8_24 :Result:=ImageFormat.Rg32ui;
|
||||
IMG_DATA_FORMAT_24_8 :Result:=ImageFormat.Rg32ui;
|
||||
IMG_DATA_FORMAT_X24_8_32 :Result:=ImageFormat.Rg32ui;
|
||||
IMG_DATA_FORMAT_ETC2_RG :Result:=ImageFormat.Rg8ui;
|
||||
IMG_DATA_FORMAT_BC5 :Result:=ImageFormat.Rg8ui;
|
||||
IMG_DATA_FORMAT_4_4 :Result:=ImageFormat.Rg8ui;
|
||||
IMG_DATA_FORMAT_32_AS_8_8 :Result:=ImageFormat.Rg8ui;
|
||||
|
||||
IMG_DATA_FORMAT_10_11_11 :Result:=ImageFormat.Rgb10a2ui;
|
||||
IMG_DATA_FORMAT_11_11_10 :Result:=ImageFormat.Rgb10a2ui;
|
||||
IMG_DATA_FORMAT_32_32_32 :Result:=ImageFormat.Rgba32ui;
|
||||
IMG_DATA_FORMAT_5_6_5 :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_ETC2_RGB :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_GB_GR :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_BG_RG :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_BC1 :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_BC6 :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_6_5_5 :Result:=ImageFormat.Rgba8ui;
|
||||
|
||||
IMG_DATA_FORMAT_10_10_10_2 :Result:=ImageFormat.Rgb10a2ui;
|
||||
IMG_DATA_FORMAT_2_10_10_10 :Result:=ImageFormat.Rgb10a2ui;
|
||||
IMG_DATA_FORMAT_8_8_8_8 :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_16_16_16_16 :Result:=ImageFormat.Rgba16ui;
|
||||
IMG_DATA_FORMAT_32_32_32_32 :Result:=ImageFormat.Rgba32ui;
|
||||
IMG_DATA_FORMAT_1_5_5_5 :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_5_5_5_1 :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_4_4_4_4 :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_ETC2_RGBA :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_ETC2_RGBA1 :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_5_9_9_9 :Result:=ImageFormat.Rgba16ui;
|
||||
IMG_DATA_FORMAT_BC2 :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_BC3 :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_BC7 :Result:=ImageFormat.Rgba8ui;
|
||||
IMG_DATA_FORMAT_32_AS_32_32_32_32:Result:=ImageFormat.Rgba32ui;
|
||||
|
||||
IMG_DATA_FORMAT_FMASK8_S2_F1 :Result:=ImageFormat.R8ui;
|
||||
IMG_DATA_FORMAT_FMASK8_S4_F1 :Result:=ImageFormat.R8ui;
|
||||
IMG_DATA_FORMAT_FMASK8_S8_F1 :Result:=ImageFormat.R8ui;
|
||||
IMG_DATA_FORMAT_FMASK8_S2_F2 :Result:=ImageFormat.R8ui;
|
||||
IMG_DATA_FORMAT_FMASK8_S4_F2 :Result:=ImageFormat.R8ui;
|
||||
IMG_DATA_FORMAT_FMASK8_S4_F4 :Result:=ImageFormat.R8ui;
|
||||
|
||||
IMG_DATA_FORMAT_FMASK16_S16_F1 :Result:=ImageFormat.R16ui;
|
||||
IMG_DATA_FORMAT_FMASK16_S8_F2 :Result:=ImageFormat.R16ui;
|
||||
|
||||
IMG_DATA_FORMAT_FMASK32_S16_F2 :Result:=ImageFormat.R32ui;
|
||||
IMG_DATA_FORMAT_FMASK32_S8_F4 :Result:=ImageFormat.R32ui;
|
||||
IMG_DATA_FORMAT_FMASK32_S8_F8 :Result:=ImageFormat.R32ui;
|
||||
|
||||
IMG_DATA_FORMAT_FMASK64_S16_F4 :Result:=ImageFormat.R64ui;
|
||||
IMG_DATA_FORMAT_FMASK64_S16_F8 :Result:=ImageFormat.R64ui;
|
||||
|
||||
else;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
IMG_NUM_FORMAT_SINT:
|
||||
begin //R8i,R16i,R32i, Rg8i,Rg16i,Rg32i, Rgba8i,Rgba16i,Rgba32i
|
||||
|
||||
Case PT^.dfmt of
|
||||
|
||||
IMG_DATA_FORMAT_8 :Result:=ImageFormat.R8i;
|
||||
IMG_DATA_FORMAT_16 :Result:=ImageFormat.R16i;
|
||||
IMG_DATA_FORMAT_32 :Result:=ImageFormat.R32i;
|
||||
IMG_DATA_FORMAT_ETC2_R :Result:=ImageFormat.R8i;
|
||||
IMG_DATA_FORMAT_BC4 :Result:=ImageFormat.R8i;
|
||||
IMG_DATA_FORMAT_1 :Result:=ImageFormat.R8i;
|
||||
IMG_DATA_FORMAT_32_AS_8 :Result:=ImageFormat.R8i;
|
||||
|
||||
IMG_DATA_FORMAT_8_8 :Result:=ImageFormat.Rg8i;
|
||||
IMG_DATA_FORMAT_16_16 :Result:=ImageFormat.Rg16i;
|
||||
IMG_DATA_FORMAT_32_32 :Result:=ImageFormat.Rg32i;
|
||||
IMG_DATA_FORMAT_8_24 :Result:=ImageFormat.Rg32i;
|
||||
IMG_DATA_FORMAT_24_8 :Result:=ImageFormat.Rg32i;
|
||||
IMG_DATA_FORMAT_X24_8_32 :Result:=ImageFormat.Rg32i;
|
||||
IMG_DATA_FORMAT_ETC2_RG :Result:=ImageFormat.Rg8i;
|
||||
IMG_DATA_FORMAT_BC5 :Result:=ImageFormat.Rg8i;
|
||||
IMG_DATA_FORMAT_4_4 :Result:=ImageFormat.Rg8i;
|
||||
IMG_DATA_FORMAT_32_AS_8_8 :Result:=ImageFormat.Rg8i;
|
||||
|
||||
IMG_DATA_FORMAT_10_11_11 :Result:=ImageFormat.Rgba16i;
|
||||
IMG_DATA_FORMAT_11_11_10 :Result:=ImageFormat.Rgba16i;
|
||||
IMG_DATA_FORMAT_32_32_32 :Result:=ImageFormat.Rgba32i;
|
||||
IMG_DATA_FORMAT_5_6_5 :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_ETC2_RGB :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_GB_GR :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_BG_RG :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_BC1 :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_BC6 :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_6_5_5 :Result:=ImageFormat.Rgba8i;
|
||||
|
||||
IMG_DATA_FORMAT_10_10_10_2 :Result:=ImageFormat.Rgba16i;
|
||||
IMG_DATA_FORMAT_2_10_10_10 :Result:=ImageFormat.Rgba16i;
|
||||
IMG_DATA_FORMAT_8_8_8_8 :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_16_16_16_16 :Result:=ImageFormat.Rgba16i;
|
||||
IMG_DATA_FORMAT_32_32_32_32 :Result:=ImageFormat.Rgba32i;
|
||||
IMG_DATA_FORMAT_1_5_5_5 :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_5_5_5_1 :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_4_4_4_4 :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_ETC2_RGBA :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_ETC2_RGBA1 :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_5_9_9_9 :Result:=ImageFormat.Rgba16i;
|
||||
IMG_DATA_FORMAT_BC2 :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_BC3 :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_BC7 :Result:=ImageFormat.Rgba8i;
|
||||
IMG_DATA_FORMAT_32_AS_32_32_32_32:Result:=ImageFormat.Rgba32i;
|
||||
|
||||
IMG_DATA_FORMAT_FMASK8_S2_F1 :Result:=ImageFormat.R8i;
|
||||
IMG_DATA_FORMAT_FMASK8_S4_F1 :Result:=ImageFormat.R8i;
|
||||
IMG_DATA_FORMAT_FMASK8_S8_F1 :Result:=ImageFormat.R8i;
|
||||
IMG_DATA_FORMAT_FMASK8_S2_F2 :Result:=ImageFormat.R8i;
|
||||
IMG_DATA_FORMAT_FMASK8_S4_F2 :Result:=ImageFormat.R8i;
|
||||
IMG_DATA_FORMAT_FMASK8_S4_F4 :Result:=ImageFormat.R8i;
|
||||
|
||||
IMG_DATA_FORMAT_FMASK16_S16_F1 :Result:=ImageFormat.R16i;
|
||||
IMG_DATA_FORMAT_FMASK16_S8_F2 :Result:=ImageFormat.R16i;
|
||||
|
||||
IMG_DATA_FORMAT_FMASK32_S16_F2 :Result:=ImageFormat.R32i;
|
||||
IMG_DATA_FORMAT_FMASK32_S8_F4 :Result:=ImageFormat.R32i;
|
||||
IMG_DATA_FORMAT_FMASK32_S8_F8 :Result:=ImageFormat.R32i;
|
||||
|
||||
IMG_DATA_FORMAT_FMASK64_S16_F4 :Result:=ImageFormat.R64i;
|
||||
IMG_DATA_FORMAT_FMASK64_S16_F8 :Result:=ImageFormat.R64i;
|
||||
|
||||
else;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
IMG_NUM_FORMAT_USCALED,
|
||||
IMG_NUM_FORMAT_SSCALED,
|
||||
IMG_NUM_FORMAT_FLOAT:
|
||||
begin //R16f,R32f, Rg16f,Rg32f, R11fG11fB10f, Rgba16f,Rgba32f
|
||||
|
||||
Case PT^.dfmt of
|
||||
|
||||
IMG_DATA_FORMAT_16 :Result:=ImageFormat.R16f;
|
||||
IMG_DATA_FORMAT_32 :Result:=ImageFormat.R32f;
|
||||
IMG_DATA_FORMAT_ETC2_R :Result:=ImageFormat.R16f;
|
||||
IMG_DATA_FORMAT_BC4 :Result:=ImageFormat.R16f;
|
||||
|
||||
IMG_DATA_FORMAT_16_16 :Result:=ImageFormat.Rg16f;
|
||||
IMG_DATA_FORMAT_32_32 :Result:=ImageFormat.Rg32f;
|
||||
IMG_DATA_FORMAT_8_24 :Result:=ImageFormat.Rg32f;
|
||||
IMG_DATA_FORMAT_24_8 :Result:=ImageFormat.Rg32f;
|
||||
IMG_DATA_FORMAT_X24_8_32 :Result:=ImageFormat.Rg32f;
|
||||
IMG_DATA_FORMAT_ETC2_RG :Result:=ImageFormat.Rg16f;
|
||||
IMG_DATA_FORMAT_BC5 :Result:=ImageFormat.Rg16f;
|
||||
|
||||
IMG_DATA_FORMAT_10_11_11 :Result:=ImageFormat.R11fG11fB10f;
|
||||
IMG_DATA_FORMAT_11_11_10 :Result:=ImageFormat.R11fG11fB10f;
|
||||
IMG_DATA_FORMAT_32_32_32 :Result:=ImageFormat.Rgba32f;
|
||||
IMG_DATA_FORMAT_ETC2_RGB :Result:=ImageFormat.Rgba16f;
|
||||
IMG_DATA_FORMAT_BC1 :Result:=ImageFormat.Rgba16f;
|
||||
IMG_DATA_FORMAT_BC6 :Result:=ImageFormat.Rgba16f;
|
||||
|
||||
IMG_DATA_FORMAT_10_10_10_2 :Result:=ImageFormat.Rgba16f;
|
||||
IMG_DATA_FORMAT_2_10_10_10 :Result:=ImageFormat.Rgba16f;
|
||||
IMG_DATA_FORMAT_16_16_16_16 :Result:=ImageFormat.Rgba16f;
|
||||
IMG_DATA_FORMAT_32_32_32_32 :Result:=ImageFormat.Rgba32f;
|
||||
IMG_DATA_FORMAT_ETC2_RGBA :Result:=ImageFormat.Rgba16f;
|
||||
IMG_DATA_FORMAT_ETC2_RGBA1 :Result:=ImageFormat.Rgba16f;
|
||||
IMG_DATA_FORMAT_BC2 :Result:=ImageFormat.Rgba16f;
|
||||
IMG_DATA_FORMAT_BC3 :Result:=ImageFormat.Rgba16f;
|
||||
IMG_DATA_FORMAT_BC7 :Result:=ImageFormat.Rgba16f;
|
||||
IMG_DATA_FORMAT_32_AS_32_32_32_32:Result:=ImageFormat.Rgba32f;
|
||||
|
||||
else;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetDimType(PT:PTSharpResource4):Byte;
|
||||
begin
|
||||
Result:=0;
|
||||
if (PT=nil) then Exit;
|
||||
Case PT^._type of
|
||||
SQ_RSRC_IMG_1D,
|
||||
SQ_RSRC_IMG_1D_ARRAY :Result:=Dim.Dim1D;
|
||||
SQ_RSRC_IMG_2D,
|
||||
SQ_RSRC_IMG_2D_ARRAY,
|
||||
SQ_RSRC_IMG_2D_MSAA,
|
||||
SQ_RSRC_IMG_2D_MSAA_ARRAY:Result:=Dim.Dim2D;
|
||||
SQ_RSRC_IMG_3D :Result:=Dim.Dim3D;
|
||||
SQ_RSRC_IMG_CUBE :Result:=Dim.Cube;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetElemType(PT:PTSharpResource4):TsrDataType;
|
||||
begin
|
||||
Result:=dtFloat32;
|
||||
if (PT=nil) then Exit;
|
||||
Case PT^.nfmt of
|
||||
IMG_NUM_FORMAT_UINT:Result:=dtUint32;
|
||||
IMG_NUM_FORMAT_SINT:Result:=dtInt32;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetDimCount(b:Byte):Byte;
|
||||
begin
|
||||
Result:=1;
|
||||
Case b of
|
||||
Dim.Dim2D:Result:=2;
|
||||
Dim.Dim3D:Result:=3;
|
||||
Dim.Cube :Result:=3;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetImageInfo(PT:PTSharpResource4):TsrImageInfo;
|
||||
begin
|
||||
Result:=Default(TsrImageInfo);
|
||||
Result.dtype:=GetElemType(PT);
|
||||
|
||||
Result.tinfo.Dim :=GetDimType(PT);
|
||||
Result.tinfo.Depth :=2;
|
||||
Result.tinfo.Arrayed:=GetArrayedType(PT);
|
||||
Result.tinfo.MS :=GetMsType(PT);
|
||||
Result.tinfo.Format :=GetImageFormat(PT);
|
||||
end;
|
||||
|
||||
procedure TEmit_MIMG._DistribDmask(dst:PsrRegNode;telem:TsrDataType); //result
|
||||
var
|
||||
pSlot:PsrRegSlot;
|
||||
i,d:Byte;
|
||||
begin
|
||||
d:=0;
|
||||
For i:=0 to 3 do
|
||||
if Byte(FSPI.MIMG.DMASK).TestBit(i) then
|
||||
begin
|
||||
pSlot:=FRegsStory.get_vdst8(FSPI.MIMG.VDATA+d); Inc(d);
|
||||
Assert(pSlot<>nil);
|
||||
dst^.mark_read;
|
||||
emit_OpCompExtract(line,pSlot^.New(line,telem),dst,i);
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TEmit_MIMG._GatherCoord_f(var offset:DWORD;dim_id:Byte):PsrRegNode; //src
|
||||
var
|
||||
src:array[0..3] of PsrRegNode;
|
||||
i,count:Byte;
|
||||
begin
|
||||
Result:=nil;
|
||||
|
||||
count:=GetDimCount(dim_id);
|
||||
if (FSPI.MIMG.DA<>0) then Inc(count); //slice
|
||||
|
||||
if (dim_id=Dim.Cube) then
|
||||
begin
|
||||
//x,y,slice,(face_id+slice*8)
|
||||
|
||||
if (FSPI.MIMG.DA<>0) then //slice
|
||||
begin
|
||||
src[0]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+0,dtFloat32); //x
|
||||
src[1]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+1,dtFloat32); //y
|
||||
src[2]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+3,dtFloat32); //face TODO: face-slice*8
|
||||
src[3]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+2,dtFloat32); //slice
|
||||
end else
|
||||
begin
|
||||
src[0]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+0,dtFloat32); //x
|
||||
src[1]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+1,dtFloat32); //y
|
||||
src[2]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+2,dtFloat32); //face
|
||||
end;
|
||||
|
||||
Result:=emit_OpMakeCube(line,GetVecType(dtFloat32,count),count,@src);
|
||||
Result^.mark_read;
|
||||
|
||||
end else
|
||||
begin
|
||||
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
src[i]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+i,dtFloat32);
|
||||
end;
|
||||
|
||||
if (count=1) then
|
||||
begin
|
||||
Result:=src[0];
|
||||
end else
|
||||
begin
|
||||
Result:=emit_OpMakeVec(line,GetVecType(dtFloat32,count),count,@src);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
offset:=offset+count;
|
||||
end;
|
||||
|
||||
Function TEmit_MIMG._GatherCoord_u(var offset:DWORD;dim_id:Byte):PsrRegNode; //src
|
||||
var
|
||||
src:array[0..3] of PsrRegNode;
|
||||
i,count:Byte;
|
||||
begin
|
||||
Result:=nil;
|
||||
|
||||
count:=GetDimCount(dim_id);
|
||||
if (FSPI.MIMG.DA<>0) then Inc(count); //slice
|
||||
|
||||
if (dim_id=Dim.Cube) then
|
||||
begin
|
||||
//x,y,slice,(face_id+slice*8)
|
||||
|
||||
if (FSPI.MIMG.DA<>0) then //slice
|
||||
begin
|
||||
src[0]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+0,dtInt32); //x
|
||||
src[1]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+1,dtInt32); //y
|
||||
src[2]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+3,dtInt32); //face TODO: face-slice*8
|
||||
src[3]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+2,dtInt32); //slice
|
||||
end else
|
||||
begin
|
||||
src[0]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+0,dtInt32); //x
|
||||
src[1]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+1,dtInt32); //y
|
||||
src[2]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+2,dtInt32); //face
|
||||
end;
|
||||
|
||||
Result:=emit_OpMakeCube(line,GetVecType(dtInt32,count),count,@src);
|
||||
Result^.mark_read;
|
||||
|
||||
end else
|
||||
begin
|
||||
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
src[i]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+i,dtInt32);
|
||||
end;
|
||||
|
||||
if (count=1) then
|
||||
begin
|
||||
Result:=src[0];
|
||||
end else
|
||||
begin
|
||||
Result:=emit_OpMakeVec(line,GetVecType(dtInt32,count),count,@src);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
offset:=offset+count;
|
||||
end;
|
||||
|
||||
Function TEmit_MIMG._Gather_packed_offset(var offset:DWORD;dim:Byte):PsrRegNode;
|
||||
var
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
|
||||
src:=fetch_vsrc8(FSPI.MIMG.VADDR+offset,dtUint32);
|
||||
Inc(offset);
|
||||
|
||||
Case dim of
|
||||
1:Result:=emit_OpPackOfs(line,dtInt32,dim,src);
|
||||
2:Result:=emit_OpPackOfs(line,dtVec2i,dim,src);
|
||||
3:Result:=emit_OpPackOfs(line,dtVec3i,dim,src);
|
||||
else
|
||||
Assert(False);
|
||||
end;
|
||||
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
procedure TEmit_MIMG._emit_image_sample(Tgrp:PsrRegNode;info:PsrImageInfo);
|
||||
var
|
||||
src:array[0..3] of PsrRegSlot;
|
||||
|
||||
pLayout:PsrDataLayout;
|
||||
Sgrp:PsrRegNode;
|
||||
|
||||
dst,cmb,coord,lod,offset:PsrRegNode;
|
||||
|
||||
roffset:DWORD;
|
||||
|
||||
node:PSpirvOp;
|
||||
|
||||
begin
|
||||
if not FRegsStory.get_srsrc(FSPI.MIMG.SSAMP,4,@src) then Assert(false);
|
||||
|
||||
pLayout:=GroupingSharp(src,rtSSharp4);
|
||||
Sgrp:=FetchSampler(pLayout);
|
||||
|
||||
cmb:=emit_OpSampledImage(line,Tgrp,Sgrp,info^.dtype,info^.tinfo);
|
||||
cmb^.mark_read;
|
||||
|
||||
dst:=NewReg(GetVecType(info^.dtype,4));
|
||||
|
||||
roffset:=0;
|
||||
|
||||
Case FSPI.MIMG.OP of
|
||||
IMAGE_SAMPLE:
|
||||
begin
|
||||
coord:=_GatherCoord_f(roffset,info^.tinfo.Dim);
|
||||
|
||||
if (FExecutionModel=ExecutionModel.Fragment) then
|
||||
begin
|
||||
node:=emit_OpImageSampleImplicitLod(line,dst,cmb,coord);
|
||||
end else
|
||||
begin
|
||||
node:=emit_OpImageSampleExplicitLod(line,dst,cmb,coord);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
IMAGE_SAMPLE_LZ:
|
||||
begin
|
||||
coord:=_GatherCoord_f(roffset,info^.tinfo.Dim);
|
||||
|
||||
node:=emit_OpImageSampleExplicitLod(line,dst,cmb,coord);
|
||||
|
||||
node^.AddLiteral(ImageOperands.Lod,'Lod');
|
||||
|
||||
//0
|
||||
lod:=FetchReg(FConsts.Fetchf(dtFloat32,0));
|
||||
node^.AddParam(ntReg,lod);
|
||||
end;
|
||||
|
||||
IMAGE_SAMPLE_LZ_O:
|
||||
begin
|
||||
offset:=_Gather_packed_offset(roffset,GetDimCount(info^.tinfo.Dim));
|
||||
|
||||
coord:=_GatherCoord_f(roffset,info^.tinfo.Dim);
|
||||
|
||||
node:=emit_OpImageSampleExplicitLod(line,dst,cmb,coord);
|
||||
|
||||
node^.AddLiteral(ImageOperands.Lod or ImageOperands.ConstOffset,'Lod|ConstOffset');
|
||||
|
||||
//0
|
||||
lod:=FetchReg(FConsts.Fetchf(dtFloat32,0));
|
||||
node^.AddParam(ntReg,lod);
|
||||
|
||||
//1
|
||||
node^.AddParam(ntReg,offset);
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
_DistribDmask(dst,info^.dtype);
|
||||
end;
|
||||
|
||||
procedure TEmit_MIMG._emit_image_load(Tgrp:PsrRegNode;info:PsrImageInfo);
|
||||
var
|
||||
dst,coord,lod:PsrRegNode;
|
||||
|
||||
roffset:DWORD;
|
||||
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
|
||||
dst:=NewReg(GetVecType(info^.dtype,4));
|
||||
|
||||
roffset:=0;
|
||||
|
||||
Case FSPI.MIMG.OP of
|
||||
IMAGE_LOAD:
|
||||
begin
|
||||
coord:=_GatherCoord_u(roffset,info^.tinfo.Dim);
|
||||
node:=emit_OpImageFetch(line,Tgrp,dst,coord);
|
||||
|
||||
//fragid T# 2D MSAA
|
||||
if (info^.tinfo.MS=1) then
|
||||
begin
|
||||
Assert(false,'TODO');
|
||||
end;
|
||||
|
||||
end;
|
||||
IMAGE_LOAD_MIP: //All except MSAA
|
||||
begin
|
||||
coord:=_GatherCoord_u(roffset,info^.tinfo.Dim);
|
||||
node:=emit_OpImageFetch(line,Tgrp,dst,coord);
|
||||
|
||||
lod:=fetch_vsrc8(FSPI.MIMG.VADDR+roffset,dtUint32);
|
||||
Inc(roffset);
|
||||
node^.AddLiteral(ImageOperands.Lod,'Lod');
|
||||
node^.AddParam(ntReg,lod);
|
||||
end;
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
_DistribDmask(dst,info^.dtype);
|
||||
end;
|
||||
|
||||
procedure TEmit_MIMG._emit_MIMG;
|
||||
var
|
||||
src:array[0..7] of PsrRegSlot;
|
||||
|
||||
pLayout:PsrDataLayout;
|
||||
info:TsrImageInfo;
|
||||
|
||||
Tgrp:PsrRegNode;
|
||||
|
||||
begin
|
||||
|
||||
Assert(FSPI.MIMG.UNRM=0,'FSPI.MIMG.UNRM');
|
||||
|
||||
pLayout:=nil;
|
||||
|
||||
Case FSPI.MIMG.R128 of
|
||||
0:
|
||||
begin
|
||||
if not FRegsStory.get_srsrc(FSPI.MIMG.SRSRC,8,@src) then Assert(false);
|
||||
pLayout:=GroupingSharp(src,rtTSharp4);
|
||||
//print_tsharp4(pLayout^.pData);
|
||||
//Tgrp:=GroupingSharp(@src,rtTSharp8);
|
||||
end;
|
||||
1:
|
||||
begin
|
||||
if not FRegsStory.get_srsrc(FSPI.MIMG.SRSRC,4,@src) then Assert(false);
|
||||
pLayout:=GroupingSharp(src,rtTSharp8);
|
||||
//print_tsharp8(pLayout^.pData);
|
||||
//Tgrp:=GroupingSharp(@src,rtTSharp4);
|
||||
end;
|
||||
end;
|
||||
|
||||
info:=GetImageInfo(pLayout^.pData);
|
||||
|
||||
Case FSPI.MIMG.OP of
|
||||
IMAGE_SAMPLE..IMAGE_SAMPLE_C_LZ_O: //sampled
|
||||
begin
|
||||
info.tinfo.Sampled:=1;
|
||||
Tgrp:=FetchImage(pLayout,info.dtype,info.tinfo);
|
||||
|
||||
_emit_image_sample(Tgrp,@info);
|
||||
end;
|
||||
|
||||
IMAGE_LOAD..IMAGE_LOAD_MIP_PCK_SGN: //loaded
|
||||
begin
|
||||
info.tinfo.Sampled:=1;
|
||||
Tgrp:=FetchImage(pLayout,info.dtype,info.tinfo);
|
||||
|
||||
_emit_image_load(Tgrp,@info);
|
||||
end
|
||||
|
||||
else
|
||||
Assert(false,'MIMG?'+IntToStr(FSPI.MIMG.OP));
|
||||
end;
|
||||
|
||||
//Writeln('DMASK=',FSPI.MIMG.DMASK);
|
||||
//Writeln('VADDR=',FSPI.MIMG.VADDR);
|
||||
//Writeln('VDATA=',FSPI.MIMG.VDATA);
|
||||
//Writeln('SRSRC=',FSPI.MIMG.SRSRC); //T#
|
||||
//Writeln('SSAMP=',FSPI.MIMG.SSAMP); //S#
|
||||
//writeln;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
||||
|
||||
|
99
spirv/emit_mtbuf.pas
Normal file
99
spirv/emit_mtbuf.pas
Normal file
@ -0,0 +1,99 @@
|
||||
unit emit_MTBUF;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srReg,
|
||||
srLayout,
|
||||
SprvEmit,
|
||||
srVBufInfo,
|
||||
emit_vbuf_load,
|
||||
emit_vbuf_store,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_MTBUF=object(TEmitOp)
|
||||
procedure _emit_MTBUF;
|
||||
procedure _emit_TBUFFER_LOAD_FORMAT(count:Byte);
|
||||
procedure _emit_TBUFFER_STORE_FORMAT(count:Byte);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_MTBUF._emit_TBUFFER_LOAD_FORMAT(count:Byte);
|
||||
var
|
||||
src:array[0..3] of PsrRegSlot;
|
||||
|
||||
grp:PsrDataLayout;
|
||||
|
||||
begin
|
||||
if not FRegsStory.get_srsrc(FSPI.MTBUF.SRSRC,4,@src) then Assert(false);
|
||||
|
||||
grp:=GroupingSharp(@src,rtVSharp4);
|
||||
|
||||
TEmit_vbuf_load(Self).buf_load(
|
||||
Buf_info(grp,
|
||||
dst_sel_identity,
|
||||
FSPI.MTBUF.DFMT,
|
||||
FSPI.MTBUF.NFMT,
|
||||
count)
|
||||
);
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_MTBUF._emit_TBUFFER_STORE_FORMAT(count:Byte);
|
||||
var
|
||||
src:array[0..3] of PsrRegSlot;
|
||||
|
||||
grp:PsrDataLayout;
|
||||
|
||||
begin
|
||||
if not FRegsStory.get_srsrc(FSPI.MTBUF.SRSRC,4,@src) then Assert(false);
|
||||
|
||||
grp:=GroupingSharp(@src,rtVSharp4);
|
||||
|
||||
TEmit_vbuf_store(Self).buf_store(
|
||||
Buf_info(grp,
|
||||
dst_sel_identity,
|
||||
FSPI.MTBUF.DFMT,
|
||||
FSPI.MTBUF.NFMT,
|
||||
count)
|
||||
);
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_MTBUF._emit_MTBUF;
|
||||
begin
|
||||
|
||||
case FSPI.MTBUF.OP of
|
||||
TBUFFER_LOAD_FORMAT_X :_emit_TBUFFER_LOAD_FORMAT(1);
|
||||
TBUFFER_LOAD_FORMAT_XY :_emit_TBUFFER_LOAD_FORMAT(2);
|
||||
TBUFFER_LOAD_FORMAT_XYZ :_emit_TBUFFER_LOAD_FORMAT(3);
|
||||
TBUFFER_LOAD_FORMAT_XYZW :_emit_TBUFFER_LOAD_FORMAT(4);
|
||||
|
||||
TBUFFER_STORE_FORMAT_X :_emit_TBUFFER_STORE_FORMAT(1);
|
||||
TBUFFER_STORE_FORMAT_XY :_emit_TBUFFER_STORE_FORMAT(2);
|
||||
TBUFFER_STORE_FORMAT_XYZ :_emit_TBUFFER_STORE_FORMAT(3);
|
||||
TBUFFER_STORE_FORMAT_XYZW:_emit_TBUFFER_STORE_FORMAT(4);
|
||||
end;
|
||||
|
||||
//OFFSET:bit12; //Unsigned byte offset.
|
||||
//OFFEN:bit1; //enable offset in VADDR
|
||||
//IDXEN:bit1; //enable index in VADDR
|
||||
//GLC:bit1; //globally coherent.
|
||||
//
|
||||
//VADDR:Byte; //VGPR address source.
|
||||
//VDATA:Byte; //Vector GPR to read/write result to.
|
||||
//SRSRC:bit5; //Scalar GPR that specifies the resource constant, in units of four SGPRs
|
||||
//SLC:bit1; //System Level Coherent.
|
||||
//TFE:bit1; //Texture Fail Enable
|
||||
//SOFFSET:Byte;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
237
spirv/emit_mubuf.pas
Normal file
237
spirv/emit_mubuf.pas
Normal file
@ -0,0 +1,237 @@
|
||||
unit emit_MUBUF;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_shader,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srReg,
|
||||
srLayout,
|
||||
srInput,
|
||||
spirv,
|
||||
SprvEmit,
|
||||
srVBufInfo,
|
||||
emit_vbuf_load,
|
||||
emit_vbuf_store,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_MUBUF=object(TEmitOp)
|
||||
procedure _emit_MUBUF;
|
||||
procedure _make_load_zero(dst:PsrRegSlot);
|
||||
procedure _make_load_one(dst:PsrRegSlot);
|
||||
procedure _make_load_comp(dst:PsrRegSlot;rsl:PsrRegNode;i:Byte);
|
||||
function _emit_BUFFER_LOAD_VA(src:PPsrRegSlot;count:Byte):Boolean;
|
||||
procedure _emit_BUFFER_LOAD_FORMAT(count:Byte);
|
||||
procedure _emit_BUFFER_STORE_FORMAT(count:Byte);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_MUBUF._make_load_zero(dst:PsrRegSlot);
|
||||
begin
|
||||
SetConst(dst,FConsts.Fetchi(dtFloat32,0));
|
||||
end;
|
||||
|
||||
procedure TEmit_MUBUF._make_load_one(dst:PsrRegSlot);
|
||||
begin
|
||||
SetConst(dst,FConsts.Fetchf(dtFloat32,1));
|
||||
end;
|
||||
|
||||
procedure TEmit_MUBUF._make_load_comp(dst:PsrRegSlot;rsl:PsrRegNode;i:Byte);
|
||||
begin
|
||||
dst^.New(line,dtFloat32);
|
||||
rsl^.mark_read;
|
||||
emit_OpCompExtract(line,dst^.current,rsl,i);
|
||||
end;
|
||||
|
||||
function TEmit_MUBUF._emit_BUFFER_LOAD_VA(src:PPsrRegSlot;count:Byte):Boolean;
|
||||
var
|
||||
dst:PsrRegSlot;
|
||||
|
||||
grp:PsrDataLayout;
|
||||
PV:PVSharpResource4;
|
||||
|
||||
idx:PsrRegNode;
|
||||
rsl:PsrRegNode;
|
||||
|
||||
inp_idx:PsrInput;
|
||||
|
||||
dsel:Tdst_sel;
|
||||
|
||||
i,d,elem_count:Byte;
|
||||
|
||||
begin
|
||||
Result:=False;
|
||||
|
||||
idx:=FRegsStory.get_vsrc8(FSPI.MUBUF.VADDR+0)^.current;
|
||||
inp_idx:=GetInputRegNode(idx);
|
||||
if (inp_idx<>nil) then
|
||||
if (inp_idx^.key.itype=itVIndex) then //is input attach
|
||||
begin
|
||||
|
||||
grp:=GroupingSharp(src,rtVSharp4);
|
||||
PV:=grp^.pData;
|
||||
rsl:=AddVertLayout(grp,dtVec4f);
|
||||
|
||||
dsel:=dst_sel(PV^.dst_sel_x,
|
||||
PV^.dst_sel_y,
|
||||
PV^.dst_sel_z,
|
||||
PV^.dst_sel_w);
|
||||
|
||||
elem_count:=GetElemCount(PV^.dfmt);
|
||||
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.MUBUF.VDATA+i);
|
||||
if (dst=nil) then Assert(false);
|
||||
|
||||
//0=0, 1=1, 4=R, 5=G, 6=B, 7=A
|
||||
Case dsel[i] of
|
||||
0:begin //0
|
||||
_make_load_zero(dst);
|
||||
end;
|
||||
1:begin //1
|
||||
_make_load_one(dst);
|
||||
end;
|
||||
4..7:
|
||||
begin //RGBA
|
||||
d:=dsel[i]-4;
|
||||
|
||||
if (d<elem_count) then
|
||||
begin
|
||||
_make_load_comp(dst,rsl,d);
|
||||
end else
|
||||
begin //as zero
|
||||
_make_load_zero(dst);
|
||||
end;
|
||||
|
||||
end;
|
||||
else
|
||||
begin //as zero
|
||||
_make_load_zero(dst);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_MUBUF._emit_BUFFER_LOAD_FORMAT(count:Byte);
|
||||
var
|
||||
src:array[0..3] of PsrRegSlot;
|
||||
|
||||
grp:PsrDataLayout;
|
||||
PV:PVSharpResource4;
|
||||
|
||||
begin
|
||||
Assert(FSPI.MUBUF.LDS=0,'FSPI.MUBUF.LDS');
|
||||
|
||||
if not FRegsStory.get_srsrc(FSPI.MUBUF.SRSRC,4,@src) then Assert(false);
|
||||
|
||||
if FUseVertexInput then
|
||||
if (FExecutionModel=ExecutionModel.Vertex) then //Vertex only
|
||||
if (FSPI.MUBUF.IDXEN=1) and
|
||||
(FSPI.MUBUF.OFFEN=0) and
|
||||
(FSPI.MUBUF.SOFFSET=128) and
|
||||
(FSPI.MUBUF.LDS=0) then
|
||||
begin
|
||||
if _emit_BUFFER_LOAD_VA(@src,count) then Exit;
|
||||
end;
|
||||
|
||||
grp:=GroupingSharp(@src,rtVSharp4);
|
||||
PV:=grp^.pData;
|
||||
|
||||
TEmit_vbuf_load(Self).buf_load(
|
||||
Buf_info(grp,
|
||||
dst_sel(PV^.dst_sel_x,
|
||||
PV^.dst_sel_y,
|
||||
PV^.dst_sel_z,
|
||||
PV^.dst_sel_w),
|
||||
PV^.dfmt,
|
||||
PV^.nfmt,
|
||||
count)
|
||||
);
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_MUBUF._emit_BUFFER_STORE_FORMAT(count:Byte);
|
||||
var
|
||||
src:array[0..3] of PsrRegSlot;
|
||||
|
||||
grp:PsrDataLayout;
|
||||
PV:PVSharpResource4;
|
||||
|
||||
begin
|
||||
Assert(FSPI.MUBUF.LDS=0,'FSPI.MUBUF.LDS');
|
||||
|
||||
if not FRegsStory.get_srsrc(FSPI.MUBUF.SRSRC,4,@src) then Assert(false);
|
||||
|
||||
grp:=GroupingSharp(@src,rtVSharp4);
|
||||
PV:=grp^.pData;
|
||||
|
||||
TEmit_vbuf_store(Self).buf_store(
|
||||
Buf_info(grp,
|
||||
dst_sel(PV^.dst_sel_x,
|
||||
PV^.dst_sel_y,
|
||||
PV^.dst_sel_z,
|
||||
PV^.dst_sel_w),
|
||||
PV^.dfmt,
|
||||
PV^.nfmt,
|
||||
count)
|
||||
);
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_MUBUF._emit_MUBUF;
|
||||
begin
|
||||
case FSPI.MUBUF.OP of
|
||||
BUFFER_LOAD_FORMAT_X:
|
||||
begin
|
||||
_emit_BUFFER_LOAD_FORMAT(1);
|
||||
end;
|
||||
BUFFER_LOAD_FORMAT_XY:
|
||||
begin
|
||||
_emit_BUFFER_LOAD_FORMAT(2);
|
||||
end;
|
||||
BUFFER_LOAD_FORMAT_XYZ:
|
||||
begin
|
||||
_emit_BUFFER_LOAD_FORMAT(3);
|
||||
end;
|
||||
BUFFER_LOAD_FORMAT_XYZW:
|
||||
begin
|
||||
_emit_BUFFER_LOAD_FORMAT(4);
|
||||
end;
|
||||
|
||||
BUFFER_STORE_FORMAT_X:
|
||||
begin
|
||||
_emit_BUFFER_STORE_FORMAT(1);
|
||||
end;
|
||||
BUFFER_STORE_FORMAT_XY:
|
||||
begin
|
||||
_emit_BUFFER_STORE_FORMAT(2);
|
||||
end;
|
||||
BUFFER_STORE_FORMAT_XYZ:
|
||||
begin
|
||||
_emit_BUFFER_STORE_FORMAT(3);
|
||||
end;
|
||||
BUFFER_STORE_FORMAT_XYZW:
|
||||
begin
|
||||
_emit_BUFFER_STORE_FORMAT(4);
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(false,'MUBUF?'+IntToStr(FSPI.MUBUF.OP));
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
1240
spirv/emit_op.pas
Normal file
1240
spirv/emit_op.pas
Normal file
File diff suppressed because it is too large
Load Diff
1298
spirv/emit_post.pas
Normal file
1298
spirv/emit_post.pas
Normal file
File diff suppressed because it is too large
Load Diff
2306
spirv/emit_post_op.pas
Normal file
2306
spirv/emit_post_op.pas
Normal file
File diff suppressed because it is too large
Load Diff
772
spirv/emit_print.pas
Normal file
772
spirv/emit_print.pas
Normal file
@ -0,0 +1,772 @@
|
||||
unit emit_print;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
srCap,
|
||||
srRefId,
|
||||
Half16,
|
||||
SprvEmit;
|
||||
|
||||
type
|
||||
TSprvEmit_print=object(TSprvEmit)
|
||||
procedure Print;
|
||||
procedure PrintCaps;
|
||||
procedure PrintOpList(node:PspirvOp);
|
||||
procedure PrintHeaderInfo;
|
||||
procedure PrintTypes;
|
||||
procedure PrintConst(node:PsrConst);
|
||||
procedure PrintConst;
|
||||
procedure PrintVariable;
|
||||
procedure PrintFunc;
|
||||
procedure PrintOp(node:PSpirvOp;print_offset:Boolean);
|
||||
procedure PrintOpBlock(pBlock:PsrOpBlock);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TSprvEmit_print.Print;
|
||||
begin
|
||||
PrintCaps;
|
||||
Writeln;
|
||||
PrintHeaderInfo;
|
||||
Writeln;
|
||||
PrintTypes;
|
||||
Writeln;
|
||||
PrintConst;
|
||||
Writeln;
|
||||
PrintVariable;
|
||||
PrintFunc;
|
||||
end;
|
||||
|
||||
procedure PrintRefId(P:PsrRefId);
|
||||
begin
|
||||
Assert(P<>nil ,'PrintRefId$1');
|
||||
Assert(P^.Alloc,'PrintRefId$2');
|
||||
Write('%',P^.ID);
|
||||
end;
|
||||
|
||||
procedure PrintConstId(P:PsrConst);
|
||||
var
|
||||
s:Single;
|
||||
i:Int64;
|
||||
u:QWORD;
|
||||
begin
|
||||
Assert(P<>nil ,'PrintConstId$1');
|
||||
Assert(P^.ID.Alloc,'PrintConstId$2');
|
||||
|
||||
Case P^.key.dtype of
|
||||
dtBool:
|
||||
begin
|
||||
Case P^.AsBool of
|
||||
true :Write('%true');
|
||||
False:Write('%false');
|
||||
end;
|
||||
end;
|
||||
|
||||
dtHalf16:
|
||||
begin
|
||||
s:=Single(P^.AsHalf16);
|
||||
i:=Trunc(s);
|
||||
if (s=i) then
|
||||
begin
|
||||
Case i of
|
||||
0..99:Write('%ch',i);
|
||||
else
|
||||
Write('%c',P^.ID.ID);
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
Write('%c',P^.ID.ID);
|
||||
end;
|
||||
end;
|
||||
|
||||
dtFloat32:
|
||||
begin
|
||||
s:=P^.AsFloat32;
|
||||
i:=Trunc(s);
|
||||
if (s=i) then
|
||||
begin
|
||||
Case i of
|
||||
0..99:Write('%cf',i);
|
||||
-9..-1:Write('%cfm',abs(i));
|
||||
else
|
||||
Write('%c',P^.ID.ID);
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
Write('%c',P^.ID.ID);
|
||||
end;
|
||||
end;
|
||||
|
||||
dtInt32 :
|
||||
begin
|
||||
i:=P^.AsInt;
|
||||
Case i of
|
||||
0..99:Write('%ci',i);
|
||||
-9..-1:Write('%cim',abs(i));
|
||||
else
|
||||
Write('%c',P^.ID.ID);
|
||||
end;
|
||||
end;
|
||||
|
||||
dtUint32:
|
||||
begin
|
||||
u:=P^.AsUint;
|
||||
Case u of
|
||||
0..99:Write('%cu',u);
|
||||
else
|
||||
Write('%c',P^.ID.ID);
|
||||
end;
|
||||
end;
|
||||
|
||||
else
|
||||
Write('%c',P^.ID.ID);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure PrintVar(P:PsrVariable);
|
||||
Var
|
||||
n:RawByteString;
|
||||
begin
|
||||
Assert(P<>nil ,'PrintVar$1');
|
||||
Assert(P^.ID.Alloc,'PrintVar$2');
|
||||
if (P^.pSource.pData<>nil) then
|
||||
begin
|
||||
n:=P^.GetName;
|
||||
if (n<>'') then
|
||||
begin
|
||||
Write('%',n);
|
||||
end else
|
||||
begin
|
||||
Write('%v',P^.ID.ID);
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
Write('%v',P^.ID.ID);
|
||||
end;
|
||||
end;
|
||||
|
||||
function type_get_base_name(dtype:TsrDataType):RawByteString;
|
||||
begin
|
||||
Result:='';
|
||||
case dtype of
|
||||
|
||||
dtBool :Result:='bool';
|
||||
|
||||
dtFloat32 :Result:='float';
|
||||
dtHalf16 :Result:='half';
|
||||
|
||||
dtInt8 :Result:='int8';
|
||||
dtUint8 :Result:='uint8';
|
||||
|
||||
dtInt16 :Result:='int16';
|
||||
dtUint16 :Result:='uint16';
|
||||
|
||||
dtInt32 :Result:='int';
|
||||
dtUint32 :Result:='uint';
|
||||
|
||||
dtInt64 :Result:='int64';
|
||||
dtUint64 :Result:='uint64';
|
||||
|
||||
//Composite types
|
||||
dtVec2b :Result:='bvec2';
|
||||
dtVec3b :Result:='bvec3';
|
||||
dtVec4b :Result:='bvec4';
|
||||
|
||||
dtStruct2u :Result:='rec2u';
|
||||
|
||||
dtVec2u8 :Result:='u8vec2';
|
||||
dtVec4u8 :Result:='u8vec4';
|
||||
|
||||
dtVec2i8 :Result:='i8vec2';
|
||||
dtVec4i8 :Result:='i8vec4';
|
||||
|
||||
dtVec2u16 :Result:='u16vec2';
|
||||
dtVec4u16 :Result:='u16vec4';
|
||||
|
||||
dtVec2i16 :Result:='i16vec2';
|
||||
dtVec4i16 :Result:='i16vec4';
|
||||
|
||||
dtVec2u :Result:='uvec2';
|
||||
dtVec3u :Result:='uvec3';
|
||||
dtVec4u :Result:='uvec4';
|
||||
|
||||
dtVec2i :Result:='ivec2';
|
||||
dtVec3i :Result:='ivec3';
|
||||
dtVec4i :Result:='ivec4';
|
||||
|
||||
dtVec2f :Result:='vec2';
|
||||
dtVec3f :Result:='vec3';
|
||||
dtVec4f :Result:='vec4';
|
||||
|
||||
dtVec2h :Result:='hvec2';
|
||||
dtVec4h :Result:='hvec4';
|
||||
|
||||
dtTypeVoid :Result:='void';
|
||||
|
||||
dtTypeSampler:Result:='samp';
|
||||
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
function type_get_base_name(node:PsrType):RawByteString;
|
||||
var
|
||||
n:PsrType;
|
||||
begin
|
||||
Result:='';
|
||||
case node^.dtype of
|
||||
{dtTypeImage:
|
||||
begin
|
||||
if DWORD(node^.key.ext.image)=DWORD(ExtImgBuf) then
|
||||
begin
|
||||
Result:='buf';
|
||||
end else
|
||||
if DWORD(node^.key.ext.image)=DWORD(ExtImage2D) then
|
||||
begin
|
||||
Result:='img2D';
|
||||
end;
|
||||
end;}
|
||||
dtTypeSampledImage:
|
||||
begin
|
||||
if (node^.key.count<>1) then Exit;
|
||||
n:=node^.GetCompItem(0);
|
||||
Result:=type_get_base_name(n);
|
||||
if (Result='') then Exit;
|
||||
Result:='sm'+Result;
|
||||
end;
|
||||
dtTypeArray:
|
||||
begin
|
||||
n:=node^.GetCompItem(0);
|
||||
Result:=type_get_base_name(n);
|
||||
if (Result='') then Exit;
|
||||
Result:='ar'+IntToStr(node^.key.ext.array_count)+Result;
|
||||
end;
|
||||
dtTypeRuntimeArray:
|
||||
begin
|
||||
n:=node^.GetCompItem(0);
|
||||
Result:=type_get_base_name(n);
|
||||
if (Result='') then Exit;
|
||||
Result:='ra'+Result;
|
||||
end;
|
||||
dtTypeStruct:
|
||||
begin
|
||||
if (node^.key.count<>1) then Exit;
|
||||
n:=node^.GetCompItem(0);
|
||||
Result:=type_get_base_name(n);
|
||||
if (Result='') then Exit;
|
||||
Result:='st'+Result;
|
||||
end;
|
||||
dtTypeFunction:
|
||||
begin
|
||||
if (node^.key.count<>1) then Exit;
|
||||
n:=node^.GetCompItem(0);
|
||||
Result:=type_get_base_name(n);
|
||||
if (Result='') then Exit;
|
||||
Result:='fn'+Result;
|
||||
end;
|
||||
else
|
||||
Result:=type_get_base_name(node^.dtype);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure PrintTypeId(node:PsrType);
|
||||
var
|
||||
s:RawByteString;
|
||||
n:PsrType;
|
||||
begin
|
||||
case node^.dtype of
|
||||
dtTypePointer:
|
||||
begin
|
||||
n:=node^.GetCompItem(0);
|
||||
S:=type_get_base_name(n);
|
||||
if (S='') then
|
||||
PrintRefId(@node^.ID)
|
||||
else
|
||||
begin
|
||||
S:='p'+S;
|
||||
Case node^.key.ext.storage_class of
|
||||
StorageClass.UniformConstant :S:=S+'_uc';
|
||||
StorageClass.Input :S:=S+'_in';
|
||||
StorageClass.Uniform :S:=S+'_uf';
|
||||
StorageClass.Output :S:=S+'_ot';
|
||||
StorageClass.Workgroup :S:=S+'_wg';
|
||||
StorageClass.CrossWorkgroup :S:=S+'_cw';
|
||||
StorageClass.Private_ :S:=S+'_pv';
|
||||
StorageClass.Function_ :S:=S+'_fc';
|
||||
StorageClass.PushConstant :S:=S+'_pc';
|
||||
StorageClass.Image :S:=S+'_im';
|
||||
StorageClass.StorageBuffer :S:=S+'_sb';
|
||||
else
|
||||
S:='';
|
||||
end;
|
||||
if (S='') then
|
||||
PrintRefId(@node^.ID)
|
||||
else
|
||||
Write('%',S);
|
||||
end;
|
||||
end;
|
||||
else
|
||||
begin
|
||||
S:=type_get_base_name(node);
|
||||
if (S='') then
|
||||
PrintRefId(@node^.ID)
|
||||
else
|
||||
Write('%',S);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure PrintChain(P:PsrChain);
|
||||
begin
|
||||
Assert(P<>nil ,'PrintChain$1');
|
||||
Assert(P^.ID.Alloc,'PrintChain$2');
|
||||
Write('%ac',P^.ID.ID);
|
||||
end;
|
||||
|
||||
procedure PrintReg(P:PsrRegNode);
|
||||
begin
|
||||
Assert(P<>nil,'PrintReg$1');
|
||||
Case P^.pWriter.ntype of
|
||||
ntConst:
|
||||
begin
|
||||
PrintConstId(P^.pWriter.pData);
|
||||
end;
|
||||
ntOp:
|
||||
begin
|
||||
if (not P^.ID.Alloc) then Assert(false,'PrintReg$2');
|
||||
Write('%r',P^.ID.ID);
|
||||
//Write('(',P^.read_count,')');
|
||||
end;
|
||||
else
|
||||
Assert(false,'PrintReg$3');
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_print.PrintCaps;
|
||||
var
|
||||
node:PSpirvCap;
|
||||
begin
|
||||
node:=FSpirvCaps.First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
Writeln(Op.GetStr(Op.OpCapability),' ',Capability.GetStr(node^.ID));
|
||||
node:=FSpirvCaps.Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_print.PrintOpList(node:PspirvOp);
|
||||
begin
|
||||
While (node<>nil) do
|
||||
begin
|
||||
PrintOp(node,false);
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_print.PrintHeaderInfo;
|
||||
begin
|
||||
PrintOpList(FHeader.pHead);
|
||||
Writeln;
|
||||
PrintOpList(FDebugInfo.pHead);
|
||||
if (FDebugInfo.pHead<>nil) then Writeln;
|
||||
PrintOpList(FDecorates.pHead);
|
||||
end;
|
||||
|
||||
function Dim_GetStr(w:Word):RawByteString;
|
||||
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
|
||||
Assert(False,'Dim_GetStr');
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_print.PrintTypes;
|
||||
var
|
||||
node:PsrType;
|
||||
pConst:PsrConst;
|
||||
i:dword;
|
||||
ie:Boolean;
|
||||
begin
|
||||
node:=FSpirvTypes.FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
ie:=True;
|
||||
|
||||
pConst:=nil;
|
||||
case node^.dtype of
|
||||
dtTypeArray:
|
||||
begin
|
||||
//find a const
|
||||
pConst:=FConsts.Fetchi(dtUInt32,node^.key.ext.array_count);
|
||||
PrintConst(pConst);
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
|
||||
PrintTypeId(node);
|
||||
Write(' = ');
|
||||
|
||||
Write(Op.GetStr(node^.key.OpId));
|
||||
|
||||
case node^.key.OpId of
|
||||
|
||||
Op.OpTypeFloat:
|
||||
begin
|
||||
Write(' ',node^.key.ext.float_size);
|
||||
end;
|
||||
|
||||
Op.OpTypeInt:
|
||||
begin
|
||||
Write(' ',node^.key.ext.int_size);
|
||||
Write(' ',node^.key.ext.int_sign);
|
||||
end;
|
||||
|
||||
Op.OpTypeVector:
|
||||
begin
|
||||
ie:=False;
|
||||
Write(' ');
|
||||
PrintTypeId(node^.GetCompItem(0));
|
||||
Write(' ',node^.key.ext.array_count);
|
||||
end;
|
||||
|
||||
Op.OpTypePointer:
|
||||
begin
|
||||
Write(' ',StorageClass.GetStr(node^.key.ext.Storage_Class));
|
||||
end;
|
||||
|
||||
Op.OpTypeArray:
|
||||
begin
|
||||
ie:=False;
|
||||
Write(' ');
|
||||
PrintTypeId(node^.GetCompItem(0));
|
||||
Write(' ');
|
||||
PrintConstId(pConst);
|
||||
end;
|
||||
|
||||
Op.OpTypeRuntimeArray:
|
||||
begin
|
||||
ie:=False;
|
||||
Write(' ');
|
||||
PrintTypeId(node^.GetCompItem(0));
|
||||
end;
|
||||
|
||||
Op.OpTypeImage:
|
||||
begin
|
||||
ie:=False;
|
||||
Write(' ');
|
||||
PrintTypeId(node^.GetCompItem(0));
|
||||
With node^.key.ext.image do
|
||||
Write(' ',
|
||||
Dim_GetStr(Dim),' ',
|
||||
Depth,' ',
|
||||
Arrayed,' ',
|
||||
MS,' ',
|
||||
Sampled,' ',
|
||||
Spirv.ImageFormat.GetStr(Format));
|
||||
end;
|
||||
|
||||
|
||||
end;
|
||||
|
||||
if ie then
|
||||
if (node^.key.count<>0) then
|
||||
begin
|
||||
For i:=0 to node^.key.count-1 do
|
||||
begin
|
||||
Write(' ');
|
||||
PrintTypeId(node^.GetCompItem(i));
|
||||
end;
|
||||
end;
|
||||
|
||||
Writeln;
|
||||
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
const
|
||||
DefaultFormatSettings : TFormatSettings = (
|
||||
CurrencyFormat: 1;
|
||||
NegCurrFormat: 5;
|
||||
ThousandSeparator: ',';
|
||||
DecimalSeparator: '.';
|
||||
CurrencyDecimals: 2;
|
||||
DateSeparator: '-';
|
||||
TimeSeparator: ':';
|
||||
ListSeparator: ',';
|
||||
CurrencyString: '$';
|
||||
ShortDateFormat: 'd/m/y';
|
||||
LongDateFormat: 'dd" "mmmm" "yyyy';
|
||||
TimeAMString: 'AM';
|
||||
TimePMString: 'PM';
|
||||
ShortTimeFormat: 'hh:nn';
|
||||
LongTimeFormat: 'hh:nn:ss';
|
||||
ShortMonthNames: ('Jan','Feb','Mar','Apr','May','Jun',
|
||||
'Jul','Aug','Sep','Oct','Nov','Dec');
|
||||
LongMonthNames: ('January','February','March','April','May','June',
|
||||
'July','August','September','October','November','December');
|
||||
ShortDayNames: ('Sun','Mon','Tue','Wed','Thu','Fri','Sat');
|
||||
LongDayNames: ('Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday');
|
||||
TwoDigitYearCenturyWindow: 50;
|
||||
);
|
||||
|
||||
procedure TSprvEmit_print.PrintConst(node:PsrConst);
|
||||
var
|
||||
i:dword;
|
||||
begin
|
||||
PrintConstId(node);
|
||||
Write(' = ');
|
||||
|
||||
if (node^.key.count=0) then
|
||||
begin
|
||||
if (node^.key.dtype=dtBool) then
|
||||
begin
|
||||
Case node^.AsBool of
|
||||
True :Write(Op.GetStr(Op.OpConstantTrue));
|
||||
False:Write(Op.GetStr(Op.OpConstantFalse));
|
||||
end;
|
||||
Write(' ');
|
||||
PrintTypeId(node^.pType);
|
||||
end else
|
||||
begin
|
||||
Write(Op.GetStr(Op.OpConstant));
|
||||
Write(' ');
|
||||
PrintTypeId(node^.pType);
|
||||
Write(' ');
|
||||
case node^.key.dtype of
|
||||
dtFloat32:Write(FloatToStr(node^.AsFloat32,DefaultFormatSettings));
|
||||
dtHalf16 :Write(FloatToStr(Single(node^.AsHalf16),DefaultFormatSettings));
|
||||
dtInt32 :Write(node^.AsInt);
|
||||
dtUint32 :Write(node^.AsUint);
|
||||
dtInt64 :Write(node^.AsInt64);
|
||||
dtUint64 :Write(node^.AsUint64);
|
||||
else
|
||||
Assert(false,'PrintConst');
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
Write(Op.GetStr(Op.OpConstantComposite));
|
||||
Write(' ');
|
||||
PrintTypeId(node^.pType);
|
||||
For i:=0 to node^.key.count-1 do
|
||||
begin
|
||||
Write(' ');
|
||||
PrintConstId(node^.GetCompItem(i));
|
||||
end;
|
||||
end;
|
||||
|
||||
Writeln;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_print.PrintConst;
|
||||
var
|
||||
node:PsrConst;
|
||||
begin
|
||||
node:=FConsts.FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
|
||||
//if not node^.is_first then
|
||||
//begin
|
||||
if (node^.key.dtype=dtUnknow) then
|
||||
begin
|
||||
Write('; ');
|
||||
PrintConstId(node);
|
||||
Writeln(' = dtUnknow: read_count=',node^.read_count,' value=',node^.Data);
|
||||
end else
|
||||
//Assert(node^.dtype<>dtUnknow);
|
||||
PrintConst(node);
|
||||
//end;
|
||||
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_print.PrintVariable;
|
||||
var
|
||||
node:PsrVariable;
|
||||
begin
|
||||
node:=FVariables.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.pType<>nil) then
|
||||
begin
|
||||
PrintVar(node);
|
||||
Write(' = ',Op.GetStr(Op.OpVariable),' ');
|
||||
PrintTypeId(node^.pType);
|
||||
Writeln(' ',StorageClass.GetStr(node^.GetStorageClass));
|
||||
end;
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure PrintFuncId(P:PSpirvFunc);
|
||||
begin
|
||||
Assert(P<>nil,'PrintFuncId');
|
||||
if (P^.name<>'') then
|
||||
begin
|
||||
Write('%',P^.name);
|
||||
end else
|
||||
begin
|
||||
PrintRefId(@P^.ID);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure PrintOpParamSingle(const Param:TOpParamSingle);
|
||||
begin
|
||||
Assert(Param.pData<>nil,'PrintOpParamSingle$1');
|
||||
Case Param.ntype of
|
||||
ntFunc :PrintFuncId(Param.pData);
|
||||
ntRefId:PrintRefId(Param.pData);
|
||||
ntType :PrintTypeId(Param.pData);
|
||||
ntReg :PrintReg(Param.pData);
|
||||
ntVar :PrintVar(Param.pData);
|
||||
ntChain:PrintChain(Param.pData);
|
||||
ntConst:PrintConstId(Param.pData);
|
||||
else
|
||||
Assert(false,'PrintOpParamSingle$2');
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure PrintOpParamNode(node:POpParamNode);
|
||||
begin
|
||||
Case node^.ntype of
|
||||
ntLiteral:
|
||||
begin
|
||||
if StrLen(@node^.name)=0 then
|
||||
begin
|
||||
Write(node^.Value);
|
||||
end else
|
||||
begin
|
||||
Write(PChar(@node^.name));
|
||||
end;
|
||||
end;
|
||||
ntString:
|
||||
begin
|
||||
Write('"',PChar(@node^.name),'"');
|
||||
end;
|
||||
else
|
||||
begin
|
||||
PrintOpParamSingle(node^.AsParam);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_print.PrintFunc;
|
||||
var
|
||||
pFunc:PSpirvFunc;
|
||||
begin
|
||||
pFunc:=FSpirvFuncs.FList.pHead;
|
||||
While (pFunc<>nil) do
|
||||
begin
|
||||
Writeln;
|
||||
PrintOpBlock(@pFunc^.FTop);
|
||||
pFunc:=pFunc^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_print.PrintOp(node:PSpirvOp;print_offset:Boolean);
|
||||
var
|
||||
Param:POpParamNode;
|
||||
Info:Op.TOpInfo;
|
||||
begin
|
||||
if (node=nil) then Exit;
|
||||
|
||||
Info:=Op.GetInfo(node^.OpId);
|
||||
|
||||
if Info.result then //dst
|
||||
begin
|
||||
Assert(node^.dst.ntype<>ntUnknow,'PrintOp$1');
|
||||
Assert(node^.dst.pData<>nil,'PrintOp$2');
|
||||
PrintOpParamSingle(node^.dst);
|
||||
Write(' = ');
|
||||
Write(Op.GetStr(node^.OpId));
|
||||
end else
|
||||
begin //no dst
|
||||
Write(Op.GetStr(node^.OpId));
|
||||
if (node^.dst.ntype<>ntUnknow) then
|
||||
begin
|
||||
Assert(node^.dst.pData<>nil,'PrintOp$3');
|
||||
Write(' ');
|
||||
PrintOpParamSingle(node^.dst);
|
||||
end;
|
||||
end;
|
||||
|
||||
if Info.rstype then //dst type
|
||||
begin
|
||||
Assert(node^.dst_type<>nil,'PrintOp$4');
|
||||
Write(' ');
|
||||
PrintTypeId(node^.dst_type);
|
||||
end;
|
||||
|
||||
Param:=node^.pParam.pHead;
|
||||
While (Param<>nil) do
|
||||
begin
|
||||
Write(' ');
|
||||
PrintOpParamNode(Param);
|
||||
Param:=Param^.pNext;
|
||||
end;
|
||||
|
||||
if (node^.OpId=Op.OpLabel) then
|
||||
begin
|
||||
print_offset:=true;
|
||||
end;
|
||||
|
||||
Case print_offset of
|
||||
True :Writeln(' ;0x',HexStr(Node^.Adr.Offdw*4,4));
|
||||
False:Writeln;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_print.PrintOpBlock(pBlock:PsrOpBlock);
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
if (pBlock=nil) then Exit;
|
||||
node:=pBlock^.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
|
||||
if (node^.OpId=OpBlock) then
|
||||
begin
|
||||
if (node^.dst.ntype=ntBlock) then
|
||||
begin
|
||||
PrintOpBlock(node^.dst.pData);
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
Write(Space(pBlock^.FLevel));
|
||||
PrintOp(node,false);
|
||||
end;
|
||||
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
155
spirv/emit_smrd.pas
Normal file
155
spirv/emit_smrd.pas
Normal file
@ -0,0 +1,155 @@
|
||||
unit emit_SMRD;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srReg,
|
||||
srLayout,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_SMRD=object(TEmitOp)
|
||||
procedure _emit_SMRD;
|
||||
procedure _emit_LOAD_DWORDX(grp:PsrDataLayout;count:Byte);
|
||||
procedure emit_LOAD_DWORDX(count:Byte);
|
||||
procedure emit_BUFFER_LOAD_DWORDX(count:Byte);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_SMRD._emit_LOAD_DWORDX(grp:PsrDataLayout;count:Byte);
|
||||
var
|
||||
dst:PsrRegSlot;
|
||||
|
||||
ofs_r,idx_r:PsrRegNode;
|
||||
dtype:TsrDataType;
|
||||
|
||||
ext:TsrChainExt;
|
||||
|
||||
i:Byte;
|
||||
|
||||
begin
|
||||
|
||||
if (FSPI.SMRD.IMM<>0) then
|
||||
begin
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SMRD.SDST+i);
|
||||
Assert(dst<>nil);
|
||||
MakeChain(dst,grp,(FSPI.SMRD.OFFSET+i)*4,4,nil);
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
ofs_r:=fetch_ssrc9(FSPI.SMRD.OFFSET,dtUint32);
|
||||
dtype:=ofs_r^.dtype;
|
||||
|
||||
idx_r:=NewReg(dtype);
|
||||
|
||||
_emit_OpShr(line,idx_r,ofs_r,FetchReg(FConsts.Fetchi(dtype,2)));
|
||||
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SMRD.SDST+i);
|
||||
Assert(dst<>nil);
|
||||
|
||||
if (i=0) then
|
||||
begin
|
||||
ofs_r:=idx_r;
|
||||
end else
|
||||
begin
|
||||
ofs_r:=NewReg(dtype);
|
||||
idx_r^.mark_read;
|
||||
_emit_OpIAdd(line,ofs_r,idx_r,FetchReg(FConsts.Fetchi(dtype,i)));
|
||||
end;
|
||||
|
||||
ofs_r^.mark_read;
|
||||
|
||||
ext:=Default(TsrChainExt);
|
||||
ext.pIndex:=ofs_r;
|
||||
ext.stride:=4;
|
||||
MakeChain(dst,grp,0,4,@ext);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_SMRD.emit_LOAD_DWORDX(count:Byte);
|
||||
var
|
||||
src:array[0..3] of PsrRegSlot;
|
||||
grp:PsrDataLayout;
|
||||
begin
|
||||
if not FRegsStory.get_sbase(FSPI.SMRD.SBASE,2,@src) then Assert(false);
|
||||
grp:=GroupingSharp(@src,rtBufPtr2);
|
||||
_emit_LOAD_DWORDX(grp,count);
|
||||
end;
|
||||
|
||||
procedure TEmit_SMRD.emit_BUFFER_LOAD_DWORDX(count:Byte);
|
||||
var
|
||||
src:array[0..3] of PsrRegSlot;
|
||||
grp:PsrDataLayout;
|
||||
begin
|
||||
if not FRegsStory.get_sbase(FSPI.SMRD.SBASE,4,@src) then Assert(false);
|
||||
grp:=GroupingSharp(@src,rtVSharp4);
|
||||
_emit_LOAD_DWORDX(grp,count);
|
||||
end;
|
||||
|
||||
procedure TEmit_SMRD._emit_SMRD;
|
||||
begin
|
||||
|
||||
Case FSPI.SMRD.OP of
|
||||
S_BUFFER_LOAD_DWORD:
|
||||
begin
|
||||
emit_BUFFER_LOAD_DWORDX(1);
|
||||
end;
|
||||
S_BUFFER_LOAD_DWORDX2:
|
||||
begin
|
||||
emit_BUFFER_LOAD_DWORDX(2);
|
||||
end;
|
||||
S_BUFFER_LOAD_DWORDX4:
|
||||
begin
|
||||
emit_BUFFER_LOAD_DWORDX(4);
|
||||
end;
|
||||
S_BUFFER_LOAD_DWORDX8:
|
||||
begin
|
||||
emit_BUFFER_LOAD_DWORDX(8);
|
||||
end;
|
||||
S_BUFFER_LOAD_DWORDX16:
|
||||
begin
|
||||
emit_BUFFER_LOAD_DWORDX(16);
|
||||
end;
|
||||
|
||||
S_LOAD_DWORD:
|
||||
begin
|
||||
emit_LOAD_DWORDX(1);
|
||||
end;
|
||||
S_LOAD_DWORDX2:
|
||||
begin
|
||||
emit_LOAD_DWORDX(2);
|
||||
end;
|
||||
S_LOAD_DWORDX4:
|
||||
begin
|
||||
emit_LOAD_DWORDX(4);
|
||||
end;
|
||||
S_LOAD_DWORDX8:
|
||||
begin
|
||||
emit_LOAD_DWORDX(8);
|
||||
end;
|
||||
S_LOAD_DWORDX16:
|
||||
begin
|
||||
emit_LOAD_DWORDX(16);
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(false,'SMRD?'+IntToStr(FSPI.SMRD.OP));
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
245
spirv/emit_sop1.pas
Normal file
245
spirv/emit_sop1.pas
Normal file
@ -0,0 +1,245 @@
|
||||
unit emit_SOP1;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srLabel,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
srLayout,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_SOP1=object(TEmitOp)
|
||||
procedure _emit_SOP1;
|
||||
Function _GetFuncPtr(src:PPsrRegSlot):Pointer;
|
||||
procedure _emit_S_MOV_B32;
|
||||
procedure _emit_S_MOV_B64;
|
||||
procedure _emit_S_SWAPPC_B64;
|
||||
procedure _emit_S_SETPC_B64;
|
||||
procedure _emit_S_AND_SAVEEXEC_B64;
|
||||
procedure _emit_S_WQM_B64;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
Function TEmit_SOP1._GetFuncPtr(src:PPsrRegSlot):Pointer;
|
||||
var
|
||||
chain:TsrChains;
|
||||
pLayout:PsrDataLayout;
|
||||
|
||||
begin
|
||||
Result:=nil;
|
||||
|
||||
chain:=Default(TsrChains);
|
||||
chain[0]:=GetChainRegNode(src[0]^.current);
|
||||
chain[1]:=GetChainRegNode(src[1]^.current);
|
||||
|
||||
pLayout:=FDataLayouts.Grouping(chain,rtFunPtr2);
|
||||
Result:=pLayout^.pData;
|
||||
|
||||
Assert(Result<>nil);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP1._emit_S_MOV_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SOP1.SDST);
|
||||
src:=fetch_ssrc9(FSPI.SOP1.SSRC,dtUnknow);
|
||||
_MakeCopy(dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP1._emit_S_MOV_B64;
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst[0]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+0);
|
||||
dst[1]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+1);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.SOP1.SSRC+0,dtUnknow);
|
||||
src[1]:=fetch_ssrc9(FSPI.SOP1.SSRC+1,dtUnknow);
|
||||
|
||||
_MakeCopy(dst[0],src[0]);
|
||||
_MakeCopy(dst[1],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP1._emit_S_SWAPPC_B64;
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
src:array[0..1] of PsrRegSlot;
|
||||
|
||||
oldptr,newptr:Pointer;
|
||||
|
||||
begin
|
||||
if not FRegsStory.get_sdst7_pair(FSPI.SOP1.SDST,@dst) then Assert(false);
|
||||
|
||||
Assert(not is_const_ssrc9(FSPI.SOP1.SSRC));
|
||||
|
||||
if not FRegsStory.get_ssrc9_pair(FSPI.SOP1.SSRC,@src) then Assert(false);
|
||||
|
||||
newptr:=_GetFuncPtr(@src);
|
||||
Assert(newptr<>nil);
|
||||
|
||||
oldptr:=FCursor.Adr.get_pc;
|
||||
|
||||
SetConst(dst[0],dtUint32,{%H-}QWORD(oldptr));
|
||||
SetConst(dst[1],dtUint32,{%H-}QWORD(oldptr) shr 32);
|
||||
|
||||
SetPtr(newptr,btSetpc);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP1._emit_S_SETPC_B64;
|
||||
Var
|
||||
src:array[0..1] of PsrRegSlot;
|
||||
node:array[0..1] of PsrRegNode;
|
||||
pConst:array[0..1] of PsrConst;
|
||||
|
||||
newptr:Pointer;
|
||||
|
||||
begin
|
||||
Assert(not is_const_ssrc9(FSPI.SOP1.SSRC));
|
||||
if not FRegsStory.get_ssrc9_pair(FSPI.SOP1.SSRC,@src) then Assert(false);
|
||||
|
||||
node[0]:=RegDown(src[0]^.current);
|
||||
node[1]:=RegDown(src[1]^.current);
|
||||
|
||||
Assert(node[0]<>nil);
|
||||
Assert(node[1]<>nil);
|
||||
|
||||
if (node[0]^.is_const) and (node[1]^.is_const) then
|
||||
begin
|
||||
//ret of func
|
||||
pConst[0]:=node[0]^.AsConst;
|
||||
pConst[1]:=node[1]^.AsConst;
|
||||
|
||||
{%H-}QWORD(newptr):=QWORD(pConst[0]^.AsUint) or (QWORD(pConst[1]^.AsUint) shl 32);
|
||||
|
||||
SetPtr(newptr,btMain);
|
||||
end else
|
||||
begin
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP1._emit_S_AND_SAVEEXEC_B64; //sdst.du = EXEC;| EXEC = (ssrc.du & EXEC);| SCC = (sdst != 0)
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
exc:array[0..1] of PsrRegNode;
|
||||
|
||||
begin
|
||||
|
||||
dst[0]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+0);
|
||||
dst[1]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+1);
|
||||
|
||||
Assert(dst[0]<>nil);
|
||||
Assert(dst[1]<>nil);
|
||||
|
||||
if not fetch_ssrc9_pair(@src,FSPI.SOP1.SSRC,dtUnknow) then Assert(False); //ssrc8
|
||||
|
||||
PrepTypeSlot(@FRegsStory.EXEC[0],dtUnknow);
|
||||
PrepTypeSlot(@FRegsStory.EXEC[1],dtUnknow);
|
||||
|
||||
exc[0]:=FRegsStory.EXEC[0].current;
|
||||
exc[1]:=FRegsStory.EXEC[1].current;
|
||||
|
||||
MakeCopy(dst[0],exc[0]);
|
||||
MakeCopy(dst[1],exc[1]);
|
||||
|
||||
exc[0]^.mark_read;
|
||||
exc[1]^.mark_read;
|
||||
|
||||
emit_OpBitwiseAnd(@FRegsStory.EXEC[0],src[0],exc[0]);
|
||||
emit_OpBitwiseAnd(@FRegsStory.EXEC[1],src[1],exc[1]);
|
||||
|
||||
//SCC = ((exc[0] != 0) or ((exc[1] != 0))
|
||||
|
||||
exc[0]^.mark_read;
|
||||
exc[1]^.mark_read;
|
||||
|
||||
emit_OpLogicalOr(@FRegsStory.SCC,exc[0],exc[1]); //implict cast (int != 0)
|
||||
|
||||
//SCC = (sdst != 0) SCC = ((exc[0] != 0) or ((exc[1] != 0))
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP1._emit_S_WQM_B64;
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
|
||||
begin
|
||||
//S_WQM_B64 EXEC_LO, EXEC_LO //sdst.du = wholeQuadMode(ssrc.du); SCC = (sdst.du != 0)
|
||||
//dst[q*4+3:q*4].du = (ssrc[4*q+3:4*q].du != 0) ? 0xF : 0
|
||||
//dst[3:0].du = (ssrc[3:0].du != 0) ? 0xF : 0
|
||||
//dst[63:60].du = (ssrc[63:60].du != 0) ? 0xF : 0
|
||||
//if (ssrc[3:0].du != 0) then dst[63:60].du=0xF else dst[63:60].du=0
|
||||
|
||||
dst[0]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+0);
|
||||
dst[1]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+1);
|
||||
|
||||
Assert(dst[0]<>nil);
|
||||
Assert(dst[1]<>nil);
|
||||
|
||||
if not fetch_ssrc9_pair(@src,FSPI.SOP1.SSRC,dtUnknow) then Assert(False); //ssrc8
|
||||
|
||||
emit_WQM_32(dst[0],src[0]);
|
||||
emit_WQM_32(dst[1],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP1._emit_SOP1;
|
||||
begin
|
||||
|
||||
Case FSPI.SOP1.OP of
|
||||
S_MOV_B32:
|
||||
begin
|
||||
_emit_S_MOV_B32;
|
||||
end;
|
||||
|
||||
S_MOV_B64:
|
||||
begin
|
||||
_emit_S_MOV_B64;
|
||||
end;
|
||||
|
||||
S_WQM_B64:
|
||||
begin
|
||||
_emit_S_WQM_B64;
|
||||
end;
|
||||
|
||||
S_SWAPPC_B64:
|
||||
begin
|
||||
_emit_S_SWAPPC_B64;
|
||||
end;
|
||||
|
||||
S_SETPC_B64:
|
||||
begin
|
||||
_emit_S_SETPC_B64;
|
||||
end;
|
||||
|
||||
S_AND_SAVEEXEC_B64:
|
||||
begin
|
||||
_emit_S_AND_SAVEEXEC_B64;
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(false,'SOP1?'+IntToStr(FSPI.SOP1.OP));
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
||||
|
||||
|
||||
|
||||
|
345
spirv/emit_sop2.pas
Normal file
345
spirv/emit_sop2.pas
Normal file
@ -0,0 +1,345 @@
|
||||
unit emit_SOP2;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
|
||||
type
|
||||
TEmit_SOP2=object(TEmitOp)
|
||||
procedure _emit_SOP2;
|
||||
procedure _emit_S_ADD_I32;
|
||||
procedure _emit_S_MUL_I32;
|
||||
procedure _emit_S_LSHL_B32;
|
||||
procedure _emit_S_LSHR_B32;
|
||||
procedure _emit_S_AND_B32;
|
||||
procedure _emit_S_AND_B64;
|
||||
procedure _emit_S_ANDN2_B64;
|
||||
procedure _emit_S_OR_B64;
|
||||
procedure _emit_S_NOR_B64;
|
||||
procedure _emit_S_CSELECT_B32;
|
||||
procedure _emit_S_BFE_U32;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_SOP2._emit_S_ADD_I32;
|
||||
Var
|
||||
dst,car:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST);
|
||||
car:=@FRegsStory.SCC;
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtInt32);
|
||||
src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtInt32);
|
||||
|
||||
emit_OpIAddExt(dst,car,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_MUL_I32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtInt32);
|
||||
src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtInt32);
|
||||
|
||||
emit_OpIMul(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_LSHL_B32; //SCC = (sdst.u != 0)
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUInt32);
|
||||
src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUInt32);
|
||||
|
||||
src[2]:=FetchReg(FConsts.Fetch(dtUInt32,31));
|
||||
emit_OpBitwiseAnd(tmp,src[1],src[2]);
|
||||
src[1]:=MakeRead(tmp,dtUInt32);
|
||||
|
||||
emit_OpShl(dst,src[0],src[1]);
|
||||
|
||||
//dst = dtUint32
|
||||
|
||||
tmp:=@FRegsStory.SCC;
|
||||
MakeCopy(tmp,dst^.current);
|
||||
tmp^.current^.dtype:=dtBool;
|
||||
|
||||
//dst^.current^.mark_read;
|
||||
//emit_IntToBool(line,FRegsStory.SCC.New(dtBool),dst^.current);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_LSHR_B32; //SCC = (sdst.u != 0)
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUInt32);
|
||||
src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUInt32);
|
||||
|
||||
src[2]:=FetchReg(FConsts.Fetch(dtUInt32,31));
|
||||
emit_OpBitwiseAnd(tmp,src[1],src[2]);
|
||||
src[1]:=MakeRead(tmp,dtUInt32);
|
||||
|
||||
emit_OpShr(dst,src[0],src[1]);
|
||||
|
||||
tmp:=@FRegsStory.SCC;
|
||||
MakeCopy(tmp,dst^.current);
|
||||
tmp^.current^.dtype:=dtBool;
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_AND_B32; //SCC = (sdst.u != 0)
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUInt32);
|
||||
src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUInt32);
|
||||
|
||||
emit_OpBitwiseAnd(dst,src[0],src[1]);
|
||||
|
||||
tmp:=@FRegsStory.SCC;
|
||||
MakeCopy(tmp,dst^.current);
|
||||
tmp^.current^.dtype:=dtBool;
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_AND_B64; //SCC = (sdst[2] != 0)
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
src0,src1,src2:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
if not FRegsStory.get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False);
|
||||
|
||||
if not fetch_ssrc9_pair(@src0,FSPI.SOP2.SSRC0,dtUInt32) then Assert(False);
|
||||
if not fetch_ssrc9_pair(@src1,FSPI.SOP2.SSRC1,dtUInt32) then Assert(False);
|
||||
|
||||
emit_OpBitwiseAnd(dst[0],src0[0],src1[0]);
|
||||
emit_OpBitwiseAnd(dst[1],src0[1],src1[1]);
|
||||
|
||||
src2[0]:=dst[0]^.current;
|
||||
src2[1]:=dst[1]^.current;
|
||||
|
||||
src2[0]^.mark_read;
|
||||
src2[1]^.mark_read;
|
||||
emit_OpLogicalOr(@FRegsStory.SCC,src2[0],src2[1]); //implict cast (int != 0)
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_ANDN2_B64; //SCC = (sdst[2] != 0)
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
tmp:PsrRegSlot;
|
||||
src0,src1,src2:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
if not FRegsStory.get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False);
|
||||
|
||||
if not fetch_ssrc9_pair(@src0,FSPI.SOP2.SSRC0,dtUInt32) then Assert(False);
|
||||
if not fetch_ssrc9_pair(@src1,FSPI.SOP2.SSRC1,dtUInt32) then Assert(False);
|
||||
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
|
||||
emit_OpNot(tmp,src1[0]);
|
||||
src1[0]:=MakeRead(tmp,dtUnknow);
|
||||
|
||||
emit_OpNot(tmp,src1[1]);
|
||||
src1[1]:=MakeRead(tmp,dtUnknow);
|
||||
|
||||
emit_OpBitwiseAnd(dst[0],src0[0],src1[0]);
|
||||
emit_OpBitwiseAnd(dst[1],src0[1],src1[1]);
|
||||
|
||||
src2[0]:=dst[0]^.current;
|
||||
src2[1]:=dst[1]^.current;
|
||||
|
||||
src2[0]^.mark_read;
|
||||
src2[1]^.mark_read;
|
||||
emit_OpLogicalOr(@FRegsStory.SCC,src2[0],src2[1]); //implict cast (int != 0)
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_OR_B64; //SCC = (sdst[2] != 0)
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
src0,src1,src2:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
if not FRegsStory.get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False);
|
||||
|
||||
if not fetch_ssrc9_pair(@src0,FSPI.SOP2.SSRC0,dtUInt32) then Assert(False);
|
||||
if not fetch_ssrc9_pair(@src1,FSPI.SOP2.SSRC1,dtUInt32) then Assert(False);
|
||||
|
||||
emit_OpBitwiseOr(dst[0],src0[0],src1[0]);
|
||||
emit_OpBitwiseOr(dst[1],src0[1],src1[1]);
|
||||
|
||||
src2[0]:=dst[0]^.current;
|
||||
src2[1]:=dst[1]^.current;
|
||||
|
||||
src2[0]^.mark_read;
|
||||
src2[1]^.mark_read;
|
||||
emit_OpLogicalOr(@FRegsStory.SCC,src2[0],src2[1]); //implict cast (int != 0)
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_NOR_B64; //SCC = (sdst[2] != 0)
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
src0,src1,src2:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
if not FRegsStory.get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False);
|
||||
|
||||
if not fetch_ssrc9_pair(@src0,FSPI.SOP2.SSRC0,dtUInt32) then Assert(False);
|
||||
if not fetch_ssrc9_pair(@src1,FSPI.SOP2.SSRC1,dtUInt32) then Assert(False);
|
||||
|
||||
emit_OpBitwiseOr(dst[0],src0[0],src1[0]);
|
||||
emit_OpBitwiseOr(dst[1],src0[1],src1[1]);
|
||||
|
||||
src2[0]:=dst[0]^.current;
|
||||
src2[1]:=dst[1]^.current;
|
||||
|
||||
src2[0]^.mark_read;
|
||||
src2[1]^.mark_read;
|
||||
|
||||
emit_OpNot(dst[0],src2[0]);
|
||||
emit_OpNot(dst[1],src2[1]);
|
||||
|
||||
src2[0]:=dst[0]^.current;
|
||||
src2[1]:=dst[1]^.current;
|
||||
|
||||
src2[0]^.mark_read;
|
||||
src2[1]^.mark_read;
|
||||
|
||||
emit_OpLogicalOr(@FRegsStory.SCC,src2[0],src2[1]); //implict cast (int != 0)
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_CSELECT_B32; //sdst = SCC ? ssrc0 : ssrc1
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUnknow);
|
||||
src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUnknow);
|
||||
src[2]:=MakeRead(@FRegsStory.SCC,dtBool);
|
||||
|
||||
emit_OpSelect(dst,src[0],src[1],src[2]);
|
||||
end;
|
||||
|
||||
//offset = ssrc1[4:0].u and 31
|
||||
//width = ssrc1[22:16].u shr 16
|
||||
procedure TEmit_SOP2._emit_S_BFE_U32; //sdst.u = bitFieldExtract(ssrc0); SCC = (sdst.u != 0)
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
num_31,num_16:PsrRegNode;
|
||||
offset,count:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUint32);
|
||||
src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUint32);
|
||||
|
||||
num_31:=FetchReg(FConsts.Fetch(dtUInt32,31));
|
||||
|
||||
emit_OpBitwiseAnd(tmp,src[1],num_31);
|
||||
offset:=MakeRead(tmp,dtUInt32);
|
||||
|
||||
num_16:=FetchReg(FConsts.Fetch(dtUInt32,16));
|
||||
|
||||
src[1]^.mark_read;
|
||||
emit_OpShr(tmp,src[1],num_16);
|
||||
count:=MakeRead(tmp,dtUInt32);
|
||||
|
||||
emit_OpBfeU(dst,src[0],offset,count);
|
||||
|
||||
tmp:=@FRegsStory.SCC;
|
||||
MakeCopy(tmp,dst^.current);
|
||||
tmp^.current^.dtype:=dtBool;
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_SOP2;
|
||||
begin
|
||||
|
||||
Case FSPI.SOP2.OP of
|
||||
|
||||
S_ADD_I32:
|
||||
begin
|
||||
_emit_S_ADD_I32;
|
||||
end;
|
||||
|
||||
S_MUL_I32: //& 0xFFFFFFFF
|
||||
begin
|
||||
_emit_S_MUL_I32;
|
||||
end;
|
||||
|
||||
S_LSHL_B32: //SCC = (sdst.u != 0)
|
||||
begin
|
||||
_emit_S_LSHL_B32;
|
||||
end;
|
||||
|
||||
S_LSHR_B32:
|
||||
begin
|
||||
_emit_S_LSHR_B32;
|
||||
end;
|
||||
|
||||
S_AND_B32:
|
||||
begin
|
||||
_emit_S_AND_B32;
|
||||
end;
|
||||
|
||||
S_AND_B64:
|
||||
begin
|
||||
_emit_S_AND_B64;
|
||||
end;
|
||||
|
||||
S_ANDN2_B64:
|
||||
begin
|
||||
_emit_S_ANDN2_B64;
|
||||
end;
|
||||
|
||||
S_OR_B64:
|
||||
begin
|
||||
_emit_S_OR_B64;
|
||||
end;
|
||||
|
||||
S_NOR_B64:
|
||||
begin
|
||||
_emit_S_NOR_B64;
|
||||
end;
|
||||
|
||||
S_CSELECT_B32:
|
||||
begin
|
||||
_emit_S_CSELECT_B32;
|
||||
end;
|
||||
|
||||
S_BFE_U32:
|
||||
begin
|
||||
_emit_S_BFE_U32;
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(False,'SOP2?'+IntToStr(FSPI.SOP2.OP));
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
66
spirv/emit_sopc.pas
Normal file
66
spirv/emit_sopc.pas
Normal file
@ -0,0 +1,66 @@
|
||||
unit emit_SOPC;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srReg,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_SOPC=object(TEmitOp)
|
||||
procedure _emit_SOPC;
|
||||
procedure _emit_S_CMP_32(OpId:DWORD;rtype:TsrDataType);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_SOPC._emit_S_CMP_32(OpId:DWORD;rtype:TsrDataType);
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=@FRegsStory.SCC;
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.SOPC.SSRC0,rtype);
|
||||
src[1]:=fetch_ssrc9(FSPI.SOPC.SSRC1,rtype);
|
||||
|
||||
emit_OpCmpS(OpId,dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOPC._emit_SOPC;
|
||||
begin
|
||||
Case FSPI.SOPC.OP of
|
||||
S_CMP_EQ_I32 :_emit_S_CMP_32(Op.OpIEqual ,dtInt32);
|
||||
S_CMP_LG_I32 :_emit_S_CMP_32(Op.OpINotEqual ,dtInt32);
|
||||
S_CMP_GT_I32 :_emit_S_CMP_32(Op.OpSGreaterThan ,dtInt32);
|
||||
S_CMP_GE_I32 :_emit_S_CMP_32(Op.OpSGreaterThanEqual,dtInt32);
|
||||
S_CMP_LT_I32 :_emit_S_CMP_32(Op.OpSLessThan ,dtInt32);
|
||||
S_CMP_LE_I32 :_emit_S_CMP_32(Op.OpSLessThanEqual ,dtInt32);
|
||||
|
||||
S_CMP_EQ_U32 :_emit_S_CMP_32(Op.OpIEqual ,dtUint32);
|
||||
S_CMP_LG_U32 :_emit_S_CMP_32(Op.OpINotEqual ,dtUint32);
|
||||
S_CMP_GT_U32 :_emit_S_CMP_32(Op.OpUGreaterThan ,dtUint32);
|
||||
S_CMP_GE_U32 :_emit_S_CMP_32(Op.OpUGreaterThanEqual,dtUint32);
|
||||
S_CMP_LT_U32 :_emit_S_CMP_32(Op.OpULessThan ,dtUint32);
|
||||
S_CMP_LE_U32 :_emit_S_CMP_32(Op.OpULessThanEqual ,dtUint32);
|
||||
|
||||
//S_BITCMP0_B32:;
|
||||
//S_BITCMP1_B32:;
|
||||
//S_BITCMP0_B64:;
|
||||
//S_BITCMP1_B64:;
|
||||
//S_SETVSKIP :;
|
||||
else
|
||||
Assert(false,'SOPC?'+IntToStr(FSPI.SOPC.OP));
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
300
spirv/emit_sopp.pas
Normal file
300
spirv/emit_sopp.pas
Normal file
@ -0,0 +1,300 @@
|
||||
unit emit_SOPP;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srParser,
|
||||
srLabel,
|
||||
srCFG,
|
||||
srReg,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
spirv,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_SOPP=object(TEmitOp)
|
||||
procedure _emit_SOPP;
|
||||
procedure _emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean);
|
||||
procedure _emit_S_BRANCH;
|
||||
function IsBegLoop(Adr:TSrcAdr):Boolean;
|
||||
function IsEndLoop(Adr:TSrcAdr):Boolean;
|
||||
procedure emit_cond_block(pSlot:PsrRegSlot;n:Boolean;adr:TSrcAdr);
|
||||
procedure UpBuildVol(last:PsrOpBlock);
|
||||
procedure emit_loop(adr:TSrcAdr);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
srVolatile;
|
||||
|
||||
procedure TEmit_SOPP.emit_cond_block(pSlot:PsrRegSlot;n:Boolean;adr:TSrcAdr);
|
||||
var
|
||||
src:PsrRegNode;
|
||||
pOpBlock:PsrOpBlock;
|
||||
pOpChild:PsrOpBlock;
|
||||
pOpLabel:array[0..1] of PspirvOp;
|
||||
pLBlock:PsrCFGBlock;
|
||||
Info:array[0..1] of TsrBlockInfo;
|
||||
begin
|
||||
src:=MakeRead(pSlot,dtBool); //get before OpBranchConditional
|
||||
|
||||
pOpLabel[0]:=NewLabelOp;
|
||||
pOpLabel[1]:=NewLabelOp;
|
||||
|
||||
pLBlock:=FCursor.pCode^.FTop.DownBlock(adr);
|
||||
Assert(pLBlock<>@FCursor.pCode^.FTop,'not found');
|
||||
|
||||
Info[0]:=Default(TsrBlockInfo);
|
||||
Info[1]:=Default(TsrBlockInfo);
|
||||
|
||||
Case pLBlock^.bType of
|
||||
btAdr: //set new adr
|
||||
begin
|
||||
Info[0].b_adr:=FCursor.Adr;
|
||||
Info[0].e_adr:=FCursor.Adr;
|
||||
Info[0].bType:=btCond;
|
||||
//
|
||||
Info[1].b_adr:=pLBlock^.pBLabel^.Adr;
|
||||
Info[1].e_adr:=pLBlock^.pELabel^.Adr;
|
||||
Info[1].bType:=btAdr;
|
||||
end;
|
||||
btCond: //normal cond
|
||||
begin
|
||||
Info[0].b_adr:=pLBlock^.pBLabel^.Adr;
|
||||
Info[0].e_adr:=pLBlock^.pELabel^.Adr;
|
||||
Info[0].bType:=btCond;
|
||||
//
|
||||
Info[1].b_adr:=Info[0].b_adr;
|
||||
Info[1].e_adr:=Info[0].e_adr;
|
||||
Info[1].bType:=btOther;
|
||||
end;
|
||||
else
|
||||
Assert(false,'emit_cond_block');
|
||||
end;
|
||||
|
||||
pOpLabel[0]^.Adr:=Info[0].b_adr;
|
||||
pOpLabel[1]^.Adr:=Info[0].e_adr;
|
||||
|
||||
pOpBlock:=NewBlockOp(FRegsStory.get_snapshot);
|
||||
pOpBlock^.SetLabels(pOpLabel[0],pOpLabel[1],nil);
|
||||
pOpBlock^.SetInfo(Info[0]);
|
||||
pOpBlock^.SetCond(src,not n);
|
||||
|
||||
PushBlockOp(line,pOpBlock,pLBlock);
|
||||
|
||||
emit_OpCondMerge(line,pOpLabel[1]);
|
||||
|
||||
Case n of
|
||||
True :emit_OpBranchCond(line,pOpLabel[1],pOpLabel[0],src);
|
||||
False:emit_OpBranchCond(line,pOpLabel[0],pOpLabel[1],src);
|
||||
end;
|
||||
|
||||
AddSpirvOp(line,pOpLabel[0]);
|
||||
|
||||
//down group
|
||||
pOpChild:=AllocBlockOp;
|
||||
pOpChild^.SetInfo(Info[1]);
|
||||
PushBlockOp(line,pOpChild,nil);
|
||||
|
||||
if (pLBlock^.bType=btAdr) then //set new adr
|
||||
begin
|
||||
SetPtr(adr.get_pc,btAdr);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_SOPP.UpBuildVol(last:PsrOpBlock);
|
||||
var
|
||||
node:PsrOpBlock;
|
||||
begin
|
||||
node:=FMain^.pBlock;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
|
||||
Case node^.Block.bType of
|
||||
btCond:TEmitVolatile(Self).build_volatile_cur(node^.Regs.pSnap);
|
||||
btLoop:TEmitVolatile(Self).build_volatile_old(node^.Regs.pSnap);
|
||||
else;
|
||||
end;
|
||||
|
||||
if (node=last) then Break;
|
||||
node:=node^.pParent;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_SOPP.emit_loop(adr:TSrcAdr);
|
||||
var
|
||||
node,pOpBlock:PsrOpBlock;
|
||||
pOpLabel:array[0..1] of PspirvOp;
|
||||
FVolMark:TsrVolMark;
|
||||
bnew:Boolean;
|
||||
begin
|
||||
|
||||
node:=FMain^.pBlock;
|
||||
pOpBlock:=node^.FindUpLoop;
|
||||
Assert(pOpBlock<>nil,'not found');
|
||||
|
||||
pOpLabel[0]:=nil;
|
||||
|
||||
FVolMark:=vmNone;
|
||||
if (pOpBlock^.Block.b_adr.get_pc=adr.get_pc) then //is continue?
|
||||
begin
|
||||
pOpLabel[0]:=pOpBlock^.Labels.pMrgOp; //-> OpLoopMerge end -> OpLoopMerge before
|
||||
pOpBlock^.Cond.FUseCont:=True;
|
||||
FVolMark:=vmCont;
|
||||
end else
|
||||
if (pOpBlock^.Block.b_adr.get_pc=adr.get_pc) then //is break?
|
||||
begin
|
||||
pOpLabel[0]:=pOpBlock^.Labels.pEndOp;
|
||||
FVolMark:=vmBreak;
|
||||
end else
|
||||
begin
|
||||
Assert(false,'emit_loop');
|
||||
end;
|
||||
|
||||
Assert(pOpLabel[0]<>nil);
|
||||
|
||||
bnew:=true;
|
||||
if FCursor.pBlock^.IsEndOf(FCursor.Adr) then //is last
|
||||
begin
|
||||
Assert(node^.Block.e_adr.get_pc=FCursor.Adr.get_pc);
|
||||
Case node^.Block.bType of
|
||||
btSetpc:;
|
||||
else
|
||||
begin
|
||||
bnew:=false;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
UpBuildVol(pOpBlock);
|
||||
node^.Regs.FVolMark:=FVolMark; //mark end of
|
||||
|
||||
emit_OpBranch(line,pOpLabel[0]);
|
||||
if bnew then
|
||||
begin
|
||||
pOpLabel[1]:=NewLabelOp;
|
||||
AddSpirvOp(line,pOpLabel[1]);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TEmit_SOPP.IsBegLoop(Adr:TSrcAdr):Boolean;
|
||||
var
|
||||
node:PsrCFGBlock;
|
||||
begin
|
||||
Result:=false;
|
||||
node:=FCursor.pBlock^.FindUpLoop;
|
||||
if (node<>nil) then
|
||||
begin
|
||||
Result:=node^.pBLabel^.Adr.get_pc=Adr.get_pc;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TEmit_SOPP.IsEndLoop(Adr:TSrcAdr):Boolean;
|
||||
var
|
||||
node:PsrCFGBlock;
|
||||
begin
|
||||
Result:=false;
|
||||
node:=FCursor.pBlock^.FindUpLoop;
|
||||
if (node<>nil) then
|
||||
begin
|
||||
Result:=node^.pELabel^.Adr.get_pc=Adr.get_pc;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_SOPP._emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean);
|
||||
var
|
||||
c_adr,b_adr:TSrcAdr;
|
||||
pLabel:PsrLabel;
|
||||
|
||||
begin
|
||||
c_adr:=FCursor.Adr;
|
||||
b_adr:=c_adr;
|
||||
b_adr.Offdw:=get_branch_offset(FSPI);
|
||||
|
||||
pLabel:=FindLabel(b_adr);
|
||||
Assert(pLabel<>nil);
|
||||
Assert(not pLabel^.IsType(ltUnknow));
|
||||
|
||||
if pLabel^.IsType(ltBegAdr) then //adr
|
||||
begin
|
||||
emit_cond_block(pSlot,n,b_adr);
|
||||
end else
|
||||
if (SmallInt(FSPI.SOPP.SIMM)<0) then //up
|
||||
begin //continue?
|
||||
if not IsBegLoop(b_adr) then Assert(false,'Unknow');
|
||||
Assert(false,'TODO');
|
||||
end else
|
||||
begin //down
|
||||
if FCursor.pBlock^.IsBigOf(b_adr) then
|
||||
begin //break?
|
||||
if not IsEndLoop(b_adr) then Assert(false,'Unknow');
|
||||
Assert(false,'TODO');
|
||||
end else
|
||||
begin //cond
|
||||
emit_cond_block(pSlot,n,c_adr);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_SOPP._emit_S_BRANCH;
|
||||
var
|
||||
c_adr,b_adr:TSrcAdr;
|
||||
|
||||
begin
|
||||
c_adr:=FCursor.Adr;
|
||||
b_adr:=c_adr;
|
||||
b_adr.Offdw:=get_branch_offset(FSPI);
|
||||
|
||||
|
||||
if (SmallInt(FSPI.SOPP.SIMM)<0) then //up
|
||||
begin //continue?
|
||||
if not IsBegLoop(b_adr) then Assert(false,'Unknow');
|
||||
emit_loop(b_adr);
|
||||
end else //down
|
||||
begin //break?
|
||||
if not IsEndLoop(b_adr) then Assert(false,'Unknow');
|
||||
emit_loop(b_adr);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_SOPP._emit_SOPP;
|
||||
begin
|
||||
Case FSPI.SOPP.OP of
|
||||
S_NOP,
|
||||
S_WAITCNT:;
|
||||
|
||||
S_ENDPGM:
|
||||
begin
|
||||
if not is_term_op(line) then
|
||||
begin
|
||||
AddSpirvOp(Op.OpReturn);
|
||||
end;
|
||||
FMain^.pBlock^.Regs.FVolMark:=vmEnd; //mark end of
|
||||
end;
|
||||
|
||||
S_CBRANCH_SCC0 :_emit_S_BRANCH_COND(@FRegsStory.SCC,false);
|
||||
S_CBRANCH_SCC1 :_emit_S_BRANCH_COND(@FRegsStory.SCC,true);
|
||||
S_CBRANCH_VCCZ :_emit_S_BRANCH_COND(@FRegsStory.VCC[0],false);
|
||||
S_CBRANCH_VCCNZ :_emit_S_BRANCH_COND(@FRegsStory.VCC[0],true);
|
||||
S_CBRANCH_EXECZ :_emit_S_BRANCH_COND(@FRegsStory.EXEC[0],false);
|
||||
S_CBRANCH_EXECNZ:_emit_S_BRANCH_COND(@FRegsStory.EXEC[0],true);
|
||||
|
||||
S_BRANCH :_emit_S_BRANCH;
|
||||
|
||||
else
|
||||
Assert(false,'SOPP?'+IntToStr(FSPI.SOPP.OP));
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
417
spirv/emit_vbuf_chain.pas
Normal file
417
spirv/emit_vbuf_chain.pas
Normal file
@ -0,0 +1,417 @@
|
||||
unit emit_vbuf_chain;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_shader,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
srLayout,
|
||||
SprvEmit,
|
||||
emit_op,
|
||||
srVBufInfo;
|
||||
|
||||
type
|
||||
TBuf_adr=packed record
|
||||
stride,align,fsize,csize:PtrInt;
|
||||
soffset,ioffset,voffset:PtrInt;
|
||||
sof,ofs,idx:PsrRegNode;
|
||||
end;
|
||||
|
||||
TvcType=(vcInvalid,vcChainVector,vcChainElement,vcUniformVector,vcUniformElement);
|
||||
|
||||
TvarChain=record
|
||||
vType:TvcType;
|
||||
data:array[0..1] of Pointer;
|
||||
end;
|
||||
|
||||
TEmit_vbuf_chain=object(TEmitOp)
|
||||
function OpDivTo(pReg:PsrRegNode;i:QWORD):PsrRegNode;
|
||||
function OpMulTo(pReg:PsrRegNode;i:QWORD):PsrRegNode;
|
||||
function OpAddTo(pReg:PsrRegNode;i:QWORD):PsrRegNode;
|
||||
function OpAddTo(pReg0,pReg1:PsrRegNode):PsrRegNode;
|
||||
procedure get_reg_adr(var adr:TBuf_adr);
|
||||
function get_sum_ofs(var adr:TBuf_adr):PsrRegNode;
|
||||
function get_idx_elm(var adr:TBuf_adr):PsrRegNode;
|
||||
function get_idx_fmt(var adr:TBuf_adr):PsrRegNode;
|
||||
function get_chain(info:TBuf_info):TvarChain;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function isPowerOfTwo(x:QWORD):Boolean; inline;
|
||||
begin
|
||||
Result:=((x-1) and x)=0;
|
||||
end;
|
||||
|
||||
function fastIntLog2(i:QWORD):QWORD; inline;
|
||||
begin
|
||||
Result:=BsfQWORD(i);
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_chain.OpDivTo(pReg:PsrRegNode;i:QWORD):PsrRegNode;
|
||||
begin
|
||||
if (pReg=nil) or (i<=1) then Exit(pReg);
|
||||
Result:=NewReg(pReg^.dtype);
|
||||
pReg^.mark_read;
|
||||
if isPowerOfTwo(i) then
|
||||
begin
|
||||
i:=fastIntLog2(i);
|
||||
if (SignType(pReg^.dtype)<>0) then
|
||||
begin
|
||||
_emit_OpShrA(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i)));
|
||||
end else
|
||||
begin
|
||||
_emit_OpShr(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i)));
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
if (SignType(pReg^.dtype)<>0) then
|
||||
begin
|
||||
_emit_OpSDiv(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i)));
|
||||
end else
|
||||
begin
|
||||
_emit_OpUDiv(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i)));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_chain.OpMulTo(pReg:PsrRegNode;i:QWORD):PsrRegNode;
|
||||
begin
|
||||
if (pReg=nil) or (i<=1) then Exit(pReg);
|
||||
Result:=NewReg(pReg^.dtype);
|
||||
pReg^.mark_read;
|
||||
if isPowerOfTwo(i) then
|
||||
begin
|
||||
i:=fastIntLog2(i);
|
||||
_emit_OpShl(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i)));
|
||||
end else
|
||||
begin
|
||||
_emit_OpIMul(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i)));
|
||||
end;
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_chain.OpAddTo(pReg:PsrRegNode;i:QWORD):PsrRegNode;
|
||||
begin
|
||||
if (pReg=nil) or (i=0) then Exit(pReg);
|
||||
Result:=NewReg(pReg^.dtype);
|
||||
pReg^.mark_read;
|
||||
_emit_OpIAdd(line,Result,pReg,FetchReg(FConsts.Fetchi(pReg^.dtype,i)));
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_chain.OpAddTo(pReg0,pReg1:PsrRegNode):PsrRegNode;
|
||||
begin
|
||||
if (pReg0=nil) then Exit(pReg1);
|
||||
if (pReg1=nil) then Exit(pReg0);
|
||||
Result:=NewReg(pReg0^.dtype);
|
||||
pReg0^.mark_read;
|
||||
pReg1^.mark_read;
|
||||
_emit_OpIAdd(line,Result,pReg0,pReg1);
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_chain.get_reg_adr(var adr:TBuf_adr);
|
||||
var
|
||||
ofs:PsrRegSlot;
|
||||
begin
|
||||
if is_const_soffset(FSPI.MUBUF.SOFFSET) then
|
||||
begin
|
||||
adr.soffset:=get_soffset_const_int(FSPI.MUBUF.SOFFSET);
|
||||
end else
|
||||
begin
|
||||
ofs:=FRegsStory.get_ssrc8(FSPI.MUBUF.SOFFSET);
|
||||
if (ofs<>nil) then
|
||||
begin
|
||||
adr.sof:=ofs^.current;
|
||||
if (adr.sof<>nil) then
|
||||
begin
|
||||
if (adr.sof^.is_const) then
|
||||
begin
|
||||
adr.soffset:=adr.sof^.AsConst^.AsInt;
|
||||
adr.sof:=nil;
|
||||
end else
|
||||
begin
|
||||
Assert(false,'FSPI.MUBUF.SOFFSET');
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
ofs:=nil;
|
||||
if (FSPI.MUBUF.IDXEN=1) then
|
||||
begin
|
||||
adr.idx:=fetch_vsrc8(FSPI.MUBUF.VADDR+0,dtInt32);
|
||||
if (FSPI.MUBUF.OFFEN=1) then
|
||||
begin
|
||||
ofs:=FRegsStory.get_vsrc8(FSPI.MUBUF.VADDR+1);
|
||||
end;
|
||||
end else
|
||||
if (FSPI.MUBUF.OFFEN=1) then
|
||||
begin
|
||||
ofs:=FRegsStory.get_vsrc8(FSPI.MUBUF.VADDR+0);
|
||||
end;
|
||||
|
||||
if (ofs<>nil) then
|
||||
begin
|
||||
adr.ofs:=ofs^.current;
|
||||
if (adr.ofs<>nil) then
|
||||
begin
|
||||
if (adr.ofs^.is_const) then
|
||||
begin
|
||||
adr.voffset:=adr.ofs^.AsConst^.AsInt;
|
||||
adr.ofs:=nil;
|
||||
end else
|
||||
begin
|
||||
adr.ofs:=MakeRead(ofs,dtInt32);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_chain.get_sum_ofs(var adr:TBuf_adr):PsrRegNode;
|
||||
var
|
||||
foffset:PtrInt;
|
||||
|
||||
sum_d,ofs_d,idx_m:PsrRegNode;
|
||||
|
||||
begin
|
||||
foffset:=adr.soffset+adr.ioffset+adr.voffset;
|
||||
|
||||
if (foffset mod adr.align=0) and //const offset is align
|
||||
((adr.idx=nil) or //no index or
|
||||
(adr.stride mod adr.align=0)) then //stride is align
|
||||
begin
|
||||
|
||||
//(foffset is Align)
|
||||
//(stride is Align)
|
||||
//result=(foffset/Align+ofs/Align+idx*(stride/Align)) in elem
|
||||
|
||||
adr.ofs^.mark_unread;
|
||||
ofs_d:=OpDivTo(adr.ofs,adr.align); //ofs/Align
|
||||
sum_d:=OpAddTo(ofs_d,foffset div adr.align); //foffset/Align+ofs/Align
|
||||
|
||||
if (adr.idx<>nil) then
|
||||
begin
|
||||
adr.idx^.mark_unread;
|
||||
idx_m:=OpMulTo(adr.idx,adr.stride div adr.align); //idx*(stride/Align)
|
||||
sum_d:=OpAddTo(sum_d,idx_m);
|
||||
end;
|
||||
|
||||
end else
|
||||
begin
|
||||
|
||||
//result=(foffset+ofs+idx*stride)/Align in elem
|
||||
|
||||
adr.ofs^.mark_unread;
|
||||
sum_d:=OpAddTo(adr.ofs,foffset); //foffset+ofs
|
||||
|
||||
if (adr.idx<>nil) then
|
||||
begin
|
||||
adr.idx^.mark_unread;
|
||||
idx_m:=OpMulTo(adr.idx,adr.stride); //idx*stride
|
||||
sum_d:=OpAddTo(sum_d,idx_m);
|
||||
end;
|
||||
|
||||
sum_d:=OpDivTo(sum_d,adr.align); // sum/Align
|
||||
end;
|
||||
|
||||
Result:=sum_d;
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_chain.get_idx_elm(var adr:TBuf_adr):PsrRegNode;
|
||||
var
|
||||
foffset:PtrInt;
|
||||
|
||||
sum_d,idx_m:PsrRegNode;
|
||||
|
||||
begin
|
||||
//result=(foffset/Align+idx*(stride/Align)) in elem
|
||||
|
||||
foffset:=adr.soffset+adr.ioffset+adr.voffset;
|
||||
foffset:=foffset div adr.align;
|
||||
|
||||
if (adr.idx=nil) then
|
||||
begin
|
||||
sum_d:=FetchReg(FConsts.Fetchi(dtUint32,foffset));
|
||||
sum_d^.mark_unread;
|
||||
end else
|
||||
begin
|
||||
adr.idx^.mark_unread;
|
||||
idx_m:=OpMulTo(adr.idx,adr.stride div adr.align); //idx*(stride/Align)
|
||||
sum_d:=OpAddTo(idx_m,foffset);
|
||||
end;
|
||||
|
||||
Result:=sum_d;
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_chain.get_idx_fmt(var adr:TBuf_adr):PsrRegNode;
|
||||
var
|
||||
foffset:PtrInt;
|
||||
|
||||
sum_d,idx_m:PsrRegNode;
|
||||
|
||||
begin
|
||||
//result=(foffset/size+idx*(stride/size)) in format
|
||||
|
||||
foffset:=adr.soffset+adr.ioffset+adr.voffset;
|
||||
foffset:=foffset div adr.fsize;
|
||||
|
||||
if (adr.idx=nil) then
|
||||
begin
|
||||
sum_d:=FetchReg(FConsts.Fetchi(dtUint32,foffset));
|
||||
sum_d^.mark_unread;
|
||||
end else
|
||||
begin
|
||||
adr.idx^.mark_unread;
|
||||
idx_m:=OpMulTo(adr.idx,adr.stride div adr.fsize); //idx*(stride/size)
|
||||
sum_d:=OpAddTo(idx_m,foffset);
|
||||
end;
|
||||
|
||||
Result:=sum_d;
|
||||
end;
|
||||
|
||||
function Min(a,b:PtrInt):PtrInt; inline;
|
||||
begin
|
||||
if (a<b) then Result:=a else Result:=b;
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_chain.get_chain(info:TBuf_info):TvarChain;
|
||||
var
|
||||
PV:PVSharpResource4;
|
||||
|
||||
adr:TBuf_adr;
|
||||
foffset:PtrInt;
|
||||
|
||||
sum_d:PsrRegNode;
|
||||
|
||||
ext:TsrChainExt;
|
||||
|
||||
img:TsrImageInfo;
|
||||
|
||||
begin
|
||||
Result:=Default(TvarChain);
|
||||
|
||||
if (info.GetElemCount=0) then
|
||||
begin
|
||||
Result.vType:=vcInvalid;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
PV:=info.grp^.pData;
|
||||
Assert(PV^.swizzle_en=0,'swizzle_en');
|
||||
Assert(PV^.addtid_en =0,'addtid_en');
|
||||
|
||||
adr:=Default(TBuf_adr);
|
||||
adr.stride :=PV^.stride;
|
||||
adr.align :=info.GetAlignSize;
|
||||
adr.fsize :=info.GetSizeFormat;
|
||||
adr.csize :=Min(info.GetElemSize*info.count,adr.fsize);
|
||||
adr.ioffset:=FSPI.MUBUF.OFFSET;
|
||||
|
||||
if (adr.stride=0) then adr.stride:=1;
|
||||
|
||||
get_reg_adr(adr);
|
||||
|
||||
foffset:=adr.soffset+adr.ioffset+adr.voffset;
|
||||
Assert(foffset>=0,'WTF');
|
||||
|
||||
if (adr.ofs=nil) and (adr.idx=nil) then //simple
|
||||
begin
|
||||
|
||||
Result.vType :=vcChainVector;
|
||||
Result.data[0]:=info.grp^.Fetch(foffset,adr.csize,nil);
|
||||
|
||||
Exit;
|
||||
end;
|
||||
|
||||
//result=Align(foffset+ofs+idx*stride) in byte
|
||||
|
||||
if (adr.ofs<>nil) then
|
||||
begin
|
||||
sum_d:=get_sum_ofs(adr);
|
||||
|
||||
//minTexelBufferOffsetAlignment
|
||||
if FUseTexelBuffer then
|
||||
if (info.IsComp) and
|
||||
(adr.stride div adr.align=0) then
|
||||
begin
|
||||
//is uniform buffer per element
|
||||
|
||||
img:=info.GetImageInfoElement;
|
||||
|
||||
Result.vType :=vcUniformElement;
|
||||
Result.data[0]:=FetchImage(info.grp,img.dtype,img.tinfo);
|
||||
Result.data[1]:=sum_d;
|
||||
|
||||
Exit;
|
||||
end;
|
||||
|
||||
sum_d^.mark_read;
|
||||
ext:=Default(TsrChainExt);
|
||||
ext.pIndex:=sum_d;
|
||||
ext.stride:=adr.align;
|
||||
|
||||
Result:=Default(TvarChain);
|
||||
Result.vType :=vcChainElement;
|
||||
Result.data[0]:=info.grp^.Fetch(0,adr.align,@ext);
|
||||
|
||||
Exit;
|
||||
end else
|
||||
begin //idx<>nil
|
||||
|
||||
//minTexelBufferOffsetAlignment
|
||||
if FUseTexelBuffer then
|
||||
if (info.IsComp) and
|
||||
(adr.stride mod adr.fsize=0) and
|
||||
(foffset mod adr.fsize=0) then
|
||||
begin
|
||||
//is uniform buffer per format
|
||||
|
||||
sum_d:=get_idx_fmt(adr);
|
||||
|
||||
img:=info.GetImageInfo;
|
||||
|
||||
Result.vType :=vcUniformVector;
|
||||
Result.data[0]:=FetchImage(info.grp,img.dtype,img.tinfo);
|
||||
Result.data[1]:=sum_d;
|
||||
|
||||
Exit;
|
||||
end;
|
||||
|
||||
//minTexelBufferOffsetAlignment
|
||||
if FUseTexelBuffer then
|
||||
if (info.IsComp) and
|
||||
(adr.stride div adr.align=0) then
|
||||
begin
|
||||
//is uniform buffer per element
|
||||
|
||||
sum_d:=get_idx_elm(adr);
|
||||
|
||||
img:=info.GetImageInfoElement;
|
||||
|
||||
Result.vType :=vcUniformElement;
|
||||
Result.data[0]:=FetchImage(info.grp,img.dtype,img.tinfo);
|
||||
Result.data[1]:=sum_d;
|
||||
|
||||
Exit;
|
||||
end;
|
||||
|
||||
//adr.idx^.mark_read;
|
||||
ext:=Default(TsrChainExt);
|
||||
ext.pIndex:=adr.idx;
|
||||
ext.stride:=adr.stride;
|
||||
|
||||
Result.vType :=vcChainVector;
|
||||
Result.data[0]:=info.grp^.Fetch(foffset,adr.csize,@ext);
|
||||
|
||||
Exit;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
394
spirv/emit_vbuf_load.pas
Normal file
394
spirv/emit_vbuf_load.pas
Normal file
@ -0,0 +1,394 @@
|
||||
unit emit_vbuf_load;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
srLayout,
|
||||
SprvEmit,
|
||||
emit_op,
|
||||
srVBufInfo,
|
||||
emit_vbuf_chain;
|
||||
|
||||
type
|
||||
Tload_cache=record
|
||||
info:TBuf_info;
|
||||
v:TvarChain;
|
||||
dst:PsrRegSlot;
|
||||
elem_orig:TsrDataType;
|
||||
elem_resl:TsrDataType;
|
||||
elem_count:ptruint;
|
||||
rsl:PsrRegNode;
|
||||
elm:array[0..3] of PsrRegNode;
|
||||
end;
|
||||
|
||||
TEmit_vbuf_load=object(TEmitOp)
|
||||
procedure buf_load(info:TBuf_info);
|
||||
function OpMulF(pReg:PsrRegNode;s:Single):PsrRegNode;
|
||||
function OpAddF(pReg:PsrRegNode;s:Single):PsrRegNode;
|
||||
function OpUToF(pReg:PsrRegNode):PsrRegNode;
|
||||
function OpSToF(pReg:PsrRegNode):PsrRegNode;
|
||||
function OpShlI(pReg:PsrRegNode;i:DWORD):PsrRegNode;
|
||||
function OpAddI(pReg:PsrRegNode;i:DWORD):PsrRegNode;
|
||||
function _convert_e(var lc:Tload_cache;src:PsrRegNode):PsrRegNode;
|
||||
procedure _make_load_cv_id(var lc:Tload_cache;i:Byte);
|
||||
procedure _make_load_ce_id(var lc:Tload_cache;i:Byte);
|
||||
procedure _make_load_uv_id(var lc:Tload_cache;i:Byte);
|
||||
procedure _make_load_ue_id(var lc:Tload_cache;i:Byte);
|
||||
procedure _make_load_zero(var lc:Tload_cache);
|
||||
procedure _make_load_one(var lc:Tload_cache);
|
||||
procedure buf_load_cv(info:TBuf_info;v:TvarChain);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_vbuf_load.buf_load(info:TBuf_info);
|
||||
var
|
||||
v:TvarChain;
|
||||
begin
|
||||
v:=TEmit_vbuf_chain(Self).get_chain(info);
|
||||
|
||||
if (v.vType=vcUniformVector) then
|
||||
begin
|
||||
//reset dst sel
|
||||
info.dsel:=dst_sel_identity;
|
||||
end;
|
||||
|
||||
buf_load_cv(info,v);
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_load.OpMulF(pReg:PsrRegNode;s:Single):PsrRegNode;
|
||||
begin
|
||||
if (pReg=nil) or (s=1) then Exit(pReg);
|
||||
Result:=NewReg(pReg^.dtype);
|
||||
pReg^.mark_read;
|
||||
_emit_Op2(line,Op.OpFMul,Result,pReg,FetchReg(FConsts.Fetchf(dtFloat32,s)));
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_load.OpAddF(pReg:PsrRegNode;s:Single):PsrRegNode;
|
||||
begin
|
||||
if (pReg=nil) or (s=0) then Exit(pReg);
|
||||
Result:=NewReg(pReg^.dtype);
|
||||
pReg^.mark_read;
|
||||
_emit_Op2(line,Op.OpFAdd,Result,pReg,FetchReg(FConsts.Fetchf(dtFloat32,s)));
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_load.OpUToF(pReg:PsrRegNode):PsrRegNode;
|
||||
begin
|
||||
if (pReg=nil) then Exit(pReg);
|
||||
Result:=NewReg(dtFloat32);
|
||||
pReg^.mark_read;
|
||||
_emit_Op1(line,Op.OpConvertUToF,Result,pReg);
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_load.OpSToF(pReg:PsrRegNode):PsrRegNode;
|
||||
begin
|
||||
if (pReg=nil) then Exit(pReg);
|
||||
Result:=NewReg(dtFloat32);
|
||||
pReg^.mark_read;
|
||||
_emit_Op1(line,Op.OpConvertSToF,Result,pReg);
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_load.OpShlI(pReg:PsrRegNode;i:DWORD):PsrRegNode;
|
||||
begin
|
||||
if (pReg=nil) or (i=0) then Exit(pReg);
|
||||
Result:=NewReg(pReg^.dtype);
|
||||
pReg^.mark_read;
|
||||
_emit_OpShl(line,Result,pReg,FetchReg(FConsts.Fetchi(dtUint32,i)));
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_load.OpAddI(pReg:PsrRegNode;i:DWORD):PsrRegNode;
|
||||
begin
|
||||
if (pReg=nil) or (i=0) then Exit(pReg);
|
||||
Result:=NewReg(pReg^.dtype);
|
||||
pReg^.mark_read;
|
||||
_emit_OpIAdd(line,Result,pReg,FetchReg(FConsts.Fetchi(dtUint32,i)));
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_load._convert_e(var lc:Tload_cache;src:PsrRegNode):PsrRegNode;
|
||||
begin
|
||||
Result:=src;
|
||||
if (lc.elem_resl<>lc.elem_orig) then
|
||||
Case lc.info.NFMT of
|
||||
BUF_NUM_FORMAT_UNORM : //Unsigned, normalized to range [0.0..1.0]; data/(1<<nbits-1)
|
||||
begin
|
||||
Result:=OpUToF(src);
|
||||
Result:=OpMulF(Result,1/GetTypeHigh(lc.elem_orig));
|
||||
end;
|
||||
|
||||
BUF_NUM_FORMAT_SNORM : //Signed, normalized to range [-1.0..1.0]; data/(1<<(nbits-1)-1) clamped
|
||||
begin
|
||||
Result:=OpSToF(src);
|
||||
Result:=OpMulF(Result,1/(GetTypeHigh(lc.elem_orig) shr 1));
|
||||
Result:=OpAddF(Result,-1);
|
||||
end;
|
||||
|
||||
BUF_NUM_FORMAT_USCALED : //Unsigned integer to float [0.0 .. (1<<nbits)-1]
|
||||
begin
|
||||
Result:=OpUToF(src);
|
||||
end;
|
||||
|
||||
BUF_NUM_FORMAT_SSCALED : //Signed integer to float [-(1<<(nbits-1)) ..(1<<(nbits-1))-1]
|
||||
begin
|
||||
Result:=OpSToF(src);
|
||||
end;
|
||||
|
||||
BUF_NUM_FORMAT_SNORM_NZ: //Signed, normalized to range [-1.0..1.0]; (data*2+1)/(1<<nbits-1)
|
||||
begin
|
||||
if (lc.info.GetElemSize=4) then
|
||||
begin
|
||||
Result:=OpSToF(src);
|
||||
Result:=OpMulF(Result,2);
|
||||
Result:=OpAddF(Result,1);
|
||||
Result:=OpMulF(Result,1/GetTypeHigh(lc.elem_orig));
|
||||
end else
|
||||
begin
|
||||
Result:=OpShlI(src,1);
|
||||
Result:=OpAddI(Result,1);
|
||||
Result:=OpSToF(Result);
|
||||
Result:=OpMulF(Result,1/GetTypeHigh(lc.elem_orig));
|
||||
end;
|
||||
end;
|
||||
|
||||
BUF_NUM_FORMAT_UINT :
|
||||
begin
|
||||
Result:=NewReg(lc.elem_resl);
|
||||
src^.mark_read;
|
||||
_emit_Op1(line,Op.OpUConvert,Result,src);
|
||||
end;
|
||||
|
||||
BUF_NUM_FORMAT_SINT :
|
||||
begin
|
||||
Result:=NewReg(lc.elem_resl);
|
||||
src^.mark_read;
|
||||
_emit_Op1(line,Op.OpSConvert,Result,src);
|
||||
end;
|
||||
|
||||
BUF_NUM_FORMAT_FLOAT :
|
||||
begin
|
||||
Result:=NewReg(lc.elem_resl);
|
||||
src^.mark_read;
|
||||
_emit_Op1(line,Op.OpFConvert,Result,src);
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_load._make_load_cv_id(var lc:Tload_cache;i:Byte);
|
||||
var
|
||||
rsl:PsrRegNode;
|
||||
begin
|
||||
rsl:=lc.rsl;
|
||||
if (rsl=nil) then
|
||||
begin
|
||||
rsl:=FetchLoad(lc.v.data[0],GetVecType(lc.elem_orig,lc.elem_count));
|
||||
lc.rsl:=rsl;
|
||||
end;
|
||||
|
||||
if (lc.elm[i]=nil) then
|
||||
begin
|
||||
|
||||
if (lc.elem_count=1) then
|
||||
begin
|
||||
rsl:=_convert_e(lc,rsl);
|
||||
|
||||
lc.elm[i]:=rsl;
|
||||
end else
|
||||
begin
|
||||
lc.elm[i]:=NewReg(lc.elem_orig);
|
||||
|
||||
rsl^.mark_read;
|
||||
emit_OpCompExtract(line,lc.elm[i],rsl,i);
|
||||
|
||||
lc.elm[i]:=_convert_e(lc,lc.elm[i]);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
MakeCopy(lc.dst,lc.elm[i]);
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_load._make_load_ce_id(var lc:Tload_cache;i:Byte);
|
||||
var
|
||||
orig,elm:PsrChain;
|
||||
sum_d:PsrRegNode;
|
||||
ext:TsrChainExt;
|
||||
rsl:PsrRegNode;
|
||||
begin
|
||||
|
||||
if (lc.elm[i]=nil) then
|
||||
begin
|
||||
orig:=lc.v.data[0];
|
||||
sum_d:=orig^.key.ext.pIndex;
|
||||
|
||||
if (i=0) then
|
||||
begin
|
||||
elm:=orig;
|
||||
end else
|
||||
begin
|
||||
sum_d:=TEmit_vbuf_chain(Self).OpAddTo(sum_d,i);
|
||||
|
||||
sum_d^.mark_read;
|
||||
ext:=Default(TsrChainExt);
|
||||
ext.pIndex:=sum_d;
|
||||
ext.stride:=orig^.key.ext.stride;
|
||||
|
||||
elm:=lc.info.grp^.Fetch(0,orig^.key.size,@ext);
|
||||
end;
|
||||
|
||||
rsl:=FetchLoad(elm,lc.elem_orig);
|
||||
|
||||
rsl:=_convert_e(lc,rsl);
|
||||
|
||||
lc.elm[i]:=rsl;
|
||||
end;
|
||||
|
||||
MakeCopy(lc.dst,lc.elm[i]);
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_load._make_load_uv_id(var lc:Tload_cache;i:Byte);
|
||||
var
|
||||
rsl,idx:PsrRegNode;
|
||||
begin
|
||||
|
||||
rsl:=lc.rsl;
|
||||
if (rsl=nil) then
|
||||
begin
|
||||
rsl:=NewReg(GetVecType(lc.elem_resl,4));
|
||||
idx:=lc.v.data[1];
|
||||
|
||||
idx^.mark_read;
|
||||
emit_OpImageRead(line,lc.v.data[0],rsl,idx);
|
||||
|
||||
lc.rsl:=rsl;
|
||||
end;
|
||||
|
||||
if (lc.elm[i]=nil) then
|
||||
begin
|
||||
rsl^.mark_read;
|
||||
lc.dst^.New(line,lc.elem_resl);
|
||||
emit_OpCompExtract(line,lc.dst^.current,rsl,i);
|
||||
|
||||
lc.elm[i]:=lc.dst^.current;
|
||||
end else
|
||||
begin
|
||||
MakeCopy(lc.dst,lc.elm[i]);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_load._make_load_ue_id(var lc:Tload_cache;i:Byte);
|
||||
var
|
||||
rsl,idx,sum_d:PsrRegNode;
|
||||
begin
|
||||
|
||||
if (lc.elm[i]=nil) then
|
||||
begin
|
||||
idx:=lc.v.data[1];
|
||||
|
||||
if (i=0) then
|
||||
begin
|
||||
sum_d:=idx;
|
||||
end else
|
||||
begin
|
||||
sum_d:=TEmit_vbuf_chain(Self).OpAddTo(idx,i);
|
||||
end;
|
||||
|
||||
rsl:=lc.dst^.New(line,lc.elem_resl);
|
||||
|
||||
sum_d^.mark_read;
|
||||
emit_OpImageRead(line,lc.v.data[0],rsl,sum_d);
|
||||
|
||||
lc.elm[i]:=rsl;
|
||||
end else
|
||||
begin
|
||||
MakeCopy(lc.dst,lc.elm[i]);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_load._make_load_zero(var lc:Tload_cache);
|
||||
begin
|
||||
SetConst(lc.dst,FConsts.Fetchi(lc.elem_resl,0));
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_load._make_load_one(var lc:Tload_cache);
|
||||
begin
|
||||
if (lc.elem_resl=dtFloat32) then
|
||||
begin
|
||||
SetConst(lc.dst,FConsts.Fetchf(lc.elem_resl,1));
|
||||
end else
|
||||
begin
|
||||
SetConst(lc.dst,FConsts.Fetchi(lc.elem_resl,1));
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_load.buf_load_cv(info:TBuf_info;v:TvarChain);
|
||||
var
|
||||
lc:Tload_cache;
|
||||
|
||||
i,d,count:Byte;
|
||||
begin
|
||||
|
||||
if info.IsExtFormat then Assert(false,'TODO');
|
||||
|
||||
lc:=Default(Tload_cache);
|
||||
lc.info :=info;
|
||||
lc.v :=v;
|
||||
lc.elem_resl :=info.GetResultType;
|
||||
lc.elem_orig :=info.GetElemType;
|
||||
lc.elem_count:=info.GetElemCount;
|
||||
|
||||
count:=info.count;
|
||||
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
lc.dst:=FRegsStory.get_vdst8(FSPI.MUBUF.VDATA+i);
|
||||
if (lc.dst=nil) then Assert(false);
|
||||
|
||||
//0=0, 1=1, 4=R, 5=G, 6=B, 7=A
|
||||
Case info.dsel[i] of
|
||||
0:begin //0
|
||||
_make_load_zero(lc);
|
||||
end;
|
||||
1:begin //1
|
||||
_make_load_one(lc);
|
||||
end;
|
||||
4..7:
|
||||
begin //RGBA
|
||||
d:=info.dsel[i]-4;
|
||||
|
||||
if (d<lc.elem_count) then
|
||||
begin
|
||||
|
||||
Case v.vType of
|
||||
vcInvalid :_make_load_zero(lc);
|
||||
vcChainVector :_make_load_cv_id(lc,d);
|
||||
vcChainElement :_make_load_ce_id(lc,d);
|
||||
vcUniformVector :_make_load_uv_id(lc,d);
|
||||
vcUniformElement:_make_load_ue_id(lc,d);
|
||||
end;
|
||||
|
||||
end else
|
||||
begin //as zero
|
||||
_make_load_zero(lc);
|
||||
end;
|
||||
|
||||
end;
|
||||
else
|
||||
begin //as zero
|
||||
_make_load_zero(lc);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
290
spirv/emit_vbuf_store.pas
Normal file
290
spirv/emit_vbuf_store.pas
Normal file
@ -0,0 +1,290 @@
|
||||
unit emit_vbuf_store;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
srLayout,
|
||||
SprvEmit,
|
||||
emit_op,
|
||||
srVBufInfo,
|
||||
emit_vbuf_chain;
|
||||
|
||||
type
|
||||
Tstore_cache=record
|
||||
info:TBuf_info;
|
||||
v:TvarChain;
|
||||
elem_orig:TsrDataType;
|
||||
elem_resl:TsrDataType;
|
||||
elem_count:ptruint;
|
||||
elm:array[0..3] of PsrRegNode;
|
||||
end;
|
||||
|
||||
TEmit_vbuf_store=object(TEmitOp)
|
||||
procedure buf_store(info:TBuf_info);
|
||||
function _fetch_id(var lc:Tstore_cache;i:Byte):PsrRegNode;
|
||||
function _fetch_zero(var lc:Tstore_cache):PsrRegNode;
|
||||
function _fetch_one(var lc:Tstore_cache):PsrRegNode;
|
||||
procedure _make_store_cv(var lc:Tstore_cache);
|
||||
procedure _make_store_ce(var lc:Tstore_cache);
|
||||
procedure _make_store_uv(var lc:Tstore_cache);
|
||||
procedure _make_store_ue(var lc:Tstore_cache);
|
||||
procedure buf_store_cv(info:TBuf_info;v:TvarChain);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_vbuf_store.buf_store(info:TBuf_info);
|
||||
var
|
||||
v:TvarChain;
|
||||
begin
|
||||
v:=TEmit_vbuf_chain(Self).get_chain(info);
|
||||
|
||||
if (v.vType=vcUniformVector) then
|
||||
begin
|
||||
//reset dst sel
|
||||
info.dsel:=dst_sel_identity;
|
||||
end else
|
||||
begin
|
||||
info.dsel:=get_reverse_dst_sel(info.dsel);
|
||||
end;
|
||||
|
||||
buf_store_cv(info,v);
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_store._fetch_id(var lc:Tstore_cache;i:Byte):PsrRegNode;
|
||||
begin
|
||||
Result:=fetch_vdst8(FSPI.MUBUF.VDATA+i,lc.elem_resl);
|
||||
if (Result=nil) then Assert(false);
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_store._fetch_zero(var lc:Tstore_cache):PsrRegNode;
|
||||
begin
|
||||
Result:=FetchReg(FConsts.Fetchi(lc.elem_resl,0));
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_store._fetch_one(var lc:Tstore_cache):PsrRegNode;
|
||||
begin
|
||||
if (lc.elem_resl=dtFloat32) then
|
||||
begin
|
||||
Result:=FetchReg(FConsts.Fetchf(lc.elem_resl,1));
|
||||
end else
|
||||
begin
|
||||
Result:=FetchReg(FConsts.Fetchi(lc.elem_resl,1));
|
||||
end;
|
||||
end;
|
||||
|
||||
function Min(a,b:PtrUInt):PtrUInt; inline;
|
||||
begin
|
||||
if (a<b) then Result:=a else Result:=b;
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_store._make_store_cv(var lc:Tstore_cache);
|
||||
var
|
||||
rsl:PsrRegNode;
|
||||
i:Byte;
|
||||
csize:PtrUInt;
|
||||
orig,new:PsrChain;
|
||||
idx:PsrRegNode;
|
||||
ext:TsrChainExt;
|
||||
begin
|
||||
|
||||
For i:=0 to lc.elem_count-1 do //fill
|
||||
if (lc.elm[i]=nil) then
|
||||
begin
|
||||
Case lc.info.dsel[i] of
|
||||
1:lc.elm[i]:=_fetch_one(lc);
|
||||
else
|
||||
lc.elm[i]:=_fetch_zero(lc);
|
||||
end;
|
||||
end;
|
||||
|
||||
Case lc.elem_count of
|
||||
1:rsl:=lc.elm[0];
|
||||
else
|
||||
begin
|
||||
rsl:=emit_OpMakeVec(line,GetVecType(lc.elem_resl,lc.elem_count),lc.elem_count,@lc.elm);
|
||||
rsl^.mark_read;
|
||||
end;
|
||||
end;
|
||||
|
||||
Assert(lc.elem_resl=lc.elem_orig,'TODO CONVERT');
|
||||
|
||||
csize:=Min(lc.info.GetElemSize*lc.elem_count,lc.info.GetSizeFormat);
|
||||
orig:=lc.v.data[0];
|
||||
|
||||
if (orig^.key.size<>csize) then //refetch
|
||||
begin
|
||||
idx:=orig^.key.ext.pIndex;
|
||||
if (idx<>nil) then
|
||||
begin
|
||||
idx^.mark_read;
|
||||
ext:=Default(TsrChainExt);
|
||||
ext.pIndex:=idx;
|
||||
ext.stride:=orig^.key.ext.stride;
|
||||
new:=lc.info.grp^.Fetch(orig^.key.offset,csize,@ext);
|
||||
end else
|
||||
begin
|
||||
new:=lc.info.grp^.Fetch(orig^.key.offset,csize,nil);
|
||||
end;
|
||||
orig:=new;
|
||||
end;
|
||||
|
||||
FetchStore(orig,rsl);
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_store._make_store_ce(var lc:Tstore_cache);
|
||||
var
|
||||
orig,elm:PsrChain;
|
||||
sum_d:PsrRegNode;
|
||||
ext:TsrChainExt;
|
||||
i:Byte;
|
||||
begin
|
||||
orig:=lc.v.data[0];
|
||||
sum_d:=orig^.key.ext.pIndex;
|
||||
|
||||
For i:=0 to lc.elem_count-1 do
|
||||
if (lc.elm[i]<>nil) then
|
||||
begin
|
||||
|
||||
if (i=0) then
|
||||
begin
|
||||
elm:=orig;
|
||||
end else
|
||||
begin
|
||||
sum_d:=TEmit_vbuf_chain(Self).OpAddTo(sum_d,i);
|
||||
|
||||
sum_d^.mark_read;
|
||||
ext:=Default(TsrChainExt);
|
||||
ext.pIndex:=sum_d;
|
||||
ext.stride:=orig^.key.ext.stride;
|
||||
|
||||
elm:=lc.info.grp^.Fetch(0,orig^.key.size,@ext);
|
||||
end;
|
||||
|
||||
Assert(lc.elem_resl=lc.elem_orig,'TODO CONVERT');
|
||||
|
||||
FetchStore(elm,lc.elm[i]);
|
||||
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_store._make_store_uv(var lc:Tstore_cache);
|
||||
var
|
||||
rsl,idx:PsrRegNode;
|
||||
i:Byte;
|
||||
begin
|
||||
|
||||
For i:=0 to lc.elem_count-1 do //fill
|
||||
if (lc.elm[i]=nil) then
|
||||
begin
|
||||
Case lc.info.dsel[i] of
|
||||
1:lc.elm[i]:=_fetch_one(lc);
|
||||
else
|
||||
lc.elm[i]:=_fetch_zero(lc);
|
||||
end;
|
||||
end;
|
||||
|
||||
Case lc.elem_count of
|
||||
1:rsl:=lc.elm[0];
|
||||
else
|
||||
begin
|
||||
rsl:=emit_OpMakeVec(line,GetVecType(lc.elem_resl,lc.elem_count),lc.elem_count,@lc.elm);
|
||||
rsl^.mark_read;
|
||||
end;
|
||||
end;
|
||||
|
||||
idx:=lc.v.data[1];
|
||||
idx^.mark_read;
|
||||
rsl^.mark_read;
|
||||
emit_OpImageWrite(line,lc.v.data[0],idx,rsl);
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_store._make_store_ue(var lc:Tstore_cache);
|
||||
var
|
||||
sum_d,idx,rsl:PsrRegNode;
|
||||
i:Byte;
|
||||
begin
|
||||
idx:=lc.v.data[1];
|
||||
|
||||
For i:=0 to lc.elem_count-1 do
|
||||
if (lc.elm[i]<>nil) then
|
||||
begin
|
||||
rsl:=lc.elm[i];
|
||||
|
||||
if (i=0) then
|
||||
begin
|
||||
sum_d:=idx;
|
||||
end else
|
||||
begin
|
||||
sum_d:=TEmit_vbuf_chain(Self).OpAddTo(idx,i);
|
||||
end;
|
||||
|
||||
sum_d^.mark_read;
|
||||
rsl^.mark_read;
|
||||
emit_OpImageWrite(line,lc.v.data[0],sum_d,rsl);
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_store.buf_store_cv(info:TBuf_info;v:TvarChain);
|
||||
var
|
||||
lc:Tstore_cache;
|
||||
|
||||
i:Byte;
|
||||
begin
|
||||
|
||||
Case v.vType of
|
||||
vcInvalid:Exit;
|
||||
else;
|
||||
end;
|
||||
|
||||
if info.IsExtFormat then Assert(false,'TODO');
|
||||
|
||||
lc:=Default(Tstore_cache);
|
||||
lc.info :=info;
|
||||
lc.v :=v;
|
||||
lc.elem_resl :=info.GetResultType;
|
||||
lc.elem_orig :=info.GetElemType;
|
||||
lc.elem_count:=info.GetElemCount;
|
||||
|
||||
For i:=0 to lc.elem_count-1 do
|
||||
begin
|
||||
lc.elm[i]:=nil;
|
||||
Case lc.info.dsel[i] of
|
||||
4..7:
|
||||
begin //RGBA
|
||||
lc.elm[i]:=_fetch_id(lc,lc.info.dsel[i]-4);
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
While (lc.elem_count<>0) do //trim count
|
||||
begin
|
||||
i:=lc.elem_count-1;
|
||||
if (lc.elm[i]<>nil) then Break;
|
||||
Dec(lc.elem_count);
|
||||
end;
|
||||
|
||||
if (lc.elem_count=0) then Exit;
|
||||
|
||||
Case v.vType of
|
||||
vcChainVector :_make_store_cv(lc);
|
||||
vcChainElement :_make_store_ce(lc);
|
||||
vcUniformVector :_make_store_uv(lc);
|
||||
vcUniformElement:_make_store_ue(lc)
|
||||
else;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
110
spirv/emit_vintrp.pas
Normal file
110
spirv/emit_vintrp.pas
Normal file
@ -0,0 +1,110 @@
|
||||
unit emit_VINTRP;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srInput,
|
||||
srReg,
|
||||
spirv,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_VINTRP=object(TEmitOp)
|
||||
procedure _emit_VINTRP;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_VINTRP._emit_VINTRP;
|
||||
var
|
||||
inp_M0:PsrInput;
|
||||
|
||||
src:PsrRegSlot;
|
||||
dst:PsrRegSlot;
|
||||
|
||||
inp_SRC:PsrInput;
|
||||
|
||||
rsl:PsrRegNode;
|
||||
|
||||
begin
|
||||
Assert(FExecutionModel=ExecutionModel.Fragment); //only pixel shader
|
||||
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VINTRP.VDST);
|
||||
|
||||
inp_M0:=GetInputRegNode(FRegsStory.M0.current);
|
||||
|
||||
Assert(inp_M0<>nil);
|
||||
Assert(inp_M0^.key.itype=itPsState);
|
||||
|
||||
Case FSPI.VINTRP.OP of
|
||||
V_INTERP_P1_F32:
|
||||
begin
|
||||
src:=FRegsStory.get_vsrc8(FSPI.VINTRP.VSRC);
|
||||
|
||||
inp_SRC:=GetInputRegNode(src^.current);
|
||||
|
||||
Assert(inp_SRC<>nil);
|
||||
|
||||
Case inp_SRC^.key.itype of
|
||||
itPerspSample,
|
||||
itPerspCenter, //barycentrics with perspective interpolation
|
||||
itPerspCentroid,
|
||||
itLinearSample,
|
||||
itLinearCenter,
|
||||
itLinearCentroid:;
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
Assert(inp_SRC^.key.typeid=0); //I
|
||||
|
||||
rsl:=AddFragLayout(inp_SRC^.key.itype,dtVec4f,FSPI.VINTRP.ATTR);
|
||||
rsl^.mark_read;
|
||||
|
||||
dst^.New(line,dtFloat32);
|
||||
emit_OpCompExtract(line,dst^.current,rsl,FSPI.VINTRP.ATTRCHAN);
|
||||
|
||||
end;
|
||||
V_INTERP_P2_F32:
|
||||
begin
|
||||
src:=FRegsStory.get_vsrc8(FSPI.VINTRP.VSRC);
|
||||
|
||||
inp_SRC:=GetInputRegNode(src^.current);
|
||||
|
||||
Assert(inp_SRC<>nil);
|
||||
|
||||
Case inp_SRC^.key.itype of
|
||||
itPerspSample,
|
||||
itPerspCenter, //barycentrics with perspective interpolation
|
||||
itPerspCentroid,
|
||||
itLinearSample,
|
||||
itLinearCenter,
|
||||
itLinearCentroid:;
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
Assert(inp_SRC^.key.typeid=1); //J
|
||||
|
||||
rsl:=AddFragLayout(inp_SRC^.key.itype,dtVec4f,FSPI.VINTRP.ATTR);
|
||||
rsl^.mark_read;
|
||||
|
||||
dst^.New(line,dtFloat32);
|
||||
emit_OpCompExtract(line,dst^.current,rsl,FSPI.VINTRP.ATTRCHAN);
|
||||
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(False,'VINTRP?'+IntToStr(FSPI.VINTRP.OP));
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
273
spirv/emit_vop1.pas
Normal file
273
spirv/emit_vop1.pas
Normal file
@ -0,0 +1,273 @@
|
||||
unit emit_VOP1;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srReg,
|
||||
spirv,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_VOP1=object(TEmitOp)
|
||||
procedure _emit_VOP1;
|
||||
procedure _emit_V_MOV_B32;
|
||||
procedure _emit_V_CVT_F32_I32;
|
||||
procedure _emit_V_CVT_U32_F32;
|
||||
procedure _emit_V_CVT_I32_F32;
|
||||
procedure _emit_V_CVT_F32_U32;
|
||||
procedure _emit_V_CVT_OFF_F32_I4;
|
||||
procedure _emit_V_SQRT_F32;
|
||||
procedure _emit_V_RSQ_F32;
|
||||
procedure _emit_V_FLOOR_F32;
|
||||
procedure _emit_V_FRACT_F32;
|
||||
procedure _emit_V_EXP_F32;
|
||||
procedure _emit_V_RCP_F32;
|
||||
procedure _emit_V_SIN_F32;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_VOP1._emit_V_MOV_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUnknow);
|
||||
_MakeCopy(dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_CVT_F32_I32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtInt32);
|
||||
emit_Op1(Op.OpConvertSToF,dtFloat32,dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_CVT_I32_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32);
|
||||
emit_Op1(Op.OpConvertFToS,dtInt32,dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_CVT_U32_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32);
|
||||
emit_Op1(Op.OpConvertFToU,dtUInt32,dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_CVT_F32_U32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUInt32);
|
||||
emit_Op1(Op.OpConvertUToF,dtFloat32,dst,src);
|
||||
end;
|
||||
|
||||
//V_CVT_OFF_F32_I4
|
||||
//([0..3]-8)/16
|
||||
procedure TEmit_VOP1._emit_V_CVT_OFF_F32_I4;
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
num_8:PsrRegNode;
|
||||
num_15:PsrRegNode;
|
||||
num_16:PsrRegNode;
|
||||
subi,subf:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUInt32);
|
||||
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
num_15:=FetchReg(FConsts.Fetch(dtUInt32,15));
|
||||
|
||||
emit_OpBitwiseAnd(tmp,src,num_15);
|
||||
src:=MakeRead(tmp,dtUInt32);
|
||||
|
||||
num_8:=FetchReg(FConsts.Fetch(dtInt32,8));
|
||||
subi:=dst^.New(line,dtInt32);
|
||||
|
||||
_emit_OpISub(line,subi,src,num_8);
|
||||
|
||||
subi^.mark_read;
|
||||
subf:=dst^.New(line,dtFloat32);
|
||||
|
||||
_emit_Op1(line,Op.OpConvertSToF,subf,subi);
|
||||
|
||||
subf^.mark_read;
|
||||
num_16:=FetchReg(FConsts.Fetchf(dtFloat32,16));
|
||||
|
||||
emit_OpFDiv(dst,subf,num_16);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_SQRT_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32);
|
||||
emit_OpSqrt(dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_RSQ_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32);
|
||||
emit_OpInverseSqrt(dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_FLOOR_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32);
|
||||
emit_OpFloor(dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_FRACT_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32);
|
||||
emit_OpFract(dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_EXP_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32);
|
||||
emit_OpExp2(dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_RCP_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
one:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32);
|
||||
|
||||
one:=FetchReg(FConsts.Fetchf(dtFloat32,1));
|
||||
|
||||
emit_OpFDiv(dst,one,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_SIN_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32);
|
||||
emit_OpSin(dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_VOP1;
|
||||
begin
|
||||
|
||||
Case FSPI.VOP1.OP of
|
||||
|
||||
V_MOV_B32:
|
||||
begin
|
||||
_emit_V_MOV_B32;
|
||||
end;
|
||||
|
||||
V_CVT_F32_I32:
|
||||
begin
|
||||
_emit_V_CVT_F32_I32;
|
||||
end;
|
||||
|
||||
V_CVT_I32_F32:
|
||||
begin
|
||||
_emit_V_CVT_I32_F32;
|
||||
end;
|
||||
|
||||
V_CVT_U32_F32:
|
||||
begin
|
||||
_emit_V_CVT_U32_F32;
|
||||
end;
|
||||
|
||||
V_CVT_F32_U32:
|
||||
begin
|
||||
_emit_V_CVT_F32_U32;
|
||||
end;
|
||||
|
||||
V_CVT_OFF_F32_I4:
|
||||
begin
|
||||
_emit_V_CVT_OFF_F32_I4;
|
||||
end;
|
||||
|
||||
V_SQRT_F32:
|
||||
begin
|
||||
_emit_V_SQRT_F32;
|
||||
end;
|
||||
|
||||
V_RSQ_F32:
|
||||
begin
|
||||
_emit_V_RSQ_F32;
|
||||
end;
|
||||
|
||||
V_FLOOR_F32:
|
||||
begin
|
||||
_emit_V_FLOOR_F32;
|
||||
end;
|
||||
|
||||
V_FRACT_F32:
|
||||
begin
|
||||
_emit_V_FRACT_F32;
|
||||
end;
|
||||
|
||||
V_EXP_F32:
|
||||
begin
|
||||
_emit_V_EXP_F32;
|
||||
end;
|
||||
|
||||
V_RCP_F32:
|
||||
begin
|
||||
_emit_V_RCP_F32;
|
||||
end;
|
||||
|
||||
V_SIN_F32:
|
||||
begin
|
||||
_emit_V_SIN_F32;
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(false,'VOP1?'+IntToStr(FSPI.VOP1.OP));
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
511
spirv/emit_vop2.pas
Normal file
511
spirv/emit_vop2.pas
Normal file
@ -0,0 +1,511 @@
|
||||
unit emit_VOP2;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_VOP2=object(TEmitOp)
|
||||
procedure _emit_VOP2;
|
||||
procedure _emit_V_CNDMASK_B32;
|
||||
procedure _emit_V_AND_B32;
|
||||
procedure _emit_V_OR_B32;
|
||||
procedure _emit_V_LSHL_B32;
|
||||
procedure _emit_V_LSHLREV_B32;
|
||||
procedure _emit_V_LSHR_B32;
|
||||
procedure _emit_V_LSHRREV_B32;
|
||||
procedure _emit_V_ASHR_I32;
|
||||
procedure _emit_V_ASHRREV_I32;
|
||||
procedure _emit_V_ADD_I32;
|
||||
procedure _emit_V_SUB_I32;
|
||||
procedure _emit_V_SUBREV_I32;
|
||||
procedure _emit_V_ADD_F32;
|
||||
procedure _emit_V_SUB_F32;
|
||||
procedure _emit_V_SUBREV_F32;
|
||||
procedure _emit_V_MUL_F32;
|
||||
procedure _emit_V_CVT_PKRTZ_F16_F32;
|
||||
procedure _emit_V_MAC_F32;
|
||||
procedure _emit_V_MADAK_F32;
|
||||
procedure _emit_V_MADMK_F32;
|
||||
procedure _emit_V_MIN_F32;
|
||||
procedure _emit_V_MAX_F32;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_VOP2._emit_V_CNDMASK_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUnknow);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUnknow);
|
||||
src[2]:=MakeRead(@FRegsStory.VCC[0],dtBool);
|
||||
|
||||
emit_OpSelect(dst,src[0],src[1],src[2]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_AND_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUnknow);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUnknow);
|
||||
|
||||
emit_OpBitwiseAnd(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_OR_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUnknow);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUnknow);
|
||||
|
||||
emit_OpBitwiseOr(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_LSHL_B32;
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32);
|
||||
|
||||
src[2]:=FetchReg(FConsts.Fetch(dtUInt32,31));
|
||||
emit_OpBitwiseAnd(tmp,src[1],src[2]);
|
||||
src[1]:=MakeRead(tmp,dtUInt32);
|
||||
|
||||
emit_OpShl(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_LSHLREV_B32;
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32);
|
||||
|
||||
src[2]:=FetchReg(FConsts.Fetch(dtUInt32,31));
|
||||
emit_OpBitwiseAnd(tmp,src[0],src[2]);
|
||||
src[0]:=MakeRead(tmp,dtUInt32);
|
||||
|
||||
emit_OpShl(dst,src[1],src[0]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_LSHR_B32;
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32);
|
||||
|
||||
src[2]:=FetchReg(FConsts.Fetch(dtUInt32,31));
|
||||
emit_OpBitwiseAnd(tmp,src[1],src[2]);
|
||||
src[1]:=MakeRead(tmp,dtUInt32);
|
||||
|
||||
emit_OpShr(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_LSHRREV_B32;
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32);
|
||||
|
||||
src[2]:=FetchReg(FConsts.Fetch(dtUInt32,31));
|
||||
emit_OpBitwiseAnd(tmp,src[0],src[2]);
|
||||
src[0]:=MakeRead(tmp,dtUInt32);
|
||||
|
||||
emit_OpShr(dst,src[1],src[0]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_ASHR_I32;
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtInt32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32);
|
||||
|
||||
src[2]:=FetchReg(FConsts.Fetch(dtInt32,31));
|
||||
emit_OpBitwiseAnd(tmp,src[1],src[2]);
|
||||
src[1]:=MakeRead(tmp,dtInt32);
|
||||
|
||||
emit_OpShrA(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_ASHRREV_I32;
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtInt32);
|
||||
|
||||
src[2]:=FetchReg(FConsts.Fetch(dtInt32,31));
|
||||
emit_OpBitwiseAnd(tmp,src[0],src[2]);
|
||||
src[0]:=MakeRead(tmp,dtInt32);
|
||||
|
||||
emit_OpShrA(dst,src[1],src[0]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_ADD_I32; //vdst = vsrc0.s + vsrc1.s; sdst[thread_id:] = carry_out & EXEC
|
||||
Var
|
||||
dst,car:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
exc,tmp:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
car:=@FRegsStory.VCC[0];
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32);
|
||||
|
||||
emit_OpIAddExt(dst,@FRegsStory.FUnattach,src[0],src[1]);
|
||||
|
||||
tmp:=FRegsStory.FUnattach.current;
|
||||
tmp^.mark_read;
|
||||
exc:=MakeRead(@FRegsStory.EXEC[0],dtUnknow);
|
||||
emit_OpBitwiseAnd(car,tmp,exc);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_SUB_I32; //vdst = vsrc0.u - vsub.u; sdst[thread_id:] = borrow_out & EXEC
|
||||
Var
|
||||
dst,car:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
exc,tmp:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
car:=@FRegsStory.VCC[0];
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32);
|
||||
|
||||
emit_OpISubExt(dst,@FRegsStory.FUnattach,src[0],src[1]);
|
||||
|
||||
tmp:=FRegsStory.FUnattach.current;
|
||||
tmp^.mark_read;
|
||||
exc:=MakeRead(@FRegsStory.EXEC[0],dtUnknow);
|
||||
emit_OpBitwiseAnd(car,tmp,exc);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_SUBREV_I32; //vdst = vsrc1.u - vsub.u; sdst[thread_id:] = borrow_out & EXEC
|
||||
Var
|
||||
dst,car:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
exc,tmp:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
car:=@FRegsStory.VCC[0];
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32);
|
||||
|
||||
emit_OpISubExt(dst,@FRegsStory.FUnattach,src[1],src[0]);
|
||||
|
||||
tmp:=FRegsStory.FUnattach.current;
|
||||
tmp^.mark_read;
|
||||
exc:=MakeRead(@FRegsStory.EXEC[0],dtUnknow);
|
||||
emit_OpBitwiseAnd(car,tmp,exc);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_ADD_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
|
||||
emit_OpFAdd(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_SUB_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
|
||||
emit_OpFSub(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_SUBREV_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
|
||||
emit_OpFSub(dst,src[1],src[0]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_MUL_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
|
||||
emit_OpFMul(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_CVT_PKRTZ_F16_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
_emit_ConvFloatToHalf(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_MAC_F32; //vdst = vsrc0.f * vsrc1.f + vdst.f -> fma
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
src[2]:=MakeRead(dst,dtFloat32);
|
||||
|
||||
emit_OpFmaF32(dst,src[0],src[1],src[2]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_MADAK_F32; //vdst = vsrc0.f * vsrc1.f + kadd.f
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
src[2]:=FetchReg(FConsts.Fetch(dtFloat32,FSPI.INLINE32));
|
||||
|
||||
emit_OpFmaF32(dst,src[0],src[1],src[2]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_MADMK_F32; //vdst = vsrc0.f * kmul.f + vadd.f
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=FetchReg(FConsts.Fetch(dtFloat32,FSPI.INLINE32));
|
||||
src[2]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
|
||||
emit_OpFmaF32(dst,src[0],src[1],src[2]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_MIN_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
|
||||
emit_OpFMin(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_MAX_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
|
||||
emit_OpFMax(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_VOP2;
|
||||
begin
|
||||
|
||||
Case FSPI.VOP2.OP of
|
||||
|
||||
V_CNDMASK_B32:
|
||||
begin
|
||||
_emit_V_CNDMASK_B32;
|
||||
end;
|
||||
|
||||
V_AND_B32:
|
||||
begin
|
||||
_emit_V_AND_B32;
|
||||
end;
|
||||
|
||||
V_OR_B32:
|
||||
begin
|
||||
_emit_V_OR_B32;
|
||||
end;
|
||||
|
||||
V_LSHL_B32:
|
||||
begin
|
||||
_emit_V_LSHL_B32;
|
||||
end;
|
||||
|
||||
V_LSHLREV_B32:
|
||||
begin
|
||||
_emit_V_LSHLREV_B32;
|
||||
end;
|
||||
|
||||
V_LSHR_B32:
|
||||
begin
|
||||
_emit_V_LSHR_B32;
|
||||
end;
|
||||
|
||||
V_LSHRREV_B32:
|
||||
begin
|
||||
_emit_V_LSHRREV_B32
|
||||
end;
|
||||
|
||||
V_ASHR_I32:
|
||||
begin
|
||||
_emit_V_ASHR_I32;
|
||||
end;
|
||||
|
||||
V_ASHRREV_I32:
|
||||
begin
|
||||
_emit_V_ASHRREV_I32
|
||||
end;
|
||||
|
||||
V_ADD_I32: //vdst = vsrc0.s + vsrc1.s; sdst[thread_id:] = carry_out & EXEC
|
||||
begin
|
||||
// Vector ALU (except v_readlane, v_readfirstlane, v_writelane),
|
||||
// Vector Memory,
|
||||
// Local and Global Data Share
|
||||
// and Export.
|
||||
_emit_V_ADD_I32;
|
||||
end;
|
||||
|
||||
V_SUB_I32:
|
||||
begin
|
||||
_emit_V_SUB_I32;
|
||||
end;
|
||||
|
||||
V_SUBREV_I32:
|
||||
begin
|
||||
_emit_V_SUBREV_I32;
|
||||
end;
|
||||
|
||||
V_ADD_F32:
|
||||
begin
|
||||
_emit_V_ADD_F32;
|
||||
end;
|
||||
|
||||
V_SUB_F32:
|
||||
begin
|
||||
_emit_V_SUB_F32;
|
||||
end;
|
||||
|
||||
V_SUBREV_F32:
|
||||
begin
|
||||
_emit_V_SUBREV_F32;
|
||||
end;
|
||||
|
||||
V_MUL_F32:
|
||||
begin
|
||||
_emit_V_MUL_F32;
|
||||
end;
|
||||
|
||||
V_CVT_PKRTZ_F16_F32:
|
||||
begin
|
||||
_emit_V_CVT_PKRTZ_F16_F32;
|
||||
end;
|
||||
|
||||
V_MAC_F32: //vdst = vsrc0.f * vsrc1.f + vdst.f -> fma
|
||||
begin
|
||||
_emit_V_MAC_F32;
|
||||
end;
|
||||
|
||||
V_MADAK_F32:
|
||||
begin
|
||||
_emit_V_MADAK_F32;
|
||||
end;
|
||||
|
||||
V_MADMK_F32:
|
||||
begin
|
||||
_emit_V_MADMK_F32;
|
||||
end;
|
||||
|
||||
V_MIN_F32:
|
||||
begin
|
||||
_emit_V_MIN_F32;
|
||||
end;
|
||||
|
||||
V_MAX_F32:
|
||||
begin
|
||||
_emit_V_MAX_F32;
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(false,'VOP2?'+IntToStr(FSPI.VOP2.OP));
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
995
spirv/emit_vop3.pas
Normal file
995
spirv/emit_vop3.pas
Normal file
@ -0,0 +1,995 @@
|
||||
unit emit_VOP3;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
spirv,
|
||||
srTypes,
|
||||
srReg,
|
||||
srOpUtils,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_VOP3=object(TEmitOp)
|
||||
procedure _emit_VOP3c;
|
||||
procedure _emit_VOP3b;
|
||||
procedure _emit_VOP3a;
|
||||
procedure _emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean);
|
||||
procedure _emit_V_CMP_C(r,x:Boolean);
|
||||
|
||||
procedure _emit_src_neg_bit(src:PPsrRegNode;count:Byte);
|
||||
procedure _emit_src_abs(src:PPsrRegNode);
|
||||
procedure _emit_src_abs_bit(src:PPsrRegNode;count:Byte);
|
||||
procedure _emit_dst_omod_f(dst:PsrRegSlot);
|
||||
procedure _emit_dst_clamp_f(dst:PsrRegSlot);
|
||||
|
||||
procedure _emit_V_CNDMASK_B32;
|
||||
procedure _emit_V_ADD_F32;
|
||||
procedure _emit_V_SUB_F32;
|
||||
procedure _emit_V_CVT_PKRTZ_F16_F32;
|
||||
procedure _emit_V_MIN_F32;
|
||||
procedure _emit_V_MAX_F32;
|
||||
procedure _emit_V_MUL_LO_I32;
|
||||
procedure _emit_V_MUL_F32;
|
||||
procedure _emit_V_MUL_I32_I24;
|
||||
procedure _emit_V_MAC_F32;
|
||||
|
||||
procedure _emit_V_BFE_U32;
|
||||
procedure _emit_V_MAD_F32;
|
||||
procedure _emit_V_MAD_I32_I24;
|
||||
procedure _emit_V_MAD_U32_U24;
|
||||
procedure _emit_V_SAD_U32;
|
||||
procedure _emit_V_MAX3_F32;
|
||||
procedure _emit_V_MIN3_F32;
|
||||
procedure _emit_V_MED3_F32;
|
||||
procedure _emit_V_FMA_F32;
|
||||
procedure _emit_V_CUBE(OpId:DWORD);
|
||||
procedure _emit_V_MOV_B32;
|
||||
procedure _emit_V_SQRT_F32;
|
||||
procedure _emit_V_RCP_F32;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_VOP3._emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean);
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst[0]:=FRegsStory.get_sdst7(FSPI.VOP3a.VDST+0);
|
||||
dst[1]:=FRegsStory.get_sdst7(FSPI.VOP3a.VDST+1);
|
||||
|
||||
Assert(dst[0]<>nil);
|
||||
Assert(dst[1]<>nil);
|
||||
|
||||
Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD');
|
||||
Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP');
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,rtype);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,rtype);
|
||||
|
||||
_emit_src_abs_bit(@src,2);
|
||||
_emit_src_neg_bit(@src,2);
|
||||
|
||||
emit_OpCmpV(OpId,dst[0],src[0],src[1]);
|
||||
|
||||
SetConst(dst[1],dtUnknow,0); //set zero
|
||||
|
||||
if x then
|
||||
begin
|
||||
MakeCopy(@FRegsStory.EXEC[0],dst[0]^.current);
|
||||
SetConst(@FRegsStory.EXEC[1],dtUnknow,0); //set zero
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_CMP_C(r,x:Boolean);
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
begin
|
||||
dst[0]:=FRegsStory.get_sdst7(FSPI.VOP3a.VDST+0);
|
||||
dst[1]:=FRegsStory.get_sdst7(FSPI.VOP3a.VDST+1);
|
||||
|
||||
Assert(dst[0]<>nil);
|
||||
Assert(dst[1]<>nil);
|
||||
|
||||
Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD');
|
||||
Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP');
|
||||
|
||||
SetConst(dst[0],dtBool,QWORD(r));
|
||||
SetConst(dst[1],dtUnknow,0); //set zero
|
||||
|
||||
if x then
|
||||
begin
|
||||
MakeCopy(@FRegsStory.EXEC[0],dst[0]^.current);
|
||||
SetConst(@FRegsStory.EXEC[1],dtUnknow,0); //set zero
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_src_neg_bit(src:PPsrRegNode;count:Byte);
|
||||
var
|
||||
i:Byte;
|
||||
dst:PsrRegNode;
|
||||
begin
|
||||
if (FSPI.VOP3a.NEG=0) then Exit;
|
||||
|
||||
For i:=0 to count-1 do
|
||||
if Byte(FSPI.VOP3a.NEG).TestBit(i) then
|
||||
begin
|
||||
dst:=NewReg(dtFloat32);
|
||||
dst^.mark_read;
|
||||
_emit_OpFNegate(line,dst,src[i]);
|
||||
src[i]:=dst;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_src_abs(src:PPsrRegNode);
|
||||
var
|
||||
dst:PsrRegNode;
|
||||
begin
|
||||
dst:=NewReg(dtFloat32);
|
||||
dst^.mark_read;
|
||||
_emit_OpFAbs(line,dst,src^);
|
||||
src^:=dst;
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_src_abs_bit(src:PPsrRegNode;count:Byte);
|
||||
var
|
||||
i:Byte;
|
||||
begin
|
||||
if (FSPI.VOP3a.ABS=0) then Exit;
|
||||
|
||||
For i:=0 to count-1 do
|
||||
if Byte(FSPI.VOP3a.ABS).TestBit(i) then
|
||||
begin
|
||||
_emit_src_abs(@src[i]);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_dst_omod_f(dst:PsrRegSlot);
|
||||
var
|
||||
src,tmp:PsrRegNode;
|
||||
begin
|
||||
|
||||
Case FSPI.VOP3a.OMOD of
|
||||
0:;
|
||||
1: // *2
|
||||
begin
|
||||
src:=dst^.current;
|
||||
src^.mark_read;
|
||||
tmp:=FetchReg(FConsts.Fetchf(dtFloat32,2));
|
||||
emit_OpFMul(dst,src,tmp);
|
||||
end;
|
||||
2: // *4
|
||||
begin
|
||||
src:=dst^.current;
|
||||
src^.mark_read;
|
||||
tmp:=FetchReg(FConsts.Fetchf(dtFloat32,4));
|
||||
emit_OpFMul(dst,src,tmp);
|
||||
end;
|
||||
3: // /2
|
||||
begin
|
||||
src:=dst^.current;
|
||||
src^.mark_read;
|
||||
tmp:=FetchReg(FConsts.Fetchf(dtFloat32,2));
|
||||
emit_OpFDiv(dst,src,tmp);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_dst_clamp_f(dst:PsrRegSlot);
|
||||
var
|
||||
src,min,max:PsrRegNode;
|
||||
begin
|
||||
if (FSPI.VOP3a.CLAMP=0) then Exit;
|
||||
|
||||
src:=dst^.current;
|
||||
src^.mark_read;
|
||||
min:=FetchReg(FConsts.Fetchf(dtFloat32,0));
|
||||
max:=FetchReg(FConsts.Fetchf(dtFloat32,1));
|
||||
|
||||
emit_OpFClamp(dst,src,min,max);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_CNDMASK_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD');
|
||||
Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP');
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtUnknow);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtUnknow);
|
||||
src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtBool);
|
||||
|
||||
_emit_src_abs_bit(@src,2);
|
||||
_emit_src_neg_bit(@src,2);
|
||||
|
||||
emit_OpSelect(dst,src[0],src[1],src[2]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_ADD_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,2);
|
||||
_emit_src_neg_bit(@src,2);
|
||||
|
||||
emit_OpFAdd(dst,src[0],src[1]);
|
||||
|
||||
_emit_dst_omod_f(dst);
|
||||
_emit_dst_clamp_f(dst);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_SUB_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,2);
|
||||
_emit_src_neg_bit(@src,2);
|
||||
|
||||
emit_OpFSub(dst,src[0],src[1]);
|
||||
|
||||
_emit_dst_omod_f(dst);
|
||||
_emit_dst_clamp_f(dst);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_CVT_PKRTZ_F16_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD');
|
||||
Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP');
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,2);
|
||||
_emit_src_neg_bit(@src,2);
|
||||
|
||||
_emit_ConvFloatToHalf(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_MIN_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,2);
|
||||
_emit_src_neg_bit(@src,2);
|
||||
|
||||
emit_OpFMin(dst,src[0],src[1]);
|
||||
|
||||
_emit_dst_omod_f(dst);
|
||||
_emit_dst_clamp_f(dst);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_MAX_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,2);
|
||||
_emit_src_neg_bit(@src,2);
|
||||
|
||||
emit_OpFMax(dst,src[0],src[1]);
|
||||
|
||||
_emit_dst_omod_f(dst);
|
||||
_emit_dst_clamp_f(dst);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_MUL_LO_I32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD');
|
||||
Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS');
|
||||
Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP');
|
||||
Assert(FSPI.VOP3a.NEG =0,'FSPI.VOP3a.NEG');
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtInt32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtInt32);
|
||||
|
||||
emit_OpIMul(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_MUL_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,2);
|
||||
_emit_src_neg_bit(@src,2);
|
||||
|
||||
emit_OpFMul(dst,src[0],src[1]);
|
||||
|
||||
_emit_dst_omod_f(dst);
|
||||
_emit_dst_clamp_f(dst);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_MUL_I32_I24;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD');
|
||||
Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS');
|
||||
Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP');
|
||||
Assert(FSPI.VOP3a.NEG =0,'FSPI.VOP3a.NEG');
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtInt32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtInt32);
|
||||
|
||||
//24bit mask TODO
|
||||
emit_OpIMul(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_MAC_F32; //vdst = vsrc0.f * vsrc1.f + vdst.f -> fma
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,3);
|
||||
_emit_src_neg_bit(@src,3);
|
||||
|
||||
emit_OpFmaF32(dst,src[0],src[1],src[2]);
|
||||
|
||||
_emit_dst_omod_f(dst);
|
||||
_emit_dst_clamp_f(dst);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_BFE_U32;
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
num_31:PsrRegNode;
|
||||
offset,count:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
|
||||
Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD');
|
||||
Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS');
|
||||
Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP');
|
||||
Assert(FSPI.VOP3a.NEG =0,'FSPI.VOP3a.NEG');
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtUint32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtUint32);
|
||||
src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtUint32);
|
||||
|
||||
num_31:=FetchReg(FConsts.Fetch(dtUInt32,31));
|
||||
|
||||
emit_OpBitwiseAnd(tmp,src[1],num_31);
|
||||
offset:=MakeRead(tmp,dtUInt32);
|
||||
|
||||
num_31^.mark_read;
|
||||
emit_OpBitwiseAnd(tmp,src[2],num_31);
|
||||
count:=MakeRead(tmp,dtUInt32);
|
||||
|
||||
emit_OpBfeU(dst,src[0],offset,count);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_MAD_F32; //vdst = vsrc0.f * vsrc1.f + vadd.f
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,3);
|
||||
_emit_src_neg_bit(@src,3);
|
||||
|
||||
emit_OpFmaF32(dst,src[0],src[1],src[2]);
|
||||
|
||||
_emit_dst_omod_f(dst);
|
||||
_emit_dst_clamp_f(dst);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_MAD_I32_I24;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD');
|
||||
Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS');
|
||||
Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP');
|
||||
Assert(FSPI.VOP3a.NEG =0,'FSPI.VOP3a.NEG');
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtInt32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtInt32);
|
||||
src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtInt32);
|
||||
|
||||
emit_OpFmaI32(dst,src[0],src[1],src[2]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_MAD_U32_U24;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD');
|
||||
Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS');
|
||||
Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP');
|
||||
Assert(FSPI.VOP3a.NEG =0,'FSPI.VOP3a.NEG');
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtUInt32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtUInt32);
|
||||
src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtUInt32);
|
||||
|
||||
emit_OpFmaU32(dst,src[0],src[1],src[2]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_SAD_U32; //dst.u = abs(vsrc0.u - vsrc1.u) + vaccum.u
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
rdif,rvac:PsrRegNode;
|
||||
//msk:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD');
|
||||
Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS');
|
||||
Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP');
|
||||
Assert(FSPI.VOP3a.NEG =0,'FSPI.VOP3a.NEG');
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtUInt32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtUInt32);
|
||||
src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtUInt32);
|
||||
|
||||
rdif:=NewReg(dtInt32);
|
||||
_emit_OpAbsDiff(line,rdif,src[0],src[1]);
|
||||
|
||||
//msk:=FetchReg(FConsts.Fetch(dtUInt32,$FFFF)); mask need?
|
||||
//emit_OpBitwiseAnd(tmp,src[2],msk);
|
||||
//rvac:=tmp^.current;
|
||||
rvac:=src[2];
|
||||
|
||||
rdif^.mark_read;
|
||||
rvac^.mark_read;
|
||||
emit_OpIAdd(dst,rdif,rvac);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_MAX3_F32;
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..3] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,3);
|
||||
_emit_src_neg_bit(@src,3);
|
||||
|
||||
emit_OpFMax(tmp,src[0],src[1]);
|
||||
src[3]:=MakeRead(tmp,dtFloat32);
|
||||
|
||||
emit_OpFMax(dst,src[3],src[2]);
|
||||
|
||||
_emit_dst_omod_f(dst);
|
||||
_emit_dst_clamp_f(dst);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_MIN3_F32;
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..3] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,3);
|
||||
_emit_src_neg_bit(@src,3);
|
||||
|
||||
emit_OpFMin(tmp,src[0],src[1]);
|
||||
src[3]:=MakeRead(tmp,dtFloat32);
|
||||
|
||||
emit_OpFMin(dst,src[3],src[2]);
|
||||
|
||||
_emit_dst_omod_f(dst);
|
||||
_emit_dst_clamp_f(dst);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_MED3_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..3] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,3);
|
||||
_emit_src_neg_bit(@src,3);
|
||||
|
||||
emit_MED3F(dst,src[0],src[1],src[2]);
|
||||
|
||||
_emit_dst_omod_f(dst);
|
||||
_emit_dst_clamp_f(dst);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_FMA_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,3);
|
||||
_emit_src_neg_bit(@src,3);
|
||||
|
||||
emit_OpFmaF32(dst,src[0],src[1],src[2]);
|
||||
|
||||
_emit_dst_omod_f(dst);
|
||||
_emit_dst_clamp_f(dst);
|
||||
end;
|
||||
|
||||
{
|
||||
procedure TEmit_VOP3._emit_V_CUBEMA_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
max:array[0..1] of PsrRegNode;
|
||||
num_2:PsrRegNode;
|
||||
begin
|
||||
//max(max(abs(x),abs(y)),abs(z))*2
|
||||
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD');
|
||||
Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS');
|
||||
Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP');
|
||||
Assert(FSPI.VOP3a.NEG =0,'FSPI.VOP3a.NEG');
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32);
|
||||
|
||||
_emit_src_abs(@src[0]);
|
||||
_emit_src_abs(@src[1]);
|
||||
_emit_src_abs(@src[2]);
|
||||
|
||||
max[0]:=NewReg(dtFloat32);
|
||||
max[0]^.mark_read;
|
||||
_emit_OpFMax(line,max[0],src[0],src[1]);
|
||||
|
||||
max[1]:=NewReg(dtFloat32);
|
||||
max[1]^.mark_read;
|
||||
_emit_OpFMax(line,max[1],max[0],src[2]);
|
||||
|
||||
num_2:=FetchReg(FConsts.Fetchf(dtFloat32,2));
|
||||
|
||||
emit_OpFMul(dst,max[1],num_2);
|
||||
end;
|
||||
}
|
||||
|
||||
procedure TEmit_VOP3._emit_V_CUBE(OpId:DWORD);
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD');
|
||||
Assert(FSPI.VOP3a.ABS =0,'FSPI.VOP3a.ABS');
|
||||
Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP');
|
||||
Assert(FSPI.VOP3a.NEG =0,'FSPI.VOP3a.NEG');
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
src[1]:=fetch_ssrc9(FSPI.VOP3a.SRC1,dtFloat32);
|
||||
src[2]:=fetch_ssrc9(FSPI.VOP3a.SRC2,dtFloat32);
|
||||
|
||||
emit_Op3(OpId,dtFloat32,dst,src[0],src[1],src[2]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_MOV_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
Assert(FSPI.VOP3a.OMOD =0,'FSPI.VOP3a.OMOD');
|
||||
Assert(FSPI.VOP3a.CLAMP=0,'FSPI.VOP3a.CLAMP');
|
||||
|
||||
if (Byte(FSPI.VOP3a.ABS).TestBit(0)) or
|
||||
(Byte(FSPI.VOP3a.NEG).TestBit(0)) then
|
||||
begin
|
||||
src:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,1);
|
||||
_emit_src_neg_bit(@src,1);
|
||||
|
||||
_MakeCopy(dst,src);
|
||||
end else
|
||||
begin
|
||||
src:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtUnknow);
|
||||
|
||||
_MakeCopy(dst,src);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_SQRT_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
src:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,1);
|
||||
_emit_src_neg_bit(@src,1);
|
||||
|
||||
emit_OpSqrt(dst,src);
|
||||
|
||||
_emit_dst_omod_f(dst);
|
||||
_emit_dst_clamp_f(dst);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_V_RCP_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
one:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP3a.VDST);
|
||||
|
||||
src:=fetch_ssrc9(FSPI.VOP3a.SRC0,dtFloat32);
|
||||
|
||||
_emit_src_abs_bit(@src,1);
|
||||
_emit_src_neg_bit(@src,1);
|
||||
|
||||
one:=FetchReg(FConsts.Fetchf(dtFloat32,1));
|
||||
|
||||
emit_OpFDiv(dst,one,src);
|
||||
|
||||
_emit_dst_omod_f(dst);
|
||||
_emit_dst_clamp_f(dst);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_VOP3c;
|
||||
begin
|
||||
Case FSPI.VOP3a.OP of
|
||||
|
||||
V_CMP_F_F32,
|
||||
V_CMP_F_F64,
|
||||
V_CMP_F_I32,
|
||||
V_CMP_F_I64,
|
||||
V_CMP_F_U32,
|
||||
V_CMP_F_U64,
|
||||
V_CMPS_F_F32,
|
||||
V_CMPS_F_F64:_emit_V_CMP_C(false,false);
|
||||
|
||||
V_CMP_T_F32,
|
||||
V_CMP_T_F64,
|
||||
V_CMP_T_I32,
|
||||
V_CMP_T_I64,
|
||||
V_CMP_T_U32,
|
||||
V_CMP_T_U64,
|
||||
V_CMPS_T_F32,
|
||||
V_CMPS_T_F64:_emit_V_CMP_C(true,false);
|
||||
|
||||
V_CMPX_F_F32,
|
||||
V_CMPX_F_F64,
|
||||
V_CMPX_F_I32,
|
||||
V_CMPX_F_I64,
|
||||
V_CMPX_F_U32,
|
||||
V_CMPX_F_U64,
|
||||
V_CMPSX_F_F32,
|
||||
V_CMPSX_F_F64:_emit_V_CMP_C(false,true);
|
||||
|
||||
V_CMPX_T_F32,
|
||||
V_CMPX_T_F64,
|
||||
V_CMPX_T_I32,
|
||||
V_CMPX_T_I64,
|
||||
V_CMPX_T_U32,
|
||||
V_CMPX_T_U64,
|
||||
V_CMPSX_T_F32,
|
||||
V_CMPSX_T_F64:_emit_V_CMP_C(true,true);
|
||||
|
||||
//
|
||||
|
||||
V_CMP_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,false);
|
||||
V_CMP_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,false);
|
||||
V_CMP_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,false);
|
||||
V_CMP_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,false);
|
||||
V_CMP_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,false);
|
||||
V_CMP_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,false);
|
||||
V_CMP_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,false);
|
||||
V_CMP_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,false);
|
||||
V_CMP_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,false);
|
||||
V_CMP_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,false);
|
||||
V_CMP_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,false);
|
||||
V_CMP_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,false);
|
||||
V_CMP_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,false);
|
||||
V_CMP_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,false);
|
||||
|
||||
V_CMPX_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,true);
|
||||
V_CMPX_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,true);
|
||||
V_CMPX_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,true);
|
||||
V_CMPX_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,true);
|
||||
V_CMPX_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,true);
|
||||
V_CMPX_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,true);
|
||||
V_CMPX_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,true);
|
||||
V_CMPX_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,true);
|
||||
V_CMPX_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,true);
|
||||
V_CMPX_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,true);
|
||||
V_CMPX_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,true);
|
||||
V_CMPX_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,true);
|
||||
V_CMPX_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,true);
|
||||
V_CMPX_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,true);
|
||||
|
||||
//
|
||||
|
||||
V_CMPS_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,false);
|
||||
V_CMPS_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,false);
|
||||
V_CMPS_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,false);
|
||||
V_CMPS_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,false);
|
||||
V_CMPS_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,false);
|
||||
V_CMPS_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,false);
|
||||
V_CMPS_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,false);
|
||||
V_CMPS_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,false);
|
||||
V_CMPS_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,false);
|
||||
V_CMPS_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,false);
|
||||
V_CMPS_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,false);
|
||||
V_CMPS_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,false);
|
||||
V_CMPS_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,false);
|
||||
V_CMPS_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,false);
|
||||
|
||||
V_CMPSX_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,true);
|
||||
V_CMPSX_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,true);
|
||||
V_CMPSX_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,true);
|
||||
V_CMPSX_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,true);
|
||||
V_CMPSX_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,true);
|
||||
V_CMPSX_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,true);
|
||||
V_CMPSX_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,true);
|
||||
V_CMPSX_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,true);
|
||||
V_CMPSX_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,true);
|
||||
V_CMPSX_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,true);
|
||||
V_CMPSX_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,true);
|
||||
V_CMPSX_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,true);
|
||||
V_CMPSX_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,true);
|
||||
V_CMPSX_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,true);
|
||||
|
||||
//
|
||||
|
||||
V_CMP_LT_I32 :_emit_V_CMP_32(Op.OpSLessThan ,dtInt32,false);
|
||||
V_CMP_EQ_I32 :_emit_V_CMP_32(Op.OpIEqual ,dtInt32,false);
|
||||
V_CMP_LE_I32 :_emit_V_CMP_32(Op.OpSLessThanEqual ,dtInt32,false);
|
||||
V_CMP_GT_I32 :_emit_V_CMP_32(Op.OpSGreaterThan ,dtInt32,false);
|
||||
V_CMP_LG_I32 :_emit_V_CMP_32(Op.OpINotEqual ,dtInt32,false);
|
||||
V_CMP_GE_I32 :_emit_V_CMP_32(Op.OpSGreaterThanEqual ,dtInt32,false);
|
||||
|
||||
V_CMPX_LT_I32 :_emit_V_CMP_32(Op.OpSLessThan ,dtInt32,true);
|
||||
V_CMPX_EQ_I32 :_emit_V_CMP_32(Op.OpIEqual ,dtInt32,true);
|
||||
V_CMPX_LE_I32 :_emit_V_CMP_32(Op.OpSLessThanEqual ,dtInt32,true);
|
||||
V_CMPX_GT_I32 :_emit_V_CMP_32(Op.OpSGreaterThan ,dtInt32,true);
|
||||
V_CMPX_LG_I32 :_emit_V_CMP_32(Op.OpINotEqual ,dtInt32,true);
|
||||
V_CMPX_GE_I32 :_emit_V_CMP_32(Op.OpSGreaterThanEqual ,dtInt32,true);
|
||||
|
||||
V_CMP_LT_U32 :_emit_V_CMP_32(Op.OpULessThan ,dtUint32,false);
|
||||
V_CMP_EQ_U32 :_emit_V_CMP_32(Op.OpIEqual ,dtUint32,false);
|
||||
V_CMP_LE_U32 :_emit_V_CMP_32(Op.OpULessThanEqual ,dtUint32,false);
|
||||
V_CMP_GT_U32 :_emit_V_CMP_32(Op.OpUGreaterThan ,dtUint32,false);
|
||||
V_CMP_LG_U32 :_emit_V_CMP_32(Op.OpINotEqual ,dtUint32,false);
|
||||
V_CMP_GE_U32 :_emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,false);
|
||||
|
||||
V_CMPX_LT_U32 :_emit_V_CMP_32(Op.OpULessThan ,dtUint32,true);
|
||||
V_CMPX_EQ_U32 :_emit_V_CMP_32(Op.OpIEqual ,dtUint32,true);
|
||||
V_CMPX_LE_U32 :_emit_V_CMP_32(Op.OpULessThanEqual ,dtUint32,true);
|
||||
V_CMPX_GT_U32 :_emit_V_CMP_32(Op.OpUGreaterThan ,dtUint32,true);
|
||||
V_CMPX_LG_U32 :_emit_V_CMP_32(Op.OpINotEqual ,dtUint32,true);
|
||||
V_CMPX_GE_U32 :_emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,true);
|
||||
|
||||
else
|
||||
Assert(false,'VOP3c?'+IntToStr(FSPI.VOP3a.OP));
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_VOP3b;
|
||||
begin
|
||||
Assert(false,'VOP3b?'+IntToStr(FSPI.VOP3b.OP));
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP3._emit_VOP3a;
|
||||
begin
|
||||
|
||||
Case FSPI.VOP3a.OP of
|
||||
|
||||
256+V_CNDMASK_B32:
|
||||
begin
|
||||
_emit_V_CNDMASK_B32;
|
||||
end;
|
||||
|
||||
256+V_ADD_F32:
|
||||
begin
|
||||
_emit_V_ADD_F32;
|
||||
end;
|
||||
|
||||
256+V_SUB_F32:
|
||||
begin
|
||||
_emit_V_SUB_F32;
|
||||
end;
|
||||
|
||||
256+V_CVT_PKRTZ_F16_F32:
|
||||
begin
|
||||
_emit_V_CVT_PKRTZ_F16_F32;
|
||||
end;
|
||||
|
||||
256+V_MIN_F32:
|
||||
begin
|
||||
_emit_V_MIN_F32;
|
||||
end;
|
||||
|
||||
256+V_MAX_F32:
|
||||
begin
|
||||
_emit_V_MAX_F32;
|
||||
end;
|
||||
|
||||
256+V_MUL_F32:
|
||||
begin
|
||||
_emit_V_MUL_F32;
|
||||
end;
|
||||
|
||||
256+V_MUL_I32_I24:
|
||||
begin
|
||||
_emit_V_MUL_I32_I24;
|
||||
end;
|
||||
|
||||
256+V_MAC_F32:
|
||||
begin
|
||||
_emit_V_MAC_F32;
|
||||
end;
|
||||
|
||||
V_MUL_LO_I32:
|
||||
begin
|
||||
_emit_V_MUL_LO_I32;
|
||||
end;
|
||||
|
||||
V_BFE_U32:
|
||||
begin
|
||||
_emit_V_BFE_U32;
|
||||
end;
|
||||
|
||||
V_MAD_F32:
|
||||
begin
|
||||
_emit_V_MAD_F32;
|
||||
end;
|
||||
|
||||
V_MAD_I32_I24:
|
||||
begin
|
||||
_emit_V_MAD_I32_I24;
|
||||
end;
|
||||
|
||||
V_MAD_U32_U24:
|
||||
begin
|
||||
_emit_V_MAD_U32_U24;
|
||||
end;
|
||||
|
||||
V_SAD_U32:
|
||||
begin
|
||||
_emit_V_SAD_U32;
|
||||
end;
|
||||
|
||||
V_MAX3_F32:
|
||||
begin
|
||||
_emit_V_MAX3_F32;
|
||||
end;
|
||||
|
||||
V_MIN3_F32:
|
||||
begin
|
||||
_emit_V_MIN3_F32;
|
||||
end;
|
||||
|
||||
V_MED3_F32:
|
||||
begin
|
||||
_emit_V_MED3_F32;
|
||||
end;
|
||||
|
||||
V_FMA_F32:
|
||||
begin
|
||||
_emit_V_FMA_F32;
|
||||
end;
|
||||
|
||||
V_CUBEID_F32:_emit_V_CUBE(OpCUBEID);
|
||||
V_CUBESC_F32:_emit_V_CUBE(OpCUBESC);
|
||||
V_CUBETC_F32:_emit_V_CUBE(OpCUBETC);
|
||||
V_CUBEMA_F32:_emit_V_CUBE(OpCUBEMA);
|
||||
|
||||
384+V_MOV_B32:
|
||||
begin
|
||||
_emit_V_MOV_B32;
|
||||
end;
|
||||
|
||||
384+V_SQRT_F32:
|
||||
begin
|
||||
_emit_V_SQRT_F32;
|
||||
end;
|
||||
|
||||
384+V_RCP_F32:
|
||||
begin
|
||||
_emit_V_RCP_F32;
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(false,'VOP3a?'+IntToStr(FSPI.VOP3a.OP));
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
205
spirv/emit_vopc.pas
Normal file
205
spirv/emit_vopc.pas
Normal file
@ -0,0 +1,205 @@
|
||||
unit emit_VOPC;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srReg,
|
||||
spirv,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_VOPC=object(TEmitOp)
|
||||
procedure _emit_VOPC;
|
||||
procedure _emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean);
|
||||
procedure _emit_V_CMP_C(r,x:Boolean);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_VOPC._emit_V_CMP_32(OpId:DWORD;rtype:TsrDataType;x:Boolean);
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst[0]:=@FRegsStory.VCC[0];
|
||||
dst[1]:=@FRegsStory.VCC[1];
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOPC.SRC0 ,rtype);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOPC.VSRC1,rtype);
|
||||
emit_OpCmpV(OpId,dst[0],src[0],src[1]);
|
||||
|
||||
SetConst(dst[1],dtUnknow,0); //set zero
|
||||
|
||||
if x then
|
||||
begin
|
||||
MakeCopy(@FRegsStory.EXEC[0],dst[0]^.current);
|
||||
SetConst(@FRegsStory.EXEC[1],dtUnknow,0); //set zero
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_VOPC._emit_V_CMP_C(r,x:Boolean);
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
begin
|
||||
dst[0]:=@FRegsStory.VCC[0];
|
||||
dst[1]:=@FRegsStory.VCC[1];
|
||||
|
||||
SetConst(dst[0],dtBool,QWORD(r));
|
||||
SetConst(dst[1],dtUnknow,0); //set zero
|
||||
|
||||
if x then
|
||||
begin
|
||||
MakeCopy(@FRegsStory.EXEC[0],dst[0]^.current);
|
||||
SetConst(@FRegsStory.EXEC[1],dtUnknow,0); //set zero
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_VOPC._emit_VOPC;
|
||||
begin
|
||||
|
||||
Case FSPI.VOPC.OP of
|
||||
|
||||
V_CMP_F_F32,
|
||||
V_CMP_F_F64,
|
||||
V_CMP_F_I32,
|
||||
V_CMP_F_I64,
|
||||
V_CMP_F_U32,
|
||||
V_CMP_F_U64,
|
||||
V_CMPS_F_F32,
|
||||
V_CMPS_F_F64:_emit_V_CMP_C(false,false);
|
||||
|
||||
V_CMP_T_F32,
|
||||
V_CMP_T_F64,
|
||||
V_CMP_T_I32,
|
||||
V_CMP_T_I64,
|
||||
V_CMP_T_U32,
|
||||
V_CMP_T_U64,
|
||||
V_CMPS_T_F32,
|
||||
V_CMPS_T_F64:_emit_V_CMP_C(true,false);
|
||||
|
||||
V_CMPX_F_F32,
|
||||
V_CMPX_F_F64,
|
||||
V_CMPX_F_I32,
|
||||
V_CMPX_F_I64,
|
||||
V_CMPX_F_U32,
|
||||
V_CMPX_F_U64,
|
||||
V_CMPSX_F_F32,
|
||||
V_CMPSX_F_F64:_emit_V_CMP_C(false,true);
|
||||
|
||||
V_CMPX_T_F32,
|
||||
V_CMPX_T_F64,
|
||||
V_CMPX_T_I32,
|
||||
V_CMPX_T_I64,
|
||||
V_CMPX_T_U32,
|
||||
V_CMPX_T_U64,
|
||||
V_CMPSX_T_F32,
|
||||
V_CMPSX_T_F64:_emit_V_CMP_C(true,true);
|
||||
|
||||
//
|
||||
|
||||
V_CMP_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,false);
|
||||
V_CMP_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,false);
|
||||
V_CMP_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,false);
|
||||
V_CMP_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,false);
|
||||
V_CMP_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,false);
|
||||
V_CMP_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,false);
|
||||
V_CMP_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,false);
|
||||
V_CMP_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,false);
|
||||
V_CMP_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,false);
|
||||
V_CMP_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,false);
|
||||
V_CMP_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,false);
|
||||
V_CMP_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,false);
|
||||
V_CMP_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,false);
|
||||
V_CMP_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,false);
|
||||
|
||||
V_CMPX_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,true);
|
||||
V_CMPX_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,true);
|
||||
V_CMPX_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,true);
|
||||
V_CMPX_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,true);
|
||||
V_CMPX_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,true);
|
||||
V_CMPX_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,true);
|
||||
V_CMPX_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,true);
|
||||
V_CMPX_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,true);
|
||||
V_CMPX_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,true);
|
||||
V_CMPX_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,true);
|
||||
V_CMPX_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,true);
|
||||
V_CMPX_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,true);
|
||||
V_CMPX_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,true);
|
||||
V_CMPX_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,true);
|
||||
|
||||
//
|
||||
|
||||
V_CMPS_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,false);
|
||||
V_CMPS_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,false);
|
||||
V_CMPS_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,false);
|
||||
V_CMPS_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,false);
|
||||
V_CMPS_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,false);
|
||||
V_CMPS_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,false);
|
||||
V_CMPS_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,false);
|
||||
V_CMPS_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,false);
|
||||
V_CMPS_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,false);
|
||||
V_CMPS_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,false);
|
||||
V_CMPS_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,false);
|
||||
V_CMPS_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,false);
|
||||
V_CMPS_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,false);
|
||||
V_CMPS_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,false);
|
||||
|
||||
V_CMPSX_LT_F32 :_emit_V_CMP_32(Op.OpFOrdLessThan ,dtFloat32,true);
|
||||
V_CMPSX_EQ_F32 :_emit_V_CMP_32(Op.OpFOrdEqual ,dtFloat32,true);
|
||||
V_CMPSX_LE_F32 :_emit_V_CMP_32(Op.OpFOrdLessThanEqual ,dtFloat32,true);
|
||||
V_CMPSX_GT_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThan ,dtFloat32,true);
|
||||
V_CMPSX_LG_F32 :_emit_V_CMP_32(Op.OpFOrdNotEqual ,dtFloat32,true);
|
||||
V_CMPSX_GE_F32 :_emit_V_CMP_32(Op.OpFOrdGreaterThanEqual ,dtFloat32,true);
|
||||
V_CMPSX_O_F32 :_emit_V_CMP_32(Op.OpOrdered ,dtFloat32,true);
|
||||
V_CMPSX_U_F32 :_emit_V_CMP_32(Op.OpUnordered ,dtFloat32,true);
|
||||
V_CMPSX_NGE_F32 :_emit_V_CMP_32(Op.OpFUnordLessThan ,dtFloat32,true);
|
||||
V_CMPSX_NLG_F32 :_emit_V_CMP_32(Op.OpFUnordEqual ,dtFloat32,true);
|
||||
V_CMPSX_NGT_F32 :_emit_V_CMP_32(Op.OpFUnordLessThanEqual ,dtFloat32,true);
|
||||
V_CMPSX_NLE_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThan ,dtFloat32,true);
|
||||
V_CMPSX_NEQ_F32 :_emit_V_CMP_32(Op.OpFUnordNotEqual ,dtFloat32,true);
|
||||
V_CMPSX_NLT_F32 :_emit_V_CMP_32(Op.OpFUnordGreaterThanEqual,dtFloat32,true);
|
||||
|
||||
//
|
||||
|
||||
V_CMP_LT_I32 :_emit_V_CMP_32(Op.OpSLessThan ,dtInt32,false);
|
||||
V_CMP_EQ_I32 :_emit_V_CMP_32(Op.OpIEqual ,dtInt32,false);
|
||||
V_CMP_LE_I32 :_emit_V_CMP_32(Op.OpSLessThanEqual ,dtInt32,false);
|
||||
V_CMP_GT_I32 :_emit_V_CMP_32(Op.OpSGreaterThan ,dtInt32,false);
|
||||
V_CMP_LG_I32 :_emit_V_CMP_32(Op.OpINotEqual ,dtInt32,false);
|
||||
V_CMP_GE_I32 :_emit_V_CMP_32(Op.OpSGreaterThanEqual ,dtInt32,false);
|
||||
|
||||
V_CMPX_LT_I32 :_emit_V_CMP_32(Op.OpSLessThan ,dtInt32,true);
|
||||
V_CMPX_EQ_I32 :_emit_V_CMP_32(Op.OpIEqual ,dtInt32,true);
|
||||
V_CMPX_LE_I32 :_emit_V_CMP_32(Op.OpSLessThanEqual ,dtInt32,true);
|
||||
V_CMPX_GT_I32 :_emit_V_CMP_32(Op.OpSGreaterThan ,dtInt32,true);
|
||||
V_CMPX_LG_I32 :_emit_V_CMP_32(Op.OpINotEqual ,dtInt32,true);
|
||||
V_CMPX_GE_I32 :_emit_V_CMP_32(Op.OpSGreaterThanEqual ,dtInt32,true);
|
||||
|
||||
V_CMP_LT_U32 :_emit_V_CMP_32(Op.OpULessThan ,dtUint32,false);
|
||||
V_CMP_EQ_U32 :_emit_V_CMP_32(Op.OpIEqual ,dtUint32,false);
|
||||
V_CMP_LE_U32 :_emit_V_CMP_32(Op.OpULessThanEqual ,dtUint32,false);
|
||||
V_CMP_GT_U32 :_emit_V_CMP_32(Op.OpUGreaterThan ,dtUint32,false);
|
||||
V_CMP_LG_U32 :_emit_V_CMP_32(Op.OpINotEqual ,dtUint32,false);
|
||||
V_CMP_GE_U32 :_emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,false);
|
||||
|
||||
V_CMPX_LT_U32 :_emit_V_CMP_32(Op.OpULessThan ,dtUint32,true);
|
||||
V_CMPX_EQ_U32 :_emit_V_CMP_32(Op.OpIEqual ,dtUint32,true);
|
||||
V_CMPX_LE_U32 :_emit_V_CMP_32(Op.OpULessThanEqual ,dtUint32,true);
|
||||
V_CMPX_GT_U32 :_emit_V_CMP_32(Op.OpUGreaterThan ,dtUint32,true);
|
||||
V_CMPX_LG_U32 :_emit_V_CMP_32(Op.OpINotEqual ,dtUint32,true);
|
||||
V_CMPX_GE_U32 :_emit_V_CMP_32(Op.OpUGreaterThanEqual ,dtUint32,true);
|
||||
|
||||
else
|
||||
Assert(false,'VOPC?');
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
285
spirv/pssl-spirv.lpi
Normal file
285
spirv/pssl-spirv.lpi
Normal file
@ -0,0 +1,285 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<CONFIG>
|
||||
<ProjectOptions>
|
||||
<Version Value="12"/>
|
||||
<PathDelim Value="\"/>
|
||||
<General>
|
||||
<Flags>
|
||||
<MainUnitHasCreateFormStatements Value="False"/>
|
||||
<MainUnitHasTitleStatement Value="False"/>
|
||||
<MainUnitHasScaledStatement Value="False"/>
|
||||
<CompatibilityMode Value="True"/>
|
||||
</Flags>
|
||||
<SessionStorage Value="InProjectDir"/>
|
||||
<Title Value="pssl-spirv"/>
|
||||
<UseAppBundle Value="False"/>
|
||||
<ResourceType Value="res"/>
|
||||
</General>
|
||||
<BuildModes Count="1">
|
||||
<Item1 Name="Default" Default="True"/>
|
||||
</BuildModes>
|
||||
<PublishOptions>
|
||||
<Version Value="2"/>
|
||||
<UseFileFilters Value="True"/>
|
||||
</PublishOptions>
|
||||
<RunParams>
|
||||
<FormatVersion Value="2"/>
|
||||
</RunParams>
|
||||
<Units Count="49">
|
||||
<Unit0>
|
||||
<Filename Value="pssl-spirv.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit0>
|
||||
<Unit1>
|
||||
<Filename Value="Half16.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit1>
|
||||
<Unit2>
|
||||
<Filename Value="srNodes.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit2>
|
||||
<Unit3>
|
||||
<Filename Value="srTypes.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit3>
|
||||
<Unit4>
|
||||
<Filename Value="srConst.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit4>
|
||||
<Unit5>
|
||||
<Filename Value="srRefId.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit5>
|
||||
<Unit6>
|
||||
<Filename Value="srIO.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit6>
|
||||
<Unit7>
|
||||
<Filename Value="srOp.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit7>
|
||||
<Unit8>
|
||||
<Filename Value="srReg.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit8>
|
||||
<Unit9>
|
||||
<Filename Value="SprvEmit.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit9>
|
||||
<Unit10>
|
||||
<Filename Value="srAllocator.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit10>
|
||||
<Unit11>
|
||||
<Filename Value="srArray.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit11>
|
||||
<Unit12>
|
||||
<Filename Value="emit_sop1.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_SOP1"/>
|
||||
</Unit12>
|
||||
<Unit13>
|
||||
<Filename Value="emit_vop1.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_VOP1"/>
|
||||
</Unit13>
|
||||
<Unit14>
|
||||
<Filename Value="emit_vopc.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_VOPC"/>
|
||||
</Unit14>
|
||||
<Unit15>
|
||||
<Filename Value="emit_vop3b.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_VOP3b"/>
|
||||
</Unit15>
|
||||
<Unit16>
|
||||
<Filename Value="emit_mubuf.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_MUBUF"/>
|
||||
</Unit16>
|
||||
<Unit17>
|
||||
<Filename Value="emit_exp.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_EXP"/>
|
||||
</Unit17>
|
||||
<Unit18>
|
||||
<Filename Value="emit_vintrp.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_VINTRP"/>
|
||||
</Unit18>
|
||||
<Unit19>
|
||||
<Filename Value="emit_smrd.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_SMRD"/>
|
||||
</Unit19>
|
||||
<Unit20>
|
||||
<Filename Value="emit_sop2.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_SOP2"/>
|
||||
</Unit20>
|
||||
<Unit21>
|
||||
<Filename Value="emit_vop2.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_VOP2"/>
|
||||
</Unit21>
|
||||
<Unit22>
|
||||
<Filename Value="emit_post_process.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit22>
|
||||
<Unit23>
|
||||
<Filename Value="emit_print.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit23>
|
||||
<Unit24>
|
||||
<Filename Value="emit_mimg.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_MIMG"/>
|
||||
</Unit24>
|
||||
<Unit25>
|
||||
<Filename Value="emit_op.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit25>
|
||||
<Unit26>
|
||||
<Filename Value="emit_sopp.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_SOPP"/>
|
||||
</Unit26>
|
||||
<Unit27>
|
||||
<Filename Value="emit_sopc.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_SOPC"/>
|
||||
</Unit27>
|
||||
<Unit28>
|
||||
<Filename Value="srparsernode.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="srParserNode"/>
|
||||
</Unit28>
|
||||
<Unit29>
|
||||
<Filename Value="srLabel.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit29>
|
||||
<Unit30>
|
||||
<Filename Value="emit_post_op.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit30>
|
||||
<Unit31>
|
||||
<Filename Value="emit_bitcast.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="srBitcast"/>
|
||||
</Unit31>
|
||||
<Unit32>
|
||||
<Filename Value="srVolatile.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit32>
|
||||
<Unit33>
|
||||
<Filename Value="srLayout.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit33>
|
||||
<Unit34>
|
||||
<Filename Value="srBuffer.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit34>
|
||||
<Unit35>
|
||||
<Filename Value="gnSplayTree.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit35>
|
||||
<Unit36>
|
||||
<Filename Value="srVariable.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit36>
|
||||
<Unit37>
|
||||
<Filename Value="srInput.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit37>
|
||||
<Unit38>
|
||||
<Filename Value="srOutput.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit38>
|
||||
<Unit39>
|
||||
<Filename Value="srUniformConstant.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit39>
|
||||
<Unit40>
|
||||
<Filename Value="srOpUtils.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit40>
|
||||
<Unit41>
|
||||
<Filename Value="srCFG.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit41>
|
||||
<Unit42>
|
||||
<Filename Value="srCap.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit42>
|
||||
<Unit43>
|
||||
<Filename Value="srVertLayout.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit43>
|
||||
<Unit44>
|
||||
<Filename Value="srFragLayout.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit44>
|
||||
<Unit45>
|
||||
<Filename Value="srDecorate.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit45>
|
||||
<Unit46>
|
||||
<Filename Value="emit_mbuf.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="emit_VBUF"/>
|
||||
</Unit46>
|
||||
<Unit47>
|
||||
<Filename Value="srbufinfo.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
<UnitName Value="srBufInfo"/>
|
||||
</Unit47>
|
||||
<Unit48>
|
||||
<Filename Value="emit_bin.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit48>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
<Version Value="11"/>
|
||||
<PathDelim Value="\"/>
|
||||
<Target>
|
||||
<Filename Value="pssl-spirv"/>
|
||||
</Target>
|
||||
<SearchPaths>
|
||||
<IncludeFiles Value="$(ProjOutDir)"/>
|
||||
<OtherUnitFiles Value="..;..\rtl;..\chip;..\vulkan"/>
|
||||
<UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/>
|
||||
</SearchPaths>
|
||||
<Parsing>
|
||||
<SyntaxOptions>
|
||||
<IncludeAssertionCode Value="True"/>
|
||||
</SyntaxOptions>
|
||||
</Parsing>
|
||||
<CodeGeneration>
|
||||
<SmartLinkUnit Value="True"/>
|
||||
<RelocatableUnit Value="True"/>
|
||||
</CodeGeneration>
|
||||
<Linking>
|
||||
<Debugging>
|
||||
<DebugInfoType Value="dsDwarf2Set"/>
|
||||
<UseLineInfoUnit Value="False"/>
|
||||
</Debugging>
|
||||
<LinkSmart Value="True"/>
|
||||
</Linking>
|
||||
</CompilerOptions>
|
||||
<Debugging>
|
||||
<Exceptions Count="3">
|
||||
<Item1>
|
||||
<Name Value="EAbort"/>
|
||||
</Item1>
|
||||
<Item2>
|
||||
<Name Value="ECodetoolError"/>
|
||||
</Item2>
|
||||
<Item3>
|
||||
<Name Value="EFOpenError"/>
|
||||
</Item3>
|
||||
</Exceptions>
|
||||
</Debugging>
|
||||
</CONFIG>
|
784
spirv/pssl-spirv.lpr
Normal file
784
spirv/pssl-spirv.lpr
Normal file
@ -0,0 +1,784 @@
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
Uses
|
||||
classes,
|
||||
Sysutils,
|
||||
si_ci_vi_merged_offset,
|
||||
si_ci_vi_merged_registers,
|
||||
ps4_pssl,
|
||||
ps4_shader,
|
||||
//spirv,
|
||||
srBuffer,
|
||||
SprvEmit,
|
||||
|
||||
emit_post,
|
||||
emit_alloc,
|
||||
emit_print,
|
||||
emit_bin;
|
||||
|
||||
var
|
||||
cfg:record
|
||||
FName:RawByteString;
|
||||
FSave:RawByteString;
|
||||
FPrintInfo:Boolean;
|
||||
FPrintAsm:Boolean;
|
||||
FPrintSpv:Boolean;
|
||||
FUseVertexInput:Boolean;
|
||||
FUseTexelBuffer:Boolean;
|
||||
|
||||
BufferCfg:TsrBufferCfg;
|
||||
end;
|
||||
|
||||
type
|
||||
TDUMP_WORD=packed record
|
||||
REG,COUNT:WORD;
|
||||
end;
|
||||
|
||||
{
|
||||
procedure load_spv(const fname:RawByteString);
|
||||
var
|
||||
M:TMemoryStream;
|
||||
Header:TSPIRVHeader;
|
||||
|
||||
DW:TSPIRVInstruction;
|
||||
|
||||
label
|
||||
_exit;
|
||||
begin
|
||||
M:=TMemoryStream.Create;
|
||||
M.LoadFromFile(fname);
|
||||
M.Position:=0;
|
||||
|
||||
Header:=Default(TSPIRVHeader);
|
||||
M.Read(Header,SizeOf(TSPIRVHeader));
|
||||
if (Header.MAGIC<>spirv.MagicNumber) then Goto _exit;
|
||||
Writeln(HexStr(Header.TOOL_ID,8));
|
||||
|
||||
DW:=Default(TSPIRVInstruction);
|
||||
repeat
|
||||
if M.Read(DW,SizeOf(TSPIRVInstruction))<>SizeOf(TSPIRVInstruction) then Break;
|
||||
Writeln(spirv.Op.GetStr(DW.OP));
|
||||
if (DW.COUNT>1) then
|
||||
begin
|
||||
M.Seek(SizeOf(DWORD)*(DW.COUNT-1),soCurrent);
|
||||
end;
|
||||
until false;
|
||||
|
||||
_exit:
|
||||
M.Free;
|
||||
end;
|
||||
}
|
||||
|
||||
procedure post_SprvEmit(var SprvEmit:TSprvEmit);
|
||||
begin
|
||||
TSprvEmit_post(SprvEmit).Post;
|
||||
end;
|
||||
|
||||
procedure alloc_SprvEmit(var SprvEmit:TSprvEmit);
|
||||
begin
|
||||
TSprvEmit_alloc(SprvEmit).Alloc;
|
||||
end;
|
||||
|
||||
procedure print_SprvEmit(var SprvEmit:TSprvEmit);
|
||||
begin
|
||||
TSprvEmit_print(SprvEmit).Print;
|
||||
end;
|
||||
|
||||
procedure SaveToStream_SprvEmit(Stream:TStream;var SprvEmit:TSprvEmit);
|
||||
begin
|
||||
TSprvEmit_bin(SprvEmit).SaveToStream(Stream);
|
||||
end;
|
||||
|
||||
procedure SaveToFile_SprvEmit(const FName:RawByteString;var SprvEmit:TSprvEmit);
|
||||
var
|
||||
F:TFileStream;
|
||||
begin
|
||||
F:=TFileStream.Create(FName,fmCreate);
|
||||
SaveToStream_SprvEmit(F,SprvEmit);
|
||||
F.Free;
|
||||
end;
|
||||
|
||||
type
|
||||
TSPI_USER_DATA=array[0..15] of DWORD;
|
||||
|
||||
var
|
||||
GPU_REGS:packed record
|
||||
|
||||
PS:packed record
|
||||
Addr:Pointer;
|
||||
|
||||
INPUT_CNTL:array[0..31] of TSPI_PS_INPUT_CNTL_0;
|
||||
|
||||
RSRC1:TSPI_SHADER_PGM_RSRC1_PS;
|
||||
RSRC2:TSPI_SHADER_PGM_RSRC2_PS;
|
||||
RSRC3:TSPI_SHADER_PGM_RSRC3_PS;
|
||||
|
||||
Z_FORMAT :TSPI_SHADER_Z_FORMAT;
|
||||
COL_FORMAT:TSPI_SHADER_COL_FORMAT;
|
||||
|
||||
INPUT_ENA :TSPI_PS_INPUT_ENA;
|
||||
INPUT_ADDR:TSPI_PS_INPUT_ADDR;
|
||||
IN_CONTROL:TSPI_PS_IN_CONTROL;
|
||||
BARYC_CNTL:TSPI_BARYC_CNTL;
|
||||
|
||||
SHADER_CONTROL:TDB_SHADER_CONTROL;
|
||||
SHADER_MASK:TCB_SHADER_MASK;
|
||||
|
||||
USER_DATA:TSPI_USER_DATA;
|
||||
end;
|
||||
|
||||
VS:packed record
|
||||
Addr:Pointer;
|
||||
|
||||
RSRC1:TSPI_SHADER_PGM_RSRC1_VS;
|
||||
RSRC2:TSPI_SHADER_PGM_RSRC2_VS;
|
||||
RSRC3:TSPI_SHADER_PGM_RSRC3_VS;
|
||||
|
||||
OUT_CONFIG:TSPI_VS_OUT_CONFIG;
|
||||
POS_FORMAT:TSPI_SHADER_POS_FORMAT;
|
||||
OUT_CNTL :TPA_CL_VS_OUT_CNTL;
|
||||
|
||||
USER_DATA:TSPI_USER_DATA;
|
||||
end;
|
||||
|
||||
CS:packed record
|
||||
Addr:Pointer;
|
||||
|
||||
RSRC1:TCOMPUTE_PGM_RSRC1;
|
||||
RSRC2:TCOMPUTE_PGM_RSRC2;
|
||||
|
||||
STATIC_THREAD_MGMT_SE0:TCOMPUTE_STATIC_THREAD_MGMT_SE0;
|
||||
STATIC_THREAD_MGMT_SE1:TCOMPUTE_STATIC_THREAD_MGMT_SE1;
|
||||
RESOURCE_LIMITS:TCOMPUTE_RESOURCE_LIMITS;
|
||||
|
||||
NUM_THREAD_X:TCOMPUTE_NUM_THREAD_X;
|
||||
NUM_THREAD_Y:TCOMPUTE_NUM_THREAD_Y;
|
||||
NUM_THREAD_Z:TCOMPUTE_NUM_THREAD_Z;
|
||||
|
||||
USER_DATA:TSPI_USER_DATA;
|
||||
end;
|
||||
|
||||
VGT_NUM_INSTANCES:TVGT_NUM_INSTANCES;
|
||||
end;
|
||||
|
||||
Blocks:TFPList;
|
||||
|
||||
procedure ClearBlocks;
|
||||
var
|
||||
i:Integer;
|
||||
begin
|
||||
if (Blocks=nil) then
|
||||
begin
|
||||
Blocks:=TFPList.Create;
|
||||
Exit;
|
||||
end;
|
||||
if (Blocks.Count<>0) then
|
||||
For i:=0 to Blocks.Count-1 do
|
||||
begin
|
||||
FreeMem(Blocks.Items[i]);
|
||||
end;
|
||||
Blocks.Clear;
|
||||
end;
|
||||
|
||||
procedure load_dump(const fname:RawByteString);
|
||||
var
|
||||
M:TMemoryStream;
|
||||
W:TDUMP_WORD;
|
||||
V:DWORD;
|
||||
addr:Pointer;
|
||||
size,i:DWORD;
|
||||
begin
|
||||
ClearBlocks;
|
||||
FillChar(GPU_REGS,SizeOf(GPU_REGS),0);
|
||||
M:=TMemoryStream.Create;
|
||||
M.LoadFromFile(fname);
|
||||
M.Position:=0;
|
||||
V:=0;
|
||||
W:=Default(TDUMP_WORD);
|
||||
repeat
|
||||
if M.Read(W,SizeOf(W))<>SizeOf(W) then Break;
|
||||
if (W.COUNT=0) then //simple
|
||||
begin
|
||||
if M.Read(V,SizeOf(V))<>SizeOf(V) then Break;
|
||||
|
||||
Case W.REG of
|
||||
mmCOMPUTE_PGM_RSRC1 :DWORD(GPU_REGS.CS.RSRC1 ):=V;
|
||||
mmCOMPUTE_PGM_RSRC2 :DWORD(GPU_REGS.CS.RSRC2 ):=V;
|
||||
mmCOMPUTE_NUM_THREAD_X:DWORD(GPU_REGS.CS.NUM_THREAD_X):=V;
|
||||
mmCOMPUTE_NUM_THREAD_Y:DWORD(GPU_REGS.CS.NUM_THREAD_Y):=V;
|
||||
mmCOMPUTE_NUM_THREAD_Z:DWORD(GPU_REGS.CS.NUM_THREAD_Z):=V;
|
||||
//
|
||||
mmCOMPUTE_USER_DATA_0..mmCOMPUTE_USER_DATA_15:
|
||||
begin
|
||||
i:=W.REG-mmCOMPUTE_USER_DATA_0;
|
||||
GPU_REGS.CS.USER_DATA[i]:=V;
|
||||
end;
|
||||
//
|
||||
mmCOMPUTE_STATIC_THREAD_MGMT_SE0:DWORD(GPU_REGS.CS.STATIC_THREAD_MGMT_SE0):=V;
|
||||
mmCOMPUTE_STATIC_THREAD_MGMT_SE1:DWORD(GPU_REGS.CS.STATIC_THREAD_MGMT_SE1):=V;
|
||||
mmCOMPUTE_RESOURCE_LIMITS :DWORD(GPU_REGS.CS.RESOURCE_LIMITS ):=V;
|
||||
//
|
||||
mmSPI_SHADER_PGM_RSRC1_PS:DWORD(GPU_REGS.PS.RSRC1 ):=V;
|
||||
mmSPI_SHADER_PGM_RSRC2_PS:DWORD(GPU_REGS.PS.RSRC2 ):=V;
|
||||
mmSPI_SHADER_PGM_RSRC3_PS:DWORD(GPU_REGS.PS.RSRC3 ):=V;
|
||||
mmSPI_SHADER_Z_FORMAT :DWORD(GPU_REGS.PS.Z_FORMAT ):=V;
|
||||
mmSPI_SHADER_COL_FORMAT :DWORD(GPU_REGS.PS.COL_FORMAT ):=V;
|
||||
mmSPI_PS_INPUT_ENA :DWORD(GPU_REGS.PS.INPUT_ENA ):=V;
|
||||
mmSPI_PS_INPUT_ADDR :DWORD(GPU_REGS.PS.INPUT_ADDR ):=V;
|
||||
mmSPI_PS_IN_CONTROL :DWORD(GPU_REGS.PS.IN_CONTROL ):=V;
|
||||
mmSPI_BARYC_CNTL :DWORD(GPU_REGS.PS.BARYC_CNTL ):=V;
|
||||
mmDB_SHADER_CONTROL :DWORD(GPU_REGS.PS.SHADER_CONTROL):=V;
|
||||
mmCB_SHADER_MASK :DWORD(GPU_REGS.PS.SHADER_MASK ):=V;
|
||||
//
|
||||
mmSPI_SHADER_USER_DATA_PS_0..mmSPI_SHADER_USER_DATA_PS_15:
|
||||
begin
|
||||
i:=W.REG-mmSPI_SHADER_USER_DATA_PS_0;
|
||||
GPU_REGS.PS.USER_DATA[i]:=V;
|
||||
end;
|
||||
//
|
||||
mmSPI_PS_INPUT_CNTL_0..mmSPI_PS_INPUT_CNTL_31:
|
||||
begin
|
||||
i:=W.REG-mmSPI_PS_INPUT_CNTL_0;
|
||||
DWORD(GPU_REGS.PS.INPUT_CNTL[i]):=V;
|
||||
end;
|
||||
//
|
||||
mmSPI_SHADER_PGM_RSRC1_VS:DWORD(GPU_REGS.VS.RSRC1 ):=V;
|
||||
mmSPI_SHADER_PGM_RSRC2_VS:DWORD(GPU_REGS.VS.RSRC2 ):=V;
|
||||
mmSPI_SHADER_PGM_RSRC3_VS:DWORD(GPU_REGS.VS.RSRC3 ):=V;
|
||||
mmSPI_VS_OUT_CONFIG :DWORD(GPU_REGS.VS.OUT_CONFIG):=V;
|
||||
mmSPI_SHADER_POS_FORMAT :DWORD(GPU_REGS.VS.POS_FORMAT):=V;
|
||||
mmPA_CL_VS_OUT_CNTL :DWORD(GPU_REGS.VS.OUT_CNTL ):=V;
|
||||
//
|
||||
mmSPI_SHADER_USER_DATA_VS_0..mmSPI_SHADER_USER_DATA_VS_15:
|
||||
begin
|
||||
i:=W.REG-mmSPI_SHADER_USER_DATA_VS_0;
|
||||
GPU_REGS.VS.USER_DATA[i]:=V;
|
||||
end;
|
||||
//
|
||||
mmVGT_NUM_INSTANCES :DWORD(GPU_REGS.VGT_NUM_INSTANCES):=V;
|
||||
end;
|
||||
|
||||
|
||||
end else
|
||||
begin
|
||||
size:=(W.COUNT+1)*4;
|
||||
|
||||
if cfg.FPrintInfo then
|
||||
if (W.COUNT<>0) then Writeln('block:',getRegName(W.REG),' size:',size);
|
||||
|
||||
addr:=AllocMem(size+7);
|
||||
if M.Read(Align(addr,8)^,size)<>size then
|
||||
begin
|
||||
FreeMem(addr);
|
||||
Break;
|
||||
end else
|
||||
begin
|
||||
Blocks.Add(addr);
|
||||
addr:=Align(addr,8);
|
||||
end;
|
||||
|
||||
Case W.REG of
|
||||
mmCOMPUTE_PGM_LO:
|
||||
begin
|
||||
GPU_REGS.CS.Addr:=addr;
|
||||
end;
|
||||
mmSPI_SHADER_PGM_LO_PS:
|
||||
begin
|
||||
GPU_REGS.PS.Addr:=addr;
|
||||
end;
|
||||
mmSPI_SHADER_PGM_LO_VS:
|
||||
begin
|
||||
GPU_REGS.VS.Addr:=addr;
|
||||
end;
|
||||
|
||||
mmCOMPUTE_USER_DATA_0..mmCOMPUTE_USER_DATA_14:
|
||||
begin
|
||||
i:=W.REG-mmCOMPUTE_USER_DATA_0;
|
||||
GPU_REGS.CS.USER_DATA[i+0]:=DWORD({%H-}QWORD(addr));
|
||||
GPU_REGS.CS.USER_DATA[i+1]:=DWORD({%H-}QWORD(addr) shr 32);
|
||||
end;
|
||||
|
||||
mmSPI_SHADER_USER_DATA_PS_0..mmSPI_SHADER_USER_DATA_PS_14:
|
||||
begin
|
||||
i:=W.REG-mmSPI_SHADER_USER_DATA_PS_0;
|
||||
GPU_REGS.PS.USER_DATA[i+0]:=DWORD({%H-}QWORD(addr));
|
||||
GPU_REGS.PS.USER_DATA[i+1]:=DWORD({%H-}QWORD(addr) shr 32);
|
||||
end;
|
||||
|
||||
mmSPI_SHADER_USER_DATA_VS_0..mmSPI_SHADER_USER_DATA_VS_14:
|
||||
begin
|
||||
i:=W.REG-mmSPI_SHADER_USER_DATA_VS_0;
|
||||
GPU_REGS.VS.USER_DATA[i+0]:=DWORD({%H-}QWORD(addr));
|
||||
GPU_REGS.VS.USER_DATA[i+1]:=DWORD({%H-}QWORD(addr) shr 32);
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
until false;
|
||||
end;
|
||||
|
||||
procedure load_pssl(base:Pointer);
|
||||
var
|
||||
info:PShaderBinaryInfo;
|
||||
Slots:PInputUsageSlot;
|
||||
|
||||
SprvEmit:TSprvEmit;
|
||||
|
||||
//LParser:TsrLParser;
|
||||
//FCode:TsrCodeBlock;
|
||||
|
||||
i:Byte;
|
||||
|
||||
begin
|
||||
if (base=nil) then Exit;
|
||||
|
||||
info:=_calc_shader_info(base,MemSize(base) div 4);
|
||||
|
||||
if cfg.FPrintInfo then
|
||||
if (info<>nil) then
|
||||
begin
|
||||
Writeln('signature =',info^.signature );
|
||||
Writeln('version =',info^.version );
|
||||
Writeln('pssl_or_cg =',info^.pssl_or_cg );
|
||||
Writeln('cached =',info^.cached );
|
||||
Writeln('m_type =',info^.m_type );
|
||||
Writeln('source_type =',info^.source_type );
|
||||
Writeln('length =',info^.length );
|
||||
Writeln('chunkUsageBaseOffsetInDW=',info^.chunkUsageBaseOffsetInDW);
|
||||
Writeln('numInputUsageSlots =',info^.numInputUsageSlots );
|
||||
Writeln('isSrt =',info^.isSrt );
|
||||
Writeln('isSrtUsedInfoValid =',info^.isSrtUsedInfoValid );
|
||||
Writeln('isExtendedUsageInfo =',info^.isExtendedUsageInfo );
|
||||
Writeln('reserved2 =',info^.reserved2 );
|
||||
Writeln('reserved3 =',info^.reserved3 );
|
||||
Writeln('shaderHash0 =','0x',HexStr(info^.shaderHash0,8));
|
||||
Writeln('shaderHash1 =','0x',HexStr(info^.shaderHash1,8));
|
||||
Writeln('crc32 =','0x',HexStr(info^.crc32,8) );
|
||||
writeln;
|
||||
|
||||
if (info^.numInputUsageSlots<>0) then
|
||||
begin
|
||||
Slots:=_calc_shader_slot(info);
|
||||
|
||||
For i:=0 to info^.numInputUsageSlots-1 do
|
||||
begin
|
||||
Writeln('Slot[',i,']');
|
||||
|
||||
case Slots[i].m_usageType of
|
||||
kShaderInputUsageImmResource :Writeln(' ','kShaderInputUsageImmResource ');
|
||||
kShaderInputUsageImmSampler :Writeln(' ','kShaderInputUsageImmSampler ');
|
||||
kShaderInputUsageImmConstBuffer :Writeln(' ','kShaderInputUsageImmConstBuffer ');
|
||||
kShaderInputUsageImmVertexBuffer :Writeln(' ','kShaderInputUsageImmVertexBuffer ');
|
||||
kShaderInputUsageImmRwResource :Writeln(' ','kShaderInputUsageImmRwResource ');
|
||||
kShaderInputUsageImmAluFloatConst :Writeln(' ','kShaderInputUsageImmAluFloatConst ');
|
||||
kShaderInputUsageImmAluBool32Const :Writeln(' ','kShaderInputUsageImmAluBool32Const ');
|
||||
kShaderInputUsageImmGdsCounterRange :Writeln(' ','kShaderInputUsageImmGdsCounterRange ');
|
||||
kShaderInputUsageImmGdsMemoryRange :Writeln(' ','kShaderInputUsageImmGdsMemoryRange ');
|
||||
kShaderInputUsageImmGwsBase :Writeln(' ','kShaderInputUsageImmGwsBase ');
|
||||
kShaderInputUsageImmShaderResourceTable :Writeln(' ','kShaderInputUsageImmShaderResourceTable ');
|
||||
kShaderInputUsageImmLdsEsGsSize :Writeln(' ','kShaderInputUsageImmLdsEsGsSize ');
|
||||
kShaderInputUsageSubPtrFetchShader :Writeln(' ','kShaderInputUsageSubPtrFetchShader ');
|
||||
kShaderInputUsagePtrResourceTable :Writeln(' ','kShaderInputUsagePtrResourceTable ');
|
||||
kShaderInputUsagePtrInternalResourceTable :Writeln(' ','kShaderInputUsagePtrInternalResourceTable ');
|
||||
kShaderInputUsagePtrSamplerTable :Writeln(' ','kShaderInputUsagePtrSamplerTable ');
|
||||
kShaderInputUsagePtrConstBufferTable :Writeln(' ','kShaderInputUsagePtrConstBufferTable ');
|
||||
kShaderInputUsagePtrVertexBufferTable :Writeln(' ','kShaderInputUsagePtrVertexBufferTable ');
|
||||
kShaderInputUsagePtrSoBufferTable :Writeln(' ','kShaderInputUsagePtrSoBufferTable ');
|
||||
kShaderInputUsagePtrRwResourceTable :Writeln(' ','kShaderInputUsagePtrRwResourceTable ');
|
||||
kShaderInputUsagePtrInternalGlobalTable :Writeln(' ','kShaderInputUsagePtrInternalGlobalTable ');
|
||||
kShaderInputUsagePtrExtendedUserData :Writeln(' ','kShaderInputUsagePtrExtendedUserData ');
|
||||
kShaderInputUsagePtrIndirectResourceTable :Writeln(' ','kShaderInputUsagePtrIndirectResourceTable ');
|
||||
kShaderInputUsagePtrIndirectInternalResourceTable:Writeln(' ','kShaderInputUsagePtrIndirectInternalResourceTable');
|
||||
kShaderInputUsagePtrIndirectRwResourceTable :Writeln(' ','kShaderInputUsagePtrIndirectRwResourceTable ');
|
||||
kShaderInputUsageImmGdsKickRingBufferOffse :Writeln(' ','kShaderInputUsageImmGdsKickRingBufferOffse ');
|
||||
kShaderInputUsageImmVertexRingBufferOffse :Writeln(' ','kShaderInputUsageImmVertexRingBufferOffse ');
|
||||
kShaderInputUsagePtrDispatchDraw :Writeln(' ','kShaderInputUsagePtrDispatchDraw ');
|
||||
kShaderInputUsageImmDispatchDrawInstances :Writeln(' ','kShaderInputUsageImmDispatchDrawInstances ');
|
||||
else
|
||||
Writeln(' m_usageType=',Slots[i].m_usageType);
|
||||
end;
|
||||
|
||||
Writeln(' apiSlot=',Slots[i].m_apiSlot);
|
||||
Writeln(' startRegister=',Slots[i].m_startRegister);
|
||||
|
||||
Writeln(' param=',HexStr(Slots[i].m_srtSizeInDWordMinusOne,2));
|
||||
end;
|
||||
Writeln;
|
||||
end;
|
||||
end;
|
||||
|
||||
Assert(info<>nil);
|
||||
|
||||
case info^.m_type of
|
||||
kShaderTypePs :
|
||||
begin
|
||||
if cfg.FPrintInfo then
|
||||
Writeln('USGPR:',GPU_REGS.PS.RSRC2.USER_SGPR,' VGPRS:',GPU_REGS.PS.RSRC1.VGPRS,' SGPRS:',GPU_REGS.PS.RSRC1.SGPRS);
|
||||
|
||||
SprvEmit.InitPs(GPU_REGS.PS.RSRC2,GPU_REGS.PS.INPUT_ENA);
|
||||
SprvEmit.SetUserData(@GPU_REGS.PS.USER_DATA);
|
||||
end;
|
||||
kShaderTypeVsVs:
|
||||
begin
|
||||
if cfg.FPrintInfo then
|
||||
Writeln('USGPR:',GPU_REGS.VS.RSRC2.USER_SGPR,' VGPRS:',GPU_REGS.VS.RSRC1.VGPRS,' SGPRS:',GPU_REGS.VS.RSRC1.SGPRS);
|
||||
|
||||
SprvEmit.InitVs(GPU_REGS.VS.RSRC2,GPU_REGS.VGT_NUM_INSTANCES);
|
||||
SprvEmit.SetUserData(@GPU_REGS.VS.USER_DATA);
|
||||
end;
|
||||
kShaderTypeCs:
|
||||
begin
|
||||
if cfg.FPrintInfo then
|
||||
Writeln('USGPR:',GPU_REGS.CS.RSRC2.USER_SGPR,' VGPRS:',GPU_REGS.CS.RSRC1.VGPRS,' SGPRS:',GPU_REGS.CS.RSRC1.SGPRS);
|
||||
|
||||
SprvEmit.InitCs(GPU_REGS.CS.RSRC2,GPU_REGS.CS.NUM_THREAD_X,GPU_REGS.CS.NUM_THREAD_Y,GPU_REGS.CS.NUM_THREAD_Z);
|
||||
SprvEmit.SetUserData(@GPU_REGS.CS.USER_DATA);
|
||||
|
||||
end;
|
||||
|
||||
else
|
||||
begin
|
||||
_parse_print(base);
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
SprvEmit.FPrintAsm :=cfg.FPrintAsm;
|
||||
SprvEmit.FUseVertexInput:=cfg.FUseVertexInput;
|
||||
SprvEmit.FUseTexelBuffer:=cfg.FUseTexelBuffer;
|
||||
|
||||
SprvEmit.FBuffers.cfg:=cfg.BufferCfg;
|
||||
|
||||
if (SprvEmit.Parse(base)>1) then
|
||||
begin
|
||||
Writeln(StdErr,'Shader Parse Err');
|
||||
end;
|
||||
|
||||
if cfg.FPrintAsm or cfg.FPrintSpv or (cfg.FSave<>'') then
|
||||
begin
|
||||
post_SprvEmit(SprvEmit);
|
||||
alloc_SprvEmit(SprvEmit);
|
||||
end;
|
||||
|
||||
if cfg.FPrintSpv then
|
||||
begin
|
||||
print_SprvEmit(SprvEmit);
|
||||
Writeln;
|
||||
end;
|
||||
|
||||
if (cfg.FSave<>'') then
|
||||
begin
|
||||
SaveToFile_SprvEmit(cfg.FSave,SprvEmit);
|
||||
end;
|
||||
|
||||
if cfg.FPrintInfo then
|
||||
Writeln('used_size=',SprvEmit.FAllocator.used_size);
|
||||
|
||||
SprvEmit.FAllocator.Free;
|
||||
end;
|
||||
|
||||
function ParseCmd:Boolean;
|
||||
var
|
||||
i,n:Integer;
|
||||
label
|
||||
promo;
|
||||
begin
|
||||
if (ParamCount=0) then
|
||||
begin
|
||||
promo:
|
||||
|
||||
Exit(False);
|
||||
end;
|
||||
|
||||
cfg.FUseVertexInput:=True;
|
||||
cfg.BufferCfg.Init;
|
||||
|
||||
n:=-1;
|
||||
For i:=1 to ParamCount do
|
||||
begin
|
||||
case LowerCase(ParamStr(i)) of
|
||||
'-i':cfg.FPrintInfo:=True;
|
||||
'-a':cfg.FPrintAsm:=True;
|
||||
'-p':cfg.FPrintSpv:=True;
|
||||
'-eva':cfg.FUseVertexInput:=True;
|
||||
'-dva':cfg.FUseVertexInput:=False;
|
||||
'-etb':cfg.FUseTexelBuffer:=True;
|
||||
'-dtb':cfg.FUseTexelBuffer:=False;
|
||||
|
||||
'-b':n:=0;
|
||||
|
||||
'-mubo':n:=1;//maxUniformBufferRange
|
||||
'-pco':n:=2;//PushConstantsOffset
|
||||
'-pcs':n:=3;//maxPushConstantsSize
|
||||
'-sboa':n:=4;//minStorageBufferOffsetAlignment
|
||||
'-uboa':n:=5;//minUniformBufferOffsetAlignment
|
||||
|
||||
else
|
||||
begin
|
||||
Case n of
|
||||
-1:cfg.FName:=ParamStr(i);
|
||||
0:cfg.FSave:=ParamStr(i);
|
||||
1:cfg.BufferCfg.maxUniformBufferRange :=StrToInt64Def(ParamStr(i),0);
|
||||
2:cfg.BufferCfg.PushConstantsOffset :=StrToInt64Def(ParamStr(i),0);
|
||||
3:cfg.BufferCfg.maxPushConstantsSize :=StrToInt64Def(ParamStr(i),0);
|
||||
4:cfg.BufferCfg.minStorageBufferOffsetAlignment:=StrToInt64Def(ParamStr(i),0);
|
||||
5:cfg.BufferCfg.minUniformBufferOffsetAlignment:=StrToInt64Def(ParamStr(i),0);
|
||||
end;
|
||||
n:=-1;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
begin
|
||||
DefaultSystemCodePage:=CP_UTF8;
|
||||
DefaultUnicodeCodePage:=CP_UTF8;
|
||||
DefaultFileSystemCodePage:=CP_UTF8;
|
||||
DefaultRTLFileSystemCodePage:=CP_UTF8;
|
||||
UTF8CompareLocale:=CP_UTF8;
|
||||
|
||||
FillChar(cfg,SizeOf(cfg),0);
|
||||
|
||||
ParseCmd;
|
||||
|
||||
if (cfg.FName='') then
|
||||
begin
|
||||
//loadspv('vert.spv');
|
||||
|
||||
//branch adr
|
||||
//load_dump('shader_dump\MomodoraRUtM\MomodoraRUtM_ps_595F5E5D.dump');
|
||||
//load_dump('shader_dump\MomodoraRUtM\MomodoraRUtM_vs_B9E80F51.dump');
|
||||
|
||||
//load_dump('shader_dump\MomodoraRUtM\MomodoraRUtM_vs_72685B15.dump');
|
||||
|
||||
//branch
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_cs_3685EFC7.dump');
|
||||
|
||||
//branch
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_8D309F69.dump');
|
||||
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_30AC6582.dump');
|
||||
|
||||
//V_MED3_F32
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_46F7D0CB.dump');
|
||||
|
||||
//branch
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_897BFEFF.dump');
|
||||
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_A9A43387.dump');
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_BD5B57D5.dump');
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_C342C7CD.dump');
|
||||
|
||||
//V_MED3_F32
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_E125C5F7.dump');
|
||||
|
||||
//branch cycle
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_E820FFDE.dump');
|
||||
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_vs_1CE5C47E.dump');
|
||||
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_vs_22E9CA76.dump');
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_vs_48FA7A4C.dump');
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_vs_243D8C75.dump');
|
||||
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_vs_B4E470AF.dump');
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_vs_E1C90BE3.dump');
|
||||
|
||||
//branch
|
||||
////load_dump('shader_dump\WeAreDoomed\WeAreDoomed_ps4_cs_FEA061C5.dump');
|
||||
|
||||
//load_dump('shader_dump\simplet-simple-fs_debug\simplet-simple-fs_debug_vs_398C5BF6.dump');
|
||||
//load_dump('shader_dump\simplet-simple-fs_debug\simplet-simple-fs_debug_ps_F327ABD1.dump');
|
||||
|
||||
//load_dump('shader_dump\simplet-single-triangle_debug\simplet-single-triangle_debug_vs_78EF9008.dump');
|
||||
//load_dump('shader_dump\simplet-single-triangle_debug\simplet-single-triangle_debug_ps_FBCA196D.dump');
|
||||
|
||||
//load_dump('shader_dump\basic_quad_debug\basic_quad_debug_ps_C342C7CD.dump');
|
||||
//load_dump('shader_dump\basic_quad_debug\basic_quad_debug_vs_D216FEB8.dump');
|
||||
|
||||
//load_dump('shader_dump\basic_quad_debug\basic_quad_debug_cs_3685EFC7.dump');
|
||||
|
||||
//load_dump('shader_dump\basic_quad_debug\basic_quad_debug_ps_A9F64695.dump');
|
||||
//load_dump('shader_dump\basic_quad_debug\basic_quad_debug_vs_B4E470AF.dump');
|
||||
|
||||
//load_dump('shader_dump\basic_quad_debug\basic_quad_debug_vs_1CE5C47E.dump');
|
||||
|
||||
//load_dump('shader_dump\basic-compute_debug\basic-compute_debug_ps_4BD7E17E.dump');
|
||||
//load_dump('shader_dump\basic-compute_debug\basic-compute_debug_vs_0C30DA0F.dump');
|
||||
|
||||
//load_dump('shader_dump\SonicMania\SonicMania_ps_0C48E8B2.dump');
|
||||
|
||||
|
||||
//load_dump('shader_dump\SonicMania\SonicMania_ps_B4281DBF.dump');
|
||||
|
||||
load_dump('shader_dump\SonicMania\SonicMania_ps_11DF2A32.dump');
|
||||
|
||||
//load_dump('shader_dump\SonicMania\SonicMania_ps_3CC22A00.dump'); //cfg
|
||||
end;
|
||||
|
||||
if (cfg.FName<>'') then
|
||||
load_dump(cfg.FName);
|
||||
|
||||
load_pssl(GPU_REGS.CS.Addr);
|
||||
|
||||
load_pssl(GPU_REGS.VS.Addr);
|
||||
load_pssl(GPU_REGS.PS.Addr);
|
||||
|
||||
if cfg.FPrintInfo then
|
||||
readln;
|
||||
end.
|
||||
|
||||
{
|
||||
|
||||
///////////////////source ext
|
||||
|
||||
[USER_DATA]
|
||||
|
|
||||
v
|
||||
//DATA LAYOUT
|
||||
[PARENT_LAYOUT|DATA_TYPE|OFFSET|INDEX]
|
||||
^ ^ ^
|
||||
| | | //CHILD LAYOUT //UNIFORM
|
||||
| |[PARENT_LAYOUT|DATA_TYPE|OFFSET] <- [SOURCE_LAYOUT|HANDLE_TYPE|PVAR|PREG]
|
||||
| | ^ ^
|
||||
| | | |
|
||||
| | /-------------------------/ |
|
||||
| | | |
|
||||
| | v |
|
||||
| | [PVAR] <- [opLoad]<--------------/
|
||||
| |
|
||||
| | //CHILD LAYOUT //BUFFER
|
||||
| [PARENT_LAYOUT|DATA_TYPE|OFFSET] <- [SOURCE_LAYOUT|CAST_NUM|PVAR] <-> [PVAR]<----------\
|
||||
| ^ |
|
||||
| | //BUFFER FIELD |
|
||||
| [SOURCE_BUFFER|SOURCE_FIELD|ID|OFFSET|SIZE|PREG] |
|
||||
| ^ | |
|
||||
| /------------/ | |
|
||||
| | | |
|
||||
| [OpAccessChain|ID|ID...]<-------------------------/
|
||||
| ^ |
|
||||
| | |
|
||||
| [opLoad]<-----------------------------------/
|
||||
|
|
||||
|[SET]
|
||||
|
|
||||
| //CHAIN LAYOUT
|
||||
[SOURCE_LAYOUT|OFFSET|PREG] <-> [opLoad]
|
||||
|
||||
///////////////////
|
||||
|
||||
|
||||
[FUserDataVar]
|
||||
^
|
||||
| /----------------------------------------v---------------------------\
|
||||
[pArray|Source] <- [OpAccessChain|[Index]] <- [PChain|pWriter|ID] <- [opLoad] <- [pReg|ID]
|
||||
|
||||
|
||||
[PChain]*x
|
||||
^ ^
|
||||
| |
|
||||
[pGroup|chains]
|
||||
|
||||
//////////////////
|
||||
|
||||
[pUniform]
|
||||
| ^
|
||||
v /-----------------------\
|
||||
[Forked_Var] <- [opLoad] <- [pReg|ID] <- [OpImageRead1D]
|
||||
|
||||
//////////////////
|
||||
|
||||
[OpVariable] [pointer struct] PushConstant
|
||||
^ ^
|
||||
| |
|
||||
| [OpTypePointer] PushConstant [struct]
|
||||
| ^
|
||||
| |
|
||||
| [OpTypeStruct] [item1:type] <- aType
|
||||
| ^ ^ ^
|
||||
| | | |
|
||||
| | [OpMemberDecorate] [struct] [item1:index] Offset 0
|
||||
| |
|
||||
| [OpDecorate] [struct] Block
|
||||
|
|
||||
| [OpTypePointer] PushConstant [item1:type]
|
||||
| |
|
||||
| v
|
||||
[OpAccessChain] [pointer type] [pVar] [item1:index]
|
||||
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
|
||||
x:=1 //write
|
||||
|
||||
[opLabel]->
|
||||
|
||||
y:=x+1 //read ^make var
|
||||
|
||||
[opLabel]<-
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
y:=0 //write
|
||||
|
||||
[opLabel]->
|
||||
|
||||
y:=1 //write
|
||||
|
||||
y:=y+y //write <-
|
||||
|
||||
[opLabel]<-
|
||||
|
||||
x:=y+1; //read ^make var
|
||||
|
||||
y:=1 //write <- reset var
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
y:=0 //write
|
||||
|
||||
[opLabel]->
|
||||
|
||||
x:=1 //write
|
||||
|
||||
[opLabel]<-
|
||||
|
||||
x:=y+1; //read ^nop
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
[OpCond]
|
||||
|
||||
IF[ [OpSelectionMerge] [OpBranchConditional] [OpLabel]
|
||||
|
||||
//body
|
||||
|
||||
[OpLabel] ]ENDIF
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
IF[ [OpBranch] [OpLabel]
|
||||
|
||||
WHILE[ [OpLoopMerge] [OpBranch] [OpLabel]
|
||||
|
||||
//body
|
||||
|
||||
[OpBranch] [OpLabel] ]WHILE(1)
|
||||
|
||||
[OpCond]
|
||||
|
||||
[OpBranchConditional] [OpLabel] ]WHILE(2) ]ENDIF
|
||||
|
||||
//////////////////////////////
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
4120
spirv/spirv.pas
Normal file
4120
spirv/spirv.pas
Normal file
File diff suppressed because it is too large
Load Diff
81
spirv/srAllocator.pas
Normal file
81
spirv/srAllocator.pas
Normal file
@ -0,0 +1,81 @@
|
||||
unit srAllocator;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
srNodes;
|
||||
|
||||
type
|
||||
PsrAllocNode=^TsrAllocNode;
|
||||
TsrAllocNode=packed record
|
||||
pNext:PsrAllocNode;
|
||||
data:record end;
|
||||
end;
|
||||
|
||||
_TsrAllocator=specialize TNodeStack<PsrAllocNode>;
|
||||
TsrAllocator=object(_TsrAllocator)
|
||||
curr_apos:ptruint; //alloc pos in current node
|
||||
curr_size:ptruint; //useable size of current node
|
||||
used_size:ptruint; //full usable size
|
||||
full_size:ptruint; //full alloc size
|
||||
Function Alloc(Size:ptruint):Pointer;
|
||||
Procedure Free;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
Function TsrAllocator.Alloc(Size:ptruint):Pointer;
|
||||
const
|
||||
asize=$FFFF-SizeOf(ptruint)*3;
|
||||
var
|
||||
mem_size:ptruint;
|
||||
|
||||
function _alloc:Pointer;
|
||||
begin
|
||||
if (Size>asize-SizeOf(Pointer)) then
|
||||
begin
|
||||
Result:=AllocMem(Size+SizeOf(Pointer));
|
||||
end else
|
||||
begin
|
||||
Result:=AllocMem(asize);
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
if (pHead=nil) or (Size>curr_size) then
|
||||
begin
|
||||
Push_head(_alloc);
|
||||
mem_size:=MemSize(pHead);
|
||||
curr_apos:=0;
|
||||
curr_size:=mem_size-SizeOf(Pointer);
|
||||
Inc(full_size,mem_size);
|
||||
end;
|
||||
|
||||
Result:=@PByte(@pHead^.data)[curr_apos];
|
||||
|
||||
Inc(used_size,Size);
|
||||
Size:=Align(Size,SizeOf(ptruint));
|
||||
Inc(curr_apos,Size);
|
||||
Dec(curr_size,Size);
|
||||
end;
|
||||
|
||||
Procedure TsrAllocator.Free;
|
||||
var
|
||||
node:PsrAllocNode;
|
||||
begin
|
||||
node:=Pop_head;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
FreeMem(node);
|
||||
node:=Pop_head;
|
||||
end;
|
||||
curr_apos:=0;
|
||||
curr_size:=0;
|
||||
used_size:=0;
|
||||
full_size:=0;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
152
spirv/srBitcast.pas
Normal file
152
spirv/srBitcast.pas
Normal file
@ -0,0 +1,152 @@
|
||||
unit srBitcast;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg;
|
||||
|
||||
type
|
||||
PsrBitcast=^TsrBitcast;
|
||||
TsrBitcast=object
|
||||
pLeft,pRight:PsrBitcast;
|
||||
//----
|
||||
key:packed record
|
||||
dtype:TsrDataType;
|
||||
src:PsrRegNode;
|
||||
end;
|
||||
dst:PsrRegNode;
|
||||
function c(n1,n2:PsrBitcast):Integer; static;
|
||||
end;
|
||||
|
||||
TsrBitcastList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrBitcast,TsrBitcast>;
|
||||
var
|
||||
pRoot:Pointer;
|
||||
FNTree:TNodeFetch;
|
||||
function Find(dtype:TsrDataType;src:PsrRegNode):PsrBitcast;
|
||||
function FetchRead(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
||||
function FetchDst(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
||||
function FetchCast(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
function TsrBitcast.c(n1,n2:PsrBitcast):Integer;
|
||||
begin
|
||||
Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrBitcast.key));
|
||||
end;
|
||||
|
||||
function TsrBitcastList.Find(dtype:TsrDataType;src:PsrRegNode):PsrBitcast;
|
||||
var
|
||||
node:TsrBitcast;
|
||||
begin
|
||||
node:=Default(TsrBitcast);
|
||||
node.key.dtype:=dtype;
|
||||
node.key.src:=src;
|
||||
Result:=FNTree.Find(@node);
|
||||
end;
|
||||
|
||||
function TsrBitcastList.FetchRead(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
||||
var
|
||||
dst:PsrRegNode;
|
||||
begin
|
||||
Result:=src;
|
||||
if (src=nil) then Exit;
|
||||
if (dtype=dtUnknow) or (dtype=src^.dtype) then
|
||||
begin
|
||||
src^.mark_read;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
src^.mark_read;
|
||||
dst:=PSprvEmit(pRoot)^.NewReg(dtype);
|
||||
dst^.pLine:=src^.pLine;
|
||||
dst^.pWriter.SetParam(ntReg,src);
|
||||
|
||||
dst^.mark_read;
|
||||
Result:=dst;
|
||||
end;
|
||||
|
||||
function TsrBitcastList.FetchDst(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
||||
begin
|
||||
Result:=src;
|
||||
if (src=nil) then Exit;
|
||||
if (dtype=dtUnknow) or (dtype=src^.dtype) then Exit;
|
||||
|
||||
Result:=PSprvEmit(pRoot)^.NewReg(dtype);
|
||||
Result^.pLine:=src^.pLine;
|
||||
Result^.mark_read;
|
||||
|
||||
Result^.pWriter:=src^.pWriter;
|
||||
src^.pWriter.SetParam(ntReg,Result);
|
||||
end;
|
||||
|
||||
function TsrBitcastList.FetchCast(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
||||
var
|
||||
node:PsrBitcast;
|
||||
dst:PsrRegNode;
|
||||
|
||||
begin
|
||||
Result:=src;
|
||||
if (src=nil) then Exit;
|
||||
if (dtype=dtUnknow) or (dtype=src^.dtype) then
|
||||
begin
|
||||
src^.mark_read;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
dst:=nil;
|
||||
|
||||
node:=Find(dtype,src);
|
||||
if (node<>nil) then
|
||||
begin
|
||||
dst:=node^.dst;
|
||||
dst^.mark_read;
|
||||
Result:=dst;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if src^.is_const then
|
||||
begin
|
||||
src^.AsConst^.mark_unread;
|
||||
dst:=PSprvEmit(pRoot)^.NewReg(dtype);
|
||||
dst^.pLine:=src^.pLine;
|
||||
dst^.pWriter.SetParam(ntConst,PSprvEmit(pRoot)^.FConsts.Bitcast(dtype,src^.AsConst));
|
||||
end else
|
||||
begin
|
||||
if TryBitcastType(src^.dtype,dtype) then
|
||||
begin
|
||||
src^.mark_read;
|
||||
dst:=PSprvEmit(pRoot)^.NewReg(dtype);
|
||||
dst^.pLine:=src^.pLine;
|
||||
PEmitOp(pRoot)^.emit_OpCastExt(src^.pLine,dst,src);
|
||||
end else
|
||||
begin
|
||||
Assert(false,'bitcast');
|
||||
end;
|
||||
end;
|
||||
|
||||
node:=PSprvEmit(pRoot)^.Alloc(SizeOf(TsrBitcast));
|
||||
node^:=Default(TsrBitcast);
|
||||
node^.key.dtype:=dtype;
|
||||
node^.key.src:=src;
|
||||
node^.dst:=dst;
|
||||
FNTree.Insert(node);
|
||||
|
||||
dst^.mark_read;
|
||||
Result:=dst;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
837
spirv/srBuffer.pas
Normal file
837
spirv/srBuffer.pas
Normal file
@ -0,0 +1,837 @@
|
||||
unit srBuffer;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
spirv,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srVariable,
|
||||
srLayout,
|
||||
srDecorate;
|
||||
|
||||
type
|
||||
PsrBuffer=^TsrBuffer;
|
||||
|
||||
PsrField=^TsrField;
|
||||
|
||||
TsrFieldValue=(frNotFit,frIdent,frVectorAsValue,frValueInVector,frValueInArray);
|
||||
|
||||
TFieldFetchValue=record
|
||||
fValue:TsrFieldValue;
|
||||
pField:PsrField;
|
||||
end;
|
||||
|
||||
TFieldEnumCb=procedure(pField:PsrField) of object;
|
||||
TsrField=object
|
||||
type
|
||||
TFieldFetch=specialize TNodeFetch<PsrField,TsrField>;
|
||||
var
|
||||
pLeft,pRight:PsrField;
|
||||
//----
|
||||
|
||||
pBuffer:PsrBuffer;
|
||||
parent:PsrField;
|
||||
offset:PtrUint;
|
||||
size:PtrUint;
|
||||
stride:PtrUint;
|
||||
|
||||
FCount:PtrUint;
|
||||
dtype:TsrDataType;
|
||||
pType:PsrType;
|
||||
FID:Integer; //alloc late
|
||||
|
||||
//
|
||||
|
||||
Alloc:TfnAlloc;
|
||||
FList:TFieldFetch;
|
||||
|
||||
function c(n1,n2:PsrField):Integer; static;
|
||||
function Cross(o,s:PtrUint):Boolean;
|
||||
function Find_be(o:PtrUint):PsrField;
|
||||
function Find_le(o:PtrUint):PsrField;
|
||||
function First:PsrField;
|
||||
function Last:PsrField;
|
||||
function Next(p:PsrField):PsrField;
|
||||
function Prev(p:PsrField):PsrField;
|
||||
function Fetch(o:PtrUint):PsrField;
|
||||
function FetchValue(_offset,_size:PtrUint;_dtype:TsrDataType):TFieldFetchValue;
|
||||
function FetchRuntimeArray(_offset,_stride:PtrUint):TFieldFetchValue;
|
||||
function IsStructUsedRuntimeArray:Boolean;
|
||||
function IsStructNotUsed:Boolean;
|
||||
function GetStructDecorate:DWORD;
|
||||
procedure FillNode(o,s:PtrUint);
|
||||
function FillSpace:Integer;
|
||||
procedure AllocID;
|
||||
procedure AllocBinding(aType:PsrType;Decorates:PsrDecorateList);
|
||||
end;
|
||||
|
||||
TsrBufferType=(btStorageBuffer,btUniformBuffer,btPushConstant);
|
||||
|
||||
TsrBuffer=object(TsrDescriptor)
|
||||
pLeft,pRight:PsrBuffer;
|
||||
//----
|
||||
|
||||
key:packed record
|
||||
pLayout:PsrDataLayout;
|
||||
CastNum:PtrInt;
|
||||
end;
|
||||
|
||||
bType:TsrBufferType;
|
||||
|
||||
write_count:DWORD;
|
||||
align_offset:DWORD;
|
||||
|
||||
FTop:TsrField;
|
||||
function c(n1,n2:PsrBuffer):Integer; static;
|
||||
function GetTypeChar:Char;
|
||||
function GetString:RawByteString;
|
||||
function GetStructName:RawByteString;
|
||||
procedure UpdateSize;
|
||||
function GetSize:PtrUint;
|
||||
procedure EnumAllField(cb:TFieldEnumCb);
|
||||
procedure ShiftOffset(Offset:PtrUint);
|
||||
end;
|
||||
|
||||
TsrBufferCfg=object
|
||||
SpvVersion:PtrUint;
|
||||
maxUniformBufferRange:PtrUint; // $FFFF
|
||||
PushConstantsOffset:PtrUint; // 0
|
||||
maxPushConstantsSize:PtrUint; // 128
|
||||
minStorageBufferOffsetAlignment:PtrUint; // $10
|
||||
minUniformBufferOffsetAlignment:PtrUint; // $100
|
||||
Procedure Init;
|
||||
Function CanUseStorageBufferClass:Boolean;
|
||||
end;
|
||||
|
||||
TsrBufferList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrBuffer,TsrBuffer>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
cfg:TsrBufferCfg;
|
||||
FNTree:TNodeFetch;
|
||||
FPushConstant:PsrBuffer;
|
||||
procedure Init(cb:TfnAlloc);
|
||||
function Fetch(s:PsrDataLayout;n:PtrInt):PsrBuffer;
|
||||
function NextCast(buf:PsrBuffer):PsrBuffer;
|
||||
Function First:PsrBuffer;
|
||||
Function Next(node:PsrBuffer):PsrBuffer;
|
||||
procedure EnumAllField(cb:TFieldEnumCb);
|
||||
procedure OnFillSpace(node:PsrField);
|
||||
procedure FillSpace;
|
||||
procedure OnAllocID(node:PsrField);
|
||||
procedure AllocID;
|
||||
procedure AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList);
|
||||
procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
procedure UpdateStorage(node:PsrChain;pBuffer:PsrBuffer);
|
||||
procedure ApplyBufferType;
|
||||
procedure AlignOffset(node:PsrBuffer;offset:PtrUint);
|
||||
procedure AlignOffset;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
//---
|
||||
|
||||
function TsrField.c(n1,n2:PsrField):Integer;
|
||||
begin
|
||||
Result:=Integer(n1^.offset>n2^.offset)-Integer(n1^.offset<n2^.offset);
|
||||
end;
|
||||
|
||||
function TsrField.Cross(o,s:PtrUint):Boolean;
|
||||
begin
|
||||
Result:=((o>=offset) and (o<offset+size)) or
|
||||
((offset>=o) and (offset<o+s));
|
||||
end;
|
||||
|
||||
function TsrField.Find_be(o:PtrUint):PsrField;
|
||||
var
|
||||
node:TsrField;
|
||||
begin
|
||||
node:=Default(TsrField);
|
||||
node.offset:=o;
|
||||
Result:=FList.Find_be(@node);
|
||||
end;
|
||||
|
||||
function TsrField.Find_le(o:PtrUint):PsrField;
|
||||
var
|
||||
node:TsrField;
|
||||
begin
|
||||
node:=Default(TsrField);
|
||||
node.offset:=o;
|
||||
Result:=FList.Find_le(@node);
|
||||
end;
|
||||
|
||||
function TsrField.First:PsrField;
|
||||
begin
|
||||
Result:=FList.Min;
|
||||
end;
|
||||
|
||||
function TsrField.Last:PsrField;
|
||||
begin
|
||||
Result:=FList.Max;
|
||||
end;
|
||||
|
||||
function TsrField.Next(p:PsrField):PsrField;
|
||||
begin
|
||||
Result:=FList.Next(p);
|
||||
end;
|
||||
|
||||
function TsrField.Prev(p:PsrField):PsrField;
|
||||
begin
|
||||
Result:=FList.Prev(p);
|
||||
end;
|
||||
|
||||
function TsrField.Fetch(o:PtrUint):PsrField;
|
||||
var
|
||||
node:TsrField;
|
||||
begin
|
||||
node:=Default(TsrField);
|
||||
node.offset:=o;
|
||||
Result:=FList.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrField));
|
||||
Result^.Alloc:=Alloc;
|
||||
Result^.pBuffer:=pBuffer;
|
||||
Result^.parent:=@Self;
|
||||
Result^.offset:=o;
|
||||
Result^.FID:=-1;
|
||||
FList.Insert(Result);
|
||||
Inc(FCount);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrField.FetchValue(_offset,_size:PtrUint;_dtype:TsrDataType):TFieldFetchValue;
|
||||
var
|
||||
node:PsrField;
|
||||
_stride:PtrUint;
|
||||
begin
|
||||
Result:=Default(TFieldFetchValue);
|
||||
|
||||
_stride:=0;
|
||||
if isVector(_dtype) then
|
||||
begin
|
||||
_stride:=BitSizeType(GetVecChild(_dtype)) div 8;
|
||||
end;
|
||||
|
||||
node:=Find_le(_offset);
|
||||
if (node<>nil) then
|
||||
begin
|
||||
if not node^.Cross(_offset,_size) then
|
||||
begin
|
||||
node:=Next(node);
|
||||
if (node<>nil) then
|
||||
begin
|
||||
if not node^.Cross(_offset,_size) then
|
||||
begin
|
||||
node:=nil;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
if (node=nil) then
|
||||
begin
|
||||
//new
|
||||
node:=Fetch(_offset);
|
||||
node^.size :=_size;
|
||||
node^.stride:=_stride;
|
||||
node^.dtype :=_dtype;
|
||||
Result.fValue:=frIdent;
|
||||
Result.pField:=node;
|
||||
end else
|
||||
Case node^.dtype of
|
||||
dtTypeArray:
|
||||
begin
|
||||
if (node^.offset>_offset) then Exit; //ident or big than
|
||||
if (node^.offset+node^.size<_offset+_size) then Exit;
|
||||
if (node^.stride<_size) then Exit; //ident or min stride
|
||||
Result.fValue:=frValueInArray;
|
||||
Result.pField:=node;
|
||||
end;
|
||||
dtTypeRuntimeArray:
|
||||
begin
|
||||
if (node^.offset>_offset) then Exit; //ident or big than
|
||||
if (node^.stride<_size) then Exit; //ident or min stride
|
||||
Result.fValue:=frValueInArray;
|
||||
Result.pField:=node;
|
||||
end;
|
||||
else
|
||||
begin
|
||||
if isVector(node^.dtype) then
|
||||
begin //ftVector
|
||||
if isVector(_dtype) then
|
||||
begin
|
||||
if (node^.offset=_offset) and
|
||||
(node^.size =_size) and
|
||||
(node^.stride=_stride) then
|
||||
begin
|
||||
Result.fValue:=frIdent; //ident
|
||||
Result.pField:=node;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
if (node^.offset>_offset) then Exit; //ident or big than
|
||||
_offset:=_offset-node^.offset;
|
||||
|
||||
if (node^.stride=_size) and
|
||||
(_offset mod node^.stride=0) then
|
||||
begin
|
||||
Result.fValue:=frValueInVector; //down to vector
|
||||
Result.pField:=node;
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
begin //ftValue
|
||||
if isVector(_dtype) then
|
||||
begin
|
||||
if (node^.offset=_offset) and
|
||||
(node^.size =_size) then
|
||||
begin
|
||||
Result.fValue:=frVectorAsValue; //vector as value?
|
||||
Result.pField:=node;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
if (node^.offset=_offset) and
|
||||
(node^.size =_size) then
|
||||
begin
|
||||
Result.fValue:=frIdent; //ident
|
||||
Result.pField:=node;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrField.FetchRuntimeArray(_offset,_stride:PtrUint):TFieldFetchValue;
|
||||
var
|
||||
node:PsrField;
|
||||
begin
|
||||
Result:=Default(TFieldFetchValue);
|
||||
node:=Find_le(_offset);
|
||||
if (node=nil) then
|
||||
begin
|
||||
//new
|
||||
node:=Fetch(_offset);
|
||||
node^.size :=High(PtrUint)-_offset;
|
||||
node^.stride :=_stride;
|
||||
node^.dtype :=dtTypeRuntimeArray;
|
||||
Result.fValue:=frValueInArray;
|
||||
Result.pField:=node;
|
||||
end else
|
||||
if (node^.stride=_stride) and
|
||||
(node^.dtype =dtTypeRuntimeArray) and
|
||||
(node^.offset<=_offset) then //ident or big than
|
||||
begin
|
||||
Result.fValue:=frValueInArray;
|
||||
Result.pField:=node;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrField.IsStructUsedRuntimeArray:Boolean;
|
||||
var
|
||||
node:PsrField;
|
||||
begin
|
||||
Result:=False;
|
||||
if (dtype=dtTypeStruct) then
|
||||
begin
|
||||
node:=FList.Max;
|
||||
if (node<>nil) then
|
||||
begin
|
||||
size:=node^.offset+node^.size;
|
||||
end;
|
||||
Result:=(size=High(PtrUint));
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrField.IsStructNotUsed:Boolean;
|
||||
begin
|
||||
Result:=(FCount<=1) and (parent<>nil);
|
||||
end;
|
||||
|
||||
function TsrField.GetStructDecorate:DWORD;
|
||||
begin
|
||||
Result:=DWORD(-1); //dont use
|
||||
if (parent=nil) then //is top
|
||||
if (dtype=dtTypeStruct) then //is struct
|
||||
begin
|
||||
|
||||
if (pBuffer^.FStorage<>StorageClass.StorageBuffer) and
|
||||
(pBuffer^.bType=btStorageBuffer) then
|
||||
begin
|
||||
Result:=Decoration.BufferBlock;
|
||||
end else
|
||||
begin
|
||||
Result:=Decoration.Block;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrField.FillNode(o,s:PtrUint);
|
||||
|
||||
procedure _Pad(p,v:PtrUint;_dtype:TsrDataType); //inline;
|
||||
var
|
||||
node:PsrField;
|
||||
begin
|
||||
if (o mod p<>0) and (s>=v) then
|
||||
begin
|
||||
node:=Fetch(o);
|
||||
Assert(node^.dtype=dtUnknow,'WTF');
|
||||
node^.size:=v;
|
||||
node^.dtype:=_dtype;
|
||||
o:=o+v;
|
||||
s:=s-v;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure _Fill(v:PtrUint;_dtype:TsrDataType); //inline;
|
||||
var
|
||||
count:PtrUint;
|
||||
node:PsrField;
|
||||
begin
|
||||
count:=s div v;
|
||||
While (count<>0) do
|
||||
begin
|
||||
node:=Fetch(o);
|
||||
Assert(node^.dtype=dtUnknow,'WTF');
|
||||
node^.size:=v;
|
||||
node^.dtype:=_dtype;
|
||||
o:=o+v;
|
||||
s:=s-v;
|
||||
Dec(count);
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
if (s=0) then Exit;
|
||||
|
||||
_Pad ( 2,1,dtUint8);
|
||||
_Pad ( 4,2,dtHalf16);
|
||||
_Pad ( 8,4,dtFloat32);
|
||||
_Pad (16,8,dtVec2f);
|
||||
|
||||
_Fill(16,dtVec4f);
|
||||
_Fill(8 ,dtVec2f);
|
||||
_Fill(4 ,dtFloat32);
|
||||
_Fill(2 ,dtHalf16);
|
||||
_Fill(1 ,dtUint8);
|
||||
end;
|
||||
|
||||
function TsrField.FillSpace:Integer;
|
||||
var
|
||||
pNode:PsrField;
|
||||
Foffset,Fsize:PtrUint;
|
||||
begin
|
||||
Result:=0;
|
||||
pNode:=First;
|
||||
if (pNode=nil) then Exit;
|
||||
|
||||
Foffset:=0;
|
||||
While (pNode<>nil) do
|
||||
begin
|
||||
Assert(pNode^.dtype<>dtUnknow,'WTF');
|
||||
if (Foffset<pNode^.offset) then
|
||||
begin
|
||||
Fsize:=pNode^.offset-Foffset;
|
||||
FillNode(Foffset,Fsize);
|
||||
Inc(Result);
|
||||
end;
|
||||
Foffset:=pNode^.offset+pNode^.size;
|
||||
pNode:=Next(pNode);
|
||||
end;
|
||||
|
||||
if (stride<>0) and (dtype in [dtTypeArray,dtTypeRuntimeArray]) then
|
||||
begin
|
||||
pNode:=FList.Max;
|
||||
if (pNode<>nil) then
|
||||
begin
|
||||
Foffset:=pNode^.offset+pNode^.size;
|
||||
Assert(Foffset<=stride);
|
||||
if (Foffset<stride) then
|
||||
begin
|
||||
Fsize:=stride-Foffset;
|
||||
FillNode(Foffset,Fsize);
|
||||
Inc(Result);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrField.AllocID;
|
||||
var
|
||||
node:PsrField;
|
||||
ID:Integer;
|
||||
begin
|
||||
ID:=0;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if IsVector(dtype) then
|
||||
begin
|
||||
ID:=node^.offset div stride;
|
||||
node^.FID:=ID;
|
||||
end else
|
||||
begin
|
||||
node^.FID:=ID;
|
||||
Inc(ID);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrField.AllocBinding(aType:PsrType;Decorates:PsrDecorateList);
|
||||
var
|
||||
node:PsrField;
|
||||
begin
|
||||
if (aType=nil) then Exit;
|
||||
if (Decorates=nil) then Exit;
|
||||
if isVector(dtype) then Exit;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
Decorates^.emit_member_decorate(ntType,aType,node^.FID,node^.offset);
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
//--
|
||||
|
||||
function TsrBuffer.c(n1,n2:PsrBuffer):Integer;
|
||||
begin
|
||||
//first pLayout
|
||||
Result:=Integer(n1^.key.pLayout>n2^.key.pLayout)-Integer(n1^.key.pLayout<n2^.key.pLayout);
|
||||
if (Result<>0) then Exit;
|
||||
//second CastNum
|
||||
Result:=Integer(n1^.key.CastNum>n2^.key.CastNum)-Integer(n1^.key.CastNum<n2^.key.CastNum);
|
||||
end;
|
||||
|
||||
function TsrBuffer.GetTypeChar:Char;
|
||||
begin
|
||||
Result:=#0;
|
||||
Case bType of
|
||||
btStorageBuffer:Result:='S';
|
||||
btUniformBuffer:Result:='U';
|
||||
btPushConstant :Result:='P';
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrBuffer.GetString:RawByteString;
|
||||
var
|
||||
PID:DWORD;
|
||||
begin
|
||||
PID:=0;
|
||||
if (key.pLayout<>nil) then
|
||||
begin
|
||||
PID:=key.pLayout^.FID;
|
||||
end;
|
||||
Result:='B'+GetTypeChar+
|
||||
';PID='+HexStr(PID,8)+
|
||||
';BND='+HexStr(FBinding,8)+
|
||||
';LEN='+HexStr(GetSize,8)+
|
||||
';OFS='+HexStr(align_offset,8);
|
||||
end;
|
||||
|
||||
function TsrBuffer.GetStructName:RawByteString;
|
||||
begin
|
||||
Result:='TD'+HexStr(FBinding,8);
|
||||
end;
|
||||
|
||||
procedure TsrBuffer.UpdateSize;
|
||||
var
|
||||
node:PsrField;
|
||||
begin
|
||||
node:=FTop.FList.Max;
|
||||
if (node<>nil) then
|
||||
begin
|
||||
FTop.size:=node^.offset+node^.size;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrBuffer.GetSize:PtrUint;
|
||||
begin
|
||||
UpdateSize;
|
||||
Result:=FTop.size;
|
||||
end;
|
||||
|
||||
procedure TsrBuffer.EnumAllField(cb:TFieldEnumCb);
|
||||
var
|
||||
curr,node:PsrField;
|
||||
begin
|
||||
if (cb=nil) then Exit;
|
||||
curr:=@FTop;
|
||||
node:=curr^.First;
|
||||
repeat
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.FList.pRoot<>nil) then //child exist
|
||||
begin
|
||||
curr^.FList._Splay(node); //Move to root
|
||||
curr:=node;
|
||||
node:=curr^.First; //down
|
||||
end else
|
||||
begin
|
||||
cb(node);
|
||||
node:=curr^.Next(node);
|
||||
end;
|
||||
end;
|
||||
cb(curr);
|
||||
curr:=curr^.parent; //up
|
||||
if (curr=nil) then Break;
|
||||
node:=curr^.FList.pRoot; //last find
|
||||
node:=curr^.Next(node);
|
||||
until false;
|
||||
end;
|
||||
|
||||
procedure TsrBuffer.ShiftOffset(Offset:PtrUint);
|
||||
var
|
||||
node:PsrField;
|
||||
begin
|
||||
if (Offset=0) then Exit;
|
||||
node:=FTop.Last;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.offset+node^.size=High(PtrUint)) then
|
||||
begin
|
||||
node^.size:=node^.size-Offset;
|
||||
end;
|
||||
node^.offset:=node^.offset+Offset;
|
||||
node:=FTop.Prev(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrBufferCfg.Init;
|
||||
begin
|
||||
SpvVersion:=$10100;
|
||||
maxUniformBufferRange:=$FFFF;
|
||||
maxPushConstantsSize:=128;
|
||||
minStorageBufferOffsetAlignment:=$10;
|
||||
minUniformBufferOffsetAlignment:=$100;
|
||||
end;
|
||||
|
||||
Function TsrBufferCfg.CanUseStorageBufferClass:Boolean;
|
||||
begin
|
||||
Result:=(SpvVersion>=$10300);
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.Init(cb:TfnAlloc);
|
||||
begin
|
||||
Alloc:=cb;
|
||||
cfg.Init;
|
||||
end;
|
||||
|
||||
function TsrBufferList.Fetch(s:PsrDataLayout;n:PtrInt):PsrBuffer;
|
||||
var
|
||||
node:TsrBuffer;
|
||||
begin
|
||||
node:=Default(TsrBuffer);
|
||||
node.key.pLayout:=s;
|
||||
node.key.CastNum:=n;
|
||||
Result:=FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrBuffer));
|
||||
Result^.key.pLayout:=s;
|
||||
Result^.key.CastNum:=n;
|
||||
Result^.bType :=btStorageBuffer;
|
||||
Result^.FStorage:=StorageClass.Uniform;
|
||||
Result^.FBinding:=-1;
|
||||
Result^.FTop.Alloc:=Alloc;
|
||||
Result^.FTop.pBuffer:=Result;
|
||||
Result^.FTop.FID:=-1;
|
||||
Result^.FTop.dtype:=dtTypeStruct;
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrBufferList.NextCast(buf:PsrBuffer):PsrBuffer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (buf=nil) then Exit;
|
||||
Result:=Fetch(buf^.key.pLayout,buf^.key.CastNum+1);
|
||||
end;
|
||||
|
||||
Function TsrBufferList.First:PsrBuffer;
|
||||
begin
|
||||
Result:=FNTree.Min;
|
||||
end;
|
||||
|
||||
Function TsrBufferList.Next(node:PsrBuffer):PsrBuffer;
|
||||
begin
|
||||
Result:=FNTree.Next(node);
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.EnumAllField(cb:TFieldEnumCb);
|
||||
var
|
||||
node:PsrBuffer;
|
||||
begin
|
||||
if (cb=nil) then Exit;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
node^.EnumAllField(cb);
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.OnFillSpace(node:PsrField);
|
||||
begin
|
||||
node^.FillSpace;
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.FillSpace;
|
||||
begin
|
||||
EnumAllField(@OnFillSpace);
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.OnAllocID(node:PsrField);
|
||||
begin
|
||||
node^.AllocID;
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.AllocID;
|
||||
begin
|
||||
EnumAllField(@OnAllocID);
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList);
|
||||
var
|
||||
node:PsrBuffer;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (Decorates=nil) then Exit;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
begin
|
||||
if (node^.bType<>btPushConstant) then
|
||||
if (node^.FBinding=-1) then //alloc
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Binding,FBinding);
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.DescriptorSet,Decorates^.FDescriptorSet);
|
||||
node^.FBinding:=FBinding;
|
||||
Inc(FBinding);
|
||||
end;
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
var
|
||||
node:PsrBuffer;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (FDebugInfo=nil) then Exit;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
begin
|
||||
FDebugInfo^.emit_source_extension(node^.GetString);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.UpdateStorage(node:PsrChain;pBuffer:PsrBuffer);
|
||||
begin
|
||||
if (node=nil) or (pBuffer=nil) then Exit;
|
||||
pBuffer^.write_count:=pBuffer^.write_count+node^.write_count;
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.ApplyBufferType;
|
||||
var
|
||||
node:PsrBuffer;
|
||||
begin
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.bType=btStorageBuffer) then
|
||||
begin
|
||||
|
||||
if (FPushConstant=nil) and
|
||||
(node^.write_count=0) and
|
||||
(node^.GetSize<=cfg.maxPushConstantsSize) then
|
||||
begin
|
||||
node^.bType :=btPushConstant;
|
||||
node^.FStorage:=StorageClass.PushConstant;
|
||||
FPushConstant:=node;
|
||||
end else
|
||||
if (node^.write_count=0) and
|
||||
(node^.GetSize<=cfg.maxUniformBufferRange) then
|
||||
begin
|
||||
node^.bType :=btUniformBuffer;
|
||||
node^.FStorage:=StorageClass.Uniform;
|
||||
end else
|
||||
if cfg.CanUseStorageBufferClass then
|
||||
begin
|
||||
node^.FStorage:=StorageClass.StorageBuffer;
|
||||
end else
|
||||
begin
|
||||
node^.FStorage:=StorageClass.Uniform;
|
||||
end;
|
||||
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
function AlignShift(addr:Pointer;alignment:PtrUInt):PtrUInt; inline;
|
||||
begin
|
||||
if (alignment>1) then
|
||||
begin
|
||||
Result:=(PtrUInt(addr) mod alignment);
|
||||
end else
|
||||
begin
|
||||
Result:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.AlignOffset(node:PsrBuffer;offset:PtrUint);
|
||||
var
|
||||
P:Pointer;
|
||||
begin
|
||||
P:=node^.key.pLayout^.GetData;
|
||||
offset:=AlignShift(P,offset);
|
||||
node^.align_offset:=offset;
|
||||
node^.ShiftOffset(offset);
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.AlignOffset;
|
||||
var
|
||||
node:PsrBuffer;
|
||||
begin
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
Case node^.bType of
|
||||
btStorageBuffer:
|
||||
begin
|
||||
AlignOffset(node,cfg.minStorageBufferOffsetAlignment);
|
||||
end;
|
||||
btUniformBuffer:
|
||||
begin
|
||||
AlignOffset(node,cfg.minUniformBufferOffsetAlignment);
|
||||
end;
|
||||
btPushConstant:
|
||||
begin
|
||||
node^.align_offset:=cfg.PushConstantsOffset;
|
||||
node^.ShiftOffset(cfg.PushConstantsOffset);
|
||||
end;
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
626
spirv/srCFG.pas
Normal file
626
spirv/srCFG.pas
Normal file
@ -0,0 +1,626 @@
|
||||
unit srCFG;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srNodes,
|
||||
srLabel;
|
||||
|
||||
type
|
||||
PsrCFGBlock=^TsrCFGBlock;
|
||||
|
||||
TsrCFGBlockList=specialize TNodeList<PsrCFGBlock>;
|
||||
|
||||
TsrCFGBlock=object
|
||||
pParent,pPrev,pNext:PsrCFGBlock;
|
||||
|
||||
FList:TsrCFGBlockList;
|
||||
|
||||
pBLabel:PsrLabel;
|
||||
pELabel:PsrLabel;
|
||||
|
||||
bType:TsrBlockType;
|
||||
|
||||
term_id:Integer;
|
||||
|
||||
function IsEndOf(Adr:TSrcAdr):Boolean;
|
||||
function IsBigOf(Adr:TSrcAdr):Boolean;
|
||||
function IsContain(Adr:TSrcAdr):Boolean;
|
||||
function FindBlock(Adr:TSrcAdr):PsrCFGBlock;
|
||||
function DownBlock(Adr:TSrcAdr):PsrCFGBlock;
|
||||
function UpBlock(Adr:TSrcAdr):PsrCFGBlock;
|
||||
function FindUpLoop:PsrCFGBlock;
|
||||
Procedure InsertBlockList(New,child:PsrCFGBlock);
|
||||
function get_level:DWORD;
|
||||
end;
|
||||
|
||||
PsrCodeBlock=^TsrCodeBlock;
|
||||
TsrCodeBlock=object
|
||||
pNext:PsrCodeBlock;
|
||||
//----
|
||||
Alloc:TfnAlloc;
|
||||
Body:Pointer;
|
||||
Size:ptruint;
|
||||
FLabels:TsrLabels;
|
||||
FTop:TsrCFGBlock;
|
||||
Function FindLabel(Adr:TSrcAdr):PsrLabel;
|
||||
Function FetchLabel(Adr:TSrcAdr):PsrLabel;
|
||||
Function IsContain(P:Pointer):Boolean;
|
||||
end;
|
||||
|
||||
TsrCFGParser=object
|
||||
FCursor:TsrLCursor;
|
||||
pCode:PsrCodeBlock;
|
||||
pBlock:PsrCFGBlock;
|
||||
FSPI:TSPI;
|
||||
procedure _print_label(Adr:TSrcAdr);
|
||||
procedure Print(base:Pointer);
|
||||
function Parse(base:Pointer):Byte;
|
||||
function NextParse:Byte;
|
||||
Procedure Finalize;
|
||||
function CheckBlock:Boolean;
|
||||
Procedure CheckLabel;
|
||||
Procedure CheckTerm;
|
||||
function emit_SOP1:Boolean;
|
||||
function emit_SOPP:Boolean;
|
||||
Function NewBlock:PsrCFGBlock;
|
||||
Procedure PushBlock(New:PsrCFGBlock);
|
||||
function PopBlock:Boolean;
|
||||
procedure emit_S_BRANCH;
|
||||
end;
|
||||
|
||||
function parse_code_cfg(bType:TsrBlockType;base:Pointer;pCode:PsrCodeBlock):Byte;
|
||||
|
||||
implementation
|
||||
|
||||
function parse_code_cfg(bType:TsrBlockType;base:Pointer;pCode:PsrCodeBlock):Byte;
|
||||
var
|
||||
LParser:TsrCFGParser;
|
||||
begin
|
||||
pCode^.FTop.bType:=bType;
|
||||
LParser:=Default(TsrCFGParser);
|
||||
LParser.pCode:=pCode;
|
||||
Result:=LParser.Parse(base);
|
||||
|
||||
//LParser.Print(base);
|
||||
end;
|
||||
|
||||
function TsrCFGBlock.IsEndOf(Adr:TSrcAdr):Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
if (pELabel<>nil) then
|
||||
begin
|
||||
Result:=(pELabel^.Adr.get_pc<=Adr.get_pc);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrCFGBlock.IsBigOf(Adr:TSrcAdr):Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
if (pELabel<>nil) then
|
||||
begin
|
||||
Result:=(pELabel^.Adr.get_pc<Adr.get_pc);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrCFGBlock.IsContain(Adr:TSrcAdr):Boolean;
|
||||
var
|
||||
b,e:Boolean;
|
||||
begin
|
||||
b:=true;
|
||||
if (pBLabel<>nil) then
|
||||
begin
|
||||
b:=(pBLabel^.Adr.get_pc<=Adr.get_pc);
|
||||
end;
|
||||
e:=true;
|
||||
if (pELabel<>nil) then
|
||||
begin
|
||||
e:=(pELabel^.Adr.get_pc>Adr.get_pc);
|
||||
end;
|
||||
Result:=b and e;
|
||||
end;
|
||||
|
||||
function TsrCFGBlock.FindBlock(Adr:TSrcAdr):PsrCFGBlock;
|
||||
var
|
||||
node:PsrCFGBlock;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if node^.IsContain(Adr) then Exit(node);
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrCFGBlock.DownBlock(Adr:TSrcAdr):PsrCFGBlock;
|
||||
var
|
||||
next:PsrCFGBlock;
|
||||
begin
|
||||
Result:=@Self;
|
||||
repeat
|
||||
next:=Result^.FindBlock(Adr);
|
||||
if (next=nil) then Exit;
|
||||
Result:=next;
|
||||
until false;
|
||||
end;
|
||||
|
||||
function TsrCFGBlock.UpBlock(Adr:TSrcAdr):PsrCFGBlock;
|
||||
var
|
||||
next:PsrCFGBlock;
|
||||
begin
|
||||
Result:=@Self;
|
||||
While (Result^.IsEndOf(Adr)) do
|
||||
begin
|
||||
next:=Result^.pParent;
|
||||
if (next=nil) then Exit;
|
||||
Result:=next;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrCFGBlock.FindUpLoop:PsrCFGBlock;
|
||||
var
|
||||
node:PsrCFGBlock;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=@Self;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.bType=btLoop) then Exit(node);
|
||||
node:=node^.pParent;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrCFGBlock.InsertBlockList(New,child:PsrCFGBlock);
|
||||
var
|
||||
next:PsrCFGBlock;
|
||||
begin
|
||||
if (New=nil) then Exit;
|
||||
New^.pParent:=@Self;
|
||||
While (child<>nil) do
|
||||
begin
|
||||
Assert(child^.pParent=@Self);
|
||||
next:=child^.pNext;
|
||||
FList.Remove(child);
|
||||
New^.FList.Push_tail(child);
|
||||
child^.pParent:=New;
|
||||
child:=next;
|
||||
end;
|
||||
FList.Push_tail(New);
|
||||
end;
|
||||
|
||||
function TsrCFGBlock.get_level:DWORD;
|
||||
var
|
||||
node:PsrCFGBlock;
|
||||
begin
|
||||
node:=@Self;
|
||||
Result:=0;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
Inc(Result);
|
||||
node:=node^.pParent;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrCFGParser._print_label(Adr:TSrcAdr);
|
||||
var
|
||||
pLabel:PsrLabel;
|
||||
begin
|
||||
pLabel:=pCode^.FindLabel(Adr);
|
||||
if (pLabel<>nil) then
|
||||
begin
|
||||
Write('label_',HexStr(Adr.Offdw*4,4),': ;');
|
||||
|
||||
if (ltBranch in pLabel^.lType) then Write('ltBranch ');
|
||||
if (ltUnknow in pLabel^.lType) then Write('ltUnknow ');
|
||||
if (ltBegAdr in pLabel^.lType) then Write('ltBegAdr ');
|
||||
if (ltEndAdr in pLabel^.lType) then Write('ltEndAdr ');
|
||||
if (ltBegCond in pLabel^.lType) then Write('ltBegCond ');
|
||||
if (ltEndCond in pLabel^.lType) then Write('ltEndCond ');
|
||||
if (ltBegLoop in pLabel^.lType) then Write('ltBegLoop ');
|
||||
if (ltEndLoop in pLabel^.lType) then Write('ltEndLoop ');
|
||||
|
||||
writeln;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrCFGParser.Print(base:Pointer);
|
||||
var
|
||||
Adr:TSrcAdr;
|
||||
level:DWORD;
|
||||
i:Byte;
|
||||
begin
|
||||
FCursor.Init(base);
|
||||
pBlock:=@pCode^.FTop;
|
||||
repeat
|
||||
Adr:=FCursor.Adr;
|
||||
|
||||
pBlock:=pBlock^.DownBlock(Adr);
|
||||
|
||||
level:=pBlock^.get_level;
|
||||
|
||||
_print_label(Adr);
|
||||
|
||||
Write(' ',HexStr(FCursor.OFFSET_DW*4,4));
|
||||
Write(Space(level));
|
||||
|
||||
FSPI:=Default(TSPI);
|
||||
i:=FCursor.Next(FSPI);
|
||||
Case i of
|
||||
0,1:begin
|
||||
|
||||
print_spi(FSPI);
|
||||
|
||||
Adr:=FCursor.Adr;
|
||||
pBlock:=pBlock^.UpBlock(Adr);
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
until (i<>0);
|
||||
_print_label(Adr);
|
||||
end;
|
||||
|
||||
function TsrCFGParser.Parse(base:Pointer):Byte;
|
||||
begin
|
||||
if (pCode=nil) then Exit(4);
|
||||
pCode^.Body:=base;
|
||||
FCursor.Init(base);
|
||||
pBlock:=@pCode^.FTop;
|
||||
pCode^.FTop.pBLabel:=pCode^.FetchLabel(FCursor.Adr);
|
||||
repeat
|
||||
Result:=NextParse;
|
||||
Case Result of
|
||||
0:;
|
||||
1:Break;
|
||||
else
|
||||
Break;
|
||||
end;
|
||||
until false;
|
||||
end;
|
||||
|
||||
function TsrCFGParser.NextParse:Byte;
|
||||
begin
|
||||
FSPI:=Default(TSPI);
|
||||
Result:=FCursor.Next(FSPI);
|
||||
Case Result of
|
||||
0,1:begin
|
||||
Case FSPI.CMD.EN of
|
||||
W_SOP1:if emit_SOP1 then Result:=1;
|
||||
W_SOPP:if emit_SOPP then Result:=1;
|
||||
end;
|
||||
While (CheckBlock) do;
|
||||
if (Result=0) then
|
||||
begin
|
||||
CheckTerm;
|
||||
end;
|
||||
CheckLabel;
|
||||
if (Result=1) then
|
||||
begin
|
||||
Finalize;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrCFGParser.Finalize;
|
||||
begin
|
||||
pCode^.FTop.pELabel:=pCode^.FetchLabel(FCursor.Adr);
|
||||
pCode^.Size:=FCursor.OFFSET_DW*4;
|
||||
end;
|
||||
|
||||
function TsrCFGParser.CheckBlock:Boolean;
|
||||
var
|
||||
pLabel:PsrLabel;
|
||||
begin
|
||||
Result:=False;
|
||||
if (pBlock=nil) then Exit;
|
||||
Result:=pBlock^.IsEndOf(FCursor.Adr);
|
||||
if Result then
|
||||
begin
|
||||
|
||||
Case pBlock^.bType of
|
||||
btAdr:
|
||||
begin
|
||||
pLabel:=pBlock^.pELabel;
|
||||
pLabel^.AddType(ltEndAdr);
|
||||
end;
|
||||
btLoop:
|
||||
begin
|
||||
pLabel:=pBlock^.pELabel;
|
||||
pLabel^.AddType(ltEndLoop);
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
|
||||
PopBlock;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrCFGParser.CheckLabel;
|
||||
var
|
||||
c_adr:TSrcAdr;
|
||||
pLabel:array[0..1] of PsrLabel;
|
||||
node,prev:PsrCFGBlock;
|
||||
begin
|
||||
c_adr:=FCursor.Adr;
|
||||
pLabel[0]:=pCode^.FindLabel(c_adr);
|
||||
if (pLabel[0]=nil) then Exit;
|
||||
|
||||
if not (pLabel[0]^.IsType(ltUnknow)) then Exit;
|
||||
|
||||
prev:=pBlock^.FList.pTail;
|
||||
While (prev<>nil) do
|
||||
begin
|
||||
if prev^.IsContain(c_adr) then Break;
|
||||
prev:=prev^.pPrev;
|
||||
end;
|
||||
if (prev=nil) then Exit;
|
||||
|
||||
if not (prev^.IsContain(c_adr)) then Exit;
|
||||
|
||||
pLabel[1]:=prev^.pBLabel;
|
||||
|
||||
pLabel[0]^.RemType(ltUnknow); //ltEndLoop later
|
||||
pLabel[1]^.AddType(ltBegLoop);
|
||||
|
||||
node:=NewBlock;
|
||||
node^.pBLabel:=pLabel[1];
|
||||
node^.pELabel:=pLabel[0];
|
||||
node^.bType:=btLoop;
|
||||
|
||||
pBlock^.InsertBlockList(node,prev);
|
||||
end;
|
||||
|
||||
Procedure TsrCFGParser.CheckTerm;
|
||||
var
|
||||
c_adr:TSrcAdr;
|
||||
pLabel:array[0..1] of PsrLabel;
|
||||
node,prev:PsrCFGBlock;
|
||||
begin
|
||||
With pBlock^ do
|
||||
begin
|
||||
if (term_id>=0) then Exit;
|
||||
term_id:=Abs(term_id);
|
||||
end;
|
||||
|
||||
c_adr:=FCursor.Adr;
|
||||
|
||||
pLabel[0]:=pCode^.FetchLabel(c_adr);
|
||||
pLabel[1]:=nil;
|
||||
pLabel[0]^.RemType(ltUnknow);
|
||||
pLabel[0]^.AddType(ltBegAdr);
|
||||
|
||||
prev:=pBlock^.pParent;
|
||||
if (prev<>nil) then
|
||||
begin
|
||||
pLabel[1]:=prev^.pELabel;
|
||||
end;
|
||||
|
||||
node:=NewBlock;
|
||||
node^.pBLabel:=pLabel[0];
|
||||
node^.pELabel:=pLabel[1];
|
||||
node^.bType:=btAdr;
|
||||
PushBlock(node);
|
||||
end;
|
||||
|
||||
function TsrCFGParser.emit_SOP1:Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
Case FSPI.SOP1.OP of
|
||||
S_SETPC_B64:if (pBlock^.bType=btSetpc) then Result:=True;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrCFGParser.emit_SOPP:Boolean;
|
||||
var
|
||||
c_adr:TSrcAdr;
|
||||
pLabel:PsrLabel;
|
||||
begin
|
||||
Result:=False;
|
||||
Case FSPI.SOPP.OP of
|
||||
|
||||
S_ENDPGM:
|
||||
begin
|
||||
|
||||
if (pBlock^.bType=btAdr) then
|
||||
begin
|
||||
c_adr:=FCursor.Adr;
|
||||
pLabel:=pCode^.FetchLabel(c_adr);
|
||||
pLabel^.AddType(ltEndAdr);
|
||||
pBlock^.pELabel:=pLabel;
|
||||
PopBlock;
|
||||
end;
|
||||
|
||||
With pBlock^ do
|
||||
begin
|
||||
term_id:=-(Abs(term_id)+1);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
S_CBRANCH_SCC0 ,
|
||||
S_CBRANCH_SCC1 ,
|
||||
S_CBRANCH_VCCZ ,
|
||||
S_CBRANCH_VCCNZ ,
|
||||
S_CBRANCH_EXECZ ,
|
||||
S_CBRANCH_EXECNZ,
|
||||
S_BRANCH :emit_S_BRANCH;
|
||||
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrCodeBlock.FindLabel(Adr:TSrcAdr):PsrLabel;
|
||||
var
|
||||
node:TsrLabel;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=Default(TsrLabel);
|
||||
node.Adr:=Adr;
|
||||
Result:=FLabels.FNTree.Find(@node);
|
||||
end;
|
||||
|
||||
Function TsrCodeBlock.FetchLabel(Adr:TSrcAdr):PsrLabel;
|
||||
var
|
||||
node:TsrLabel;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=Default(TsrLabel);
|
||||
node.Adr:=Adr;
|
||||
Result:=FLabels.FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrLabel));
|
||||
Result^.Adr:=Adr;
|
||||
FLabels.FNTree.Insert(Result);
|
||||
//FLabels.FList.Push_tail(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrCodeBlock.IsContain(P:Pointer):Boolean;
|
||||
begin
|
||||
Result:=(Body<=P) and ((Body+Size)>P);
|
||||
end;
|
||||
|
||||
Function TsrCFGParser.NewBlock:PsrCFGBlock;
|
||||
begin
|
||||
Result:=pCode^.Alloc(SizeOf(TsrCFGBlock));
|
||||
end;
|
||||
|
||||
Procedure TsrCFGParser.PushBlock(New:PsrCFGBlock);
|
||||
begin
|
||||
if (New=nil) then Exit;
|
||||
pBlock^.FList.Push_tail(New);
|
||||
New^.pParent:=pBlock;
|
||||
pBlock:=New;
|
||||
end;
|
||||
|
||||
function TsrCFGParser.PopBlock:Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
if (pBlock=nil) then Exit;
|
||||
if (pBlock^.pParent=nil) then Exit;
|
||||
pBlock:=pBlock^.pParent;
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
procedure TsrCFGParser.emit_S_BRANCH;
|
||||
var
|
||||
pLabel:array[0..1] of PsrLabel;
|
||||
c_adr,b_adr,t_adr:TSrcAdr;
|
||||
node,child,prev,parent:PsrCFGBlock;
|
||||
begin
|
||||
c_adr:=FCursor.Adr;
|
||||
b_adr:=c_adr;
|
||||
b_adr.Offdw:=get_branch_offset(FSPI);
|
||||
|
||||
pLabel[0]:=pCode^.FetchLabel(c_adr);
|
||||
pLabel[1]:=pCode^.FetchLabel(b_adr);
|
||||
pLabel[0]^.AddType(ltBranch);
|
||||
|
||||
if (SmallInt(FSPI.SOPP.SIMM)<0) then //up
|
||||
begin
|
||||
|
||||
child:=nil;
|
||||
parent:=pBlock;
|
||||
|
||||
repeat
|
||||
|
||||
if (parent^.pBLabel=nil) then
|
||||
begin
|
||||
t_adr:=c_adr;
|
||||
t_adr.Offdw:=0;
|
||||
end else
|
||||
begin
|
||||
t_adr:=parent^.pBLabel^.Adr;
|
||||
end;
|
||||
|
||||
if (parent^.bType=btLoop) and (t_adr.get_pc=b_adr.get_pc) then //is exist loop
|
||||
begin
|
||||
pLabel[0]^.RemType(ltUnknow); //ltEndLoop later
|
||||
if (parent^.pELabel=nil) then
|
||||
begin
|
||||
parent^.pELabel:=pLabel[0]; //set end
|
||||
end else
|
||||
begin
|
||||
t_adr:=parent^.pELabel^.Adr;
|
||||
if (t_adr.get_pc<c_adr.get_pc) then
|
||||
begin
|
||||
parent^.pELabel:=pLabel[0]; //update end of loop
|
||||
end;
|
||||
end;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if (t_adr.get_pc<=b_adr.get_pc) then Break;
|
||||
|
||||
child:=parent;
|
||||
parent:=parent^.pParent;
|
||||
until false;
|
||||
|
||||
if (child<>nil) then
|
||||
repeat //up list
|
||||
if child^.IsContain(t_adr) then Assert(false);
|
||||
|
||||
prev:=child^.pPrev;
|
||||
if (prev=nil) then Break;
|
||||
|
||||
if (prev^.pELabel=nil) then
|
||||
begin
|
||||
t_adr:=c_adr;
|
||||
end else
|
||||
begin
|
||||
t_adr:=prev^.pELabel^.Adr;
|
||||
end;
|
||||
|
||||
if (t_adr.get_pc<=b_adr.get_pc) then Break;
|
||||
|
||||
child:=prev;
|
||||
until false;
|
||||
|
||||
//new loop block
|
||||
|
||||
pLabel[0]^.RemType(ltUnknow); //ltEndLoop later
|
||||
pLabel[1]^.AddType(ltBegLoop);
|
||||
|
||||
node:=NewBlock;
|
||||
node^.pBLabel:=pLabel[1];
|
||||
node^.pELabel:=pLabel[0];
|
||||
node^.bType:=btLoop;
|
||||
|
||||
parent^.InsertBlockList(node,child);
|
||||
|
||||
end else //down
|
||||
begin
|
||||
|
||||
if (pBlock^.pELabel<>nil) then
|
||||
if (pBlock^.pELabel^.Adr.get_pc<b_adr.get_pc) then
|
||||
begin
|
||||
//push adr or loop end
|
||||
if not pLabel[1]^.IsType(ltBegAdr) then
|
||||
begin
|
||||
pLabel[1]^.AddType(ltUnknow);
|
||||
end;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
pLabel[0]^.AddType(ltBegCond);
|
||||
pLabel[1]^.AddType(ltEndCond);
|
||||
|
||||
node:=NewBlock;
|
||||
node^.pBLabel:=pLabel[0];
|
||||
node^.pELabel:=pLabel[1];
|
||||
node^.bType:=btCond;
|
||||
PushBlock(node);
|
||||
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
end.
|
||||
|
61
spirv/srCap.pas
Normal file
61
spirv/srCap.pas
Normal file
@ -0,0 +1,61 @@
|
||||
unit srCap;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
srNodes;
|
||||
|
||||
type
|
||||
PSpirvCap=^TSpirvCap;
|
||||
TSpirvCap=object
|
||||
pLeft,pRight:PSpirvCap;
|
||||
//----
|
||||
ID:DWORD;
|
||||
function c(n1,n2:PSpirvCap):Integer; static;
|
||||
end;
|
||||
|
||||
TsrCapList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PSpirvCap,TSpirvCap>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
FNTree:TNodeFetch;
|
||||
procedure Add(ID:DWORD);
|
||||
Function First:PSpirvCap;
|
||||
Function Next(node:PSpirvCap):PSpirvCap;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TSpirvCap.c(n1,n2:PSpirvCap):Integer;
|
||||
begin
|
||||
Result:=Integer(n1^.ID>n2^.ID)-Integer(n1^.ID<n2^.ID);
|
||||
end;
|
||||
|
||||
procedure TsrCapList.Add(ID:DWORD);
|
||||
var
|
||||
fnode:TSpirvCap;
|
||||
pnode:PSpirvCap;
|
||||
begin
|
||||
fnode:=Default(TSpirvCap);
|
||||
fnode.ID:=ID;
|
||||
if (FNTree.Find(@fnode)<>nil) then Exit;
|
||||
pnode:=Alloc(SizeOf(TSpirvCap));
|
||||
Move(fnode,pnode^,SizeOf(TSpirvCap));
|
||||
FNTree.Insert(pnode);
|
||||
end;
|
||||
|
||||
Function TsrCapList.First:PSpirvCap;
|
||||
begin
|
||||
Result:=FNTree.Min;
|
||||
end;
|
||||
|
||||
Function TsrCapList.Next(node:PSpirvCap):PSpirvCap;
|
||||
begin
|
||||
Result:=FNTree.Next(node);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
601
spirv/srConst.pas
Normal file
601
spirv/srConst.pas
Normal file
@ -0,0 +1,601 @@
|
||||
unit srConst;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
srNodes,
|
||||
srRefId,
|
||||
srTypes,
|
||||
half16;
|
||||
|
||||
type
|
||||
PPsrConst=^PsrConst;
|
||||
PsrConst=^TsrConst;
|
||||
TsrConst=object
|
||||
pPrev,pNext,pLeft,pRight:PsrConst;
|
||||
//----
|
||||
read_count:DWORD;
|
||||
ID:TsrRefId; //post id
|
||||
pType:PsrType;
|
||||
key:packed record
|
||||
dtype:TsrDataType;
|
||||
count:DWORD;
|
||||
end;
|
||||
Data:QWORD;
|
||||
function c(n1,n2:PsrConst):Integer; static;
|
||||
Procedure mark_read;
|
||||
Procedure mark_unread;
|
||||
function GetCompItem(i:Byte):PsrConst; inline;
|
||||
Procedure SetCompItem(i:Byte;p:PsrConst); inline;
|
||||
function GetData:QWORD;
|
||||
Function isZeroVal:Boolean; inline;
|
||||
Function isBoolVal:Boolean;
|
||||
Function AsBool:Boolean; inline;
|
||||
Function AsUint:DWORD;
|
||||
function AsInt:Integer; inline;
|
||||
Function AsUint64:QWORD; inline;
|
||||
Function AsInt64:Int64; inline;
|
||||
function AsFloat32:Single;
|
||||
function AsHalf16:THalf16;
|
||||
function AsWord:Word;
|
||||
function AsByte:Byte;
|
||||
Procedure _mark_read_child;
|
||||
Procedure _mark_unread_child;
|
||||
Procedure Clear;
|
||||
end;
|
||||
|
||||
TsrConstList=object
|
||||
type
|
||||
TNodeList=specialize TNodeList<PsrConst>;
|
||||
TNodeFetch=specialize TNodeFetch<PsrConst,TsrConst>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
FList:TNodeList;
|
||||
FNTree:TNodeFetch;
|
||||
function _Fetch(node:PsrConst):PsrConst;
|
||||
function Fetch(dtype:TsrDataType;value:QWORD):PsrConst;
|
||||
function Fetchb(value:Boolean):PsrConst; inline;
|
||||
function Fetchi(dtype:TsrDataType;value:Integer):PsrConst; inline;
|
||||
Function Fetchf(dtype:TsrDataType;value:Single):PsrConst; inline;
|
||||
function Fetch_ssrc9_const(SSRC:Word;d2:DWORD):PsrConst;
|
||||
function Fetch_ssrc9_const(SSRC:Word;d2:DWORD;rtype:TsrDataType):PsrConst;
|
||||
function Fetch_ssrc8_const(SSRC:Byte;d2:DWORD):PsrConst; inline;
|
||||
function Fetch_ssrc8_const(SSRC:Byte;d2:DWORD;rtype:TsrDataType):PsrConst; inline;
|
||||
function Fetch_vec(rtype:TsrDataType;count:Byte;nodes:PPsrConst):PsrConst;
|
||||
function Bitcast(rtype:TsrDataType;old:PsrConst):PsrConst;
|
||||
end;
|
||||
|
||||
function get_soffset_const_int(SSRC:Word):Integer;
|
||||
function is_const_soffset(SSRC:Byte):Boolean; inline;
|
||||
function is_const_ssrc8(SSRC:Byte):Boolean; inline;
|
||||
function is_const_ssrc9(SSRC:Word):Boolean; inline;
|
||||
function CompareConst(r1,r2:PsrConst):Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
function TsrConst.c(n1,n2:PsrConst):Integer;
|
||||
var
|
||||
count:DWORD;
|
||||
begin
|
||||
Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrConst.key));
|
||||
if (Result<>0) then Exit;
|
||||
count:=n1^.key.count;
|
||||
if (count=0) then
|
||||
begin
|
||||
Result:=Integer(n1^.Data>n2^.Data)-Integer(n1^.Data<n2^.Data);
|
||||
end else
|
||||
begin
|
||||
Result:=ComparePtruint(@n1^.Data,@n2^.Data,count);
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrConst.mark_read;
|
||||
begin
|
||||
Inc(read_count);
|
||||
end;
|
||||
|
||||
Procedure TsrConst.mark_unread;
|
||||
begin
|
||||
Assert(read_count<>0);
|
||||
if (read_count<>0) then Dec(read_count);
|
||||
end;
|
||||
|
||||
function TsrConst.GetCompItem(i:Byte):PsrConst; inline;
|
||||
begin
|
||||
Result:=PPsrConst(@Data)[i];
|
||||
end;
|
||||
|
||||
Procedure TsrConst.SetCompItem(i:Byte;p:PsrConst); inline;
|
||||
begin
|
||||
PPsrConst(@Data)[i]:=p;
|
||||
end;
|
||||
|
||||
function TsrConst.GetData:QWORD;
|
||||
begin
|
||||
Result:=0;
|
||||
case key.dtype of
|
||||
dtVec2f:
|
||||
begin
|
||||
PSingle(@Result)[0]:=GetCompItem(0)^.AsFloat32;
|
||||
PSingle(@Result)[1]:=GetCompItem(1)^.AsFloat32;
|
||||
end;
|
||||
dtVec2h:
|
||||
begin
|
||||
PHalf16(@Result)[0]:=GetCompItem(0)^.AsHalf16;
|
||||
PHalf16(@Result)[1]:=GetCompItem(1)^.AsHalf16;
|
||||
end;
|
||||
dtVec4h:
|
||||
begin
|
||||
PHalf16(@Result)[0]:=GetCompItem(0)^.AsHalf16;
|
||||
PHalf16(@Result)[1]:=GetCompItem(1)^.AsHalf16;
|
||||
PHalf16(@Result)[2]:=GetCompItem(2)^.AsHalf16;
|
||||
PHalf16(@Result)[3]:=GetCompItem(3)^.AsHalf16;
|
||||
end;
|
||||
dtStruct2u:
|
||||
begin
|
||||
PDWord(@Result)[0]:=GetCompItem(0)^.AsUint;
|
||||
PDWord(@Result)[1]:=GetCompItem(1)^.AsUint;
|
||||
end;
|
||||
else
|
||||
begin
|
||||
Assert(key.count=0,'count<>0');
|
||||
Result:=data;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrConst.isZeroVal:Boolean;
|
||||
begin
|
||||
case key.dtype of
|
||||
dtInt32 ,
|
||||
dtUint32 ,
|
||||
dtFloat32:Result:=(AsUint=0);
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrConst.isBoolVal:Boolean;
|
||||
begin
|
||||
if (key.count<>0) then Exit(False);
|
||||
Case Data of
|
||||
0,1:Result:=True;
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrConst.AsBool:Boolean; inline;
|
||||
begin
|
||||
Result:=PBoolean(@Data)^;
|
||||
end;
|
||||
|
||||
Function TsrConst.AsUint:DWORD;
|
||||
begin
|
||||
Result:=PDWORD(@Data)^;
|
||||
end;
|
||||
|
||||
function TsrConst.AsInt:Integer; inline;
|
||||
begin
|
||||
Result:=PInteger(@Data)^;
|
||||
end;
|
||||
|
||||
Function TsrConst.AsUint64:QWORD; inline;
|
||||
begin
|
||||
Result:=Data;
|
||||
end;
|
||||
|
||||
Function TsrConst.AsInt64:Int64; inline;
|
||||
begin
|
||||
Result:=Int64(Data);
|
||||
end;
|
||||
|
||||
function TsrConst.AsFloat32:Single;
|
||||
begin
|
||||
Result:=PSingle(@Data)^;
|
||||
end;
|
||||
|
||||
function TsrConst.AsHalf16:THalf16;
|
||||
begin
|
||||
Result:=PHalf16(@Data)^
|
||||
end;
|
||||
|
||||
function TsrConst.AsWord:Word;
|
||||
begin
|
||||
Result:=PWord(@Data)^;
|
||||
end;
|
||||
|
||||
function TsrConst.AsByte:Byte;
|
||||
begin
|
||||
Result:=PByte(@Data)^;
|
||||
end;
|
||||
|
||||
Procedure TsrConst._mark_read_child;
|
||||
var
|
||||
i:DWORD;
|
||||
begin
|
||||
if (key.count<>0) then
|
||||
For i:=0 to key.count-1 do
|
||||
begin
|
||||
GetCompItem(i)^.mark_read;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrConst._mark_unread_child;
|
||||
var
|
||||
i:DWORD;
|
||||
begin
|
||||
if (key.count<>0) then
|
||||
For i:=0 to key.count-1 do
|
||||
begin
|
||||
GetCompItem(i)^.mark_unread;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrConst.Clear;
|
||||
var
|
||||
i:DWORD;
|
||||
begin
|
||||
if (key.count<>0) then
|
||||
begin
|
||||
For i:=0 to key.count-1 do
|
||||
begin
|
||||
GetCompItem(i)^.mark_unread;
|
||||
end;
|
||||
key.count:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrConstList._Fetch(node:PsrConst):PsrConst;
|
||||
var
|
||||
size:DWORD;
|
||||
begin
|
||||
Result:=FNTree.Find(node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
size:=node^.key.count;
|
||||
if (size=0) then
|
||||
size:=SizeOf(TsrConst)
|
||||
else
|
||||
size:=SizeOf(TsrConst)-SizeOf(TsrConst.Data)+SizeOf(Pointer)*size;
|
||||
Result:=Alloc(size);
|
||||
Move(node^,Result^,size);
|
||||
FNTree.Insert(Result);
|
||||
FList.Push_tail(Result);
|
||||
end else
|
||||
begin
|
||||
node^._mark_unread_child;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrConstList.Fetch(dtype:TsrDataType;value:QWORD):PsrConst;
|
||||
var
|
||||
rec:record
|
||||
node:TsrConst;
|
||||
align:array[0..3] of Pointer;
|
||||
end;
|
||||
h:array[0..3] of PsrConst;
|
||||
begin
|
||||
Result:=nil;
|
||||
rec.node:=Default(TsrConst);
|
||||
|
||||
value:=value and GetTypeHigh(dtype);
|
||||
|
||||
Case dtype of
|
||||
dtUnknow,
|
||||
dtBool,
|
||||
dtFloat32,
|
||||
dtHalf16,
|
||||
dtInt32,
|
||||
dtUint32,
|
||||
dtInt64,
|
||||
dtUint64:
|
||||
|
||||
begin
|
||||
rec.node.key.dtype:=dtype;
|
||||
rec.node.Data:=value;
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
dtStruct2u,
|
||||
dtVec2u,
|
||||
dtVec2i,
|
||||
dtVec2f:
|
||||
begin
|
||||
rec.node.key.dtype:=GetVecChild(dtype);
|
||||
rec.node.Data:=PDWORD(@value)[0];
|
||||
h[0]:=_Fetch(@rec.node);
|
||||
h[0]^.mark_read;
|
||||
rec.node.Data:=PDWORD(@value)[1];
|
||||
h[1]:=_Fetch(@rec.node);
|
||||
h[1]^.mark_read;
|
||||
rec.node.key.dtype:=dtype;
|
||||
rec.node.key.count:=2;
|
||||
rec.node.SetCompItem(0,h[0]);
|
||||
rec.node.SetCompItem(1,h[1]);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
dtVec2h:
|
||||
begin
|
||||
rec.node.key.dtype:=dtHalf16;
|
||||
rec.node.Data:=PWORD(@value)[0];
|
||||
h[0]:=_Fetch(@rec.node);
|
||||
h[0]^.mark_read;
|
||||
rec.node.Data:=PWORD(@value)[1];
|
||||
h[1]:=_Fetch(@rec.node);
|
||||
h[1]^.mark_read;
|
||||
rec.node.key.dtype:=dtVec2h;
|
||||
rec.node.key.count:=2;
|
||||
rec.node.SetCompItem(0,h[0]);
|
||||
rec.node.SetCompItem(1,h[1]);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
dtVec4h:
|
||||
begin
|
||||
rec.node.key.dtype:=dtHalf16;
|
||||
rec.node.Data:=PWORD(@value)[0];
|
||||
h[0]:=_Fetch(@rec.node);
|
||||
h[0]^.mark_read;
|
||||
rec.node.Data:=PWORD(@value)[1];
|
||||
h[1]:=_Fetch(@rec.node);
|
||||
h[1]^.mark_read;
|
||||
rec.node.Data:=PWORD(@value)[2];
|
||||
h[2]:=_Fetch(@rec.node);
|
||||
h[2]^.mark_read;
|
||||
rec.node.Data:=PWORD(@value)[3];
|
||||
h[3]:=_Fetch(@rec.node);
|
||||
h[3]^.mark_read;
|
||||
rec.node.key.dtype:=dtVec4h;
|
||||
rec.node.key.count:=4;
|
||||
rec.node.SetCompItem(0,h[0]);
|
||||
rec.node.SetCompItem(1,h[1]);
|
||||
rec.node.SetCompItem(2,h[2]);
|
||||
rec.node.SetCompItem(3,h[3]);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
function TsrConstList.Fetchb(value:Boolean):PsrConst; inline;
|
||||
begin
|
||||
Result:=Fetch(dtBool,QWORD(value));
|
||||
end;
|
||||
|
||||
function TsrConstList.Fetchi(dtype:TsrDataType;value:Integer):PsrConst; inline;
|
||||
begin
|
||||
Result:=Fetch(dtype,PDWORD(@value)^);
|
||||
end;
|
||||
|
||||
Function TsrConstList.Fetchf(dtype:TsrDataType;value:Single):PsrConst; inline;
|
||||
begin
|
||||
Result:=Fetch(dtype,PDWORD(@value)^);
|
||||
end;
|
||||
|
||||
function TsrConstList.Fetch_ssrc9_const(SSRC:Word;d2:DWORD):PsrConst;
|
||||
begin
|
||||
Case SSRC of
|
||||
128:Result:=Fetch(dtUnknow,0);
|
||||
129..192:Result:=Fetch(dtUint32,SSRC-128);
|
||||
193..208:Result:=Fetchi(dtInt32,-(SSRC-192));
|
||||
240:Result:=Fetchf(dtFloat32, 0.5);
|
||||
241:Result:=Fetchf(dtFloat32,-0.5);
|
||||
242:Result:=Fetchf(dtFloat32, 1.0);
|
||||
243:Result:=Fetchf(dtFloat32,-1.0);
|
||||
244:Result:=Fetchf(dtFloat32, 2.0);
|
||||
245:Result:=Fetchf(dtFloat32,-2.0);
|
||||
246:Result:=Fetchf(dtFloat32, 4.0);
|
||||
247:Result:=Fetchf(dtFloat32,-4.0);
|
||||
255:Result:=Fetch(dtUnknow,d2);
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrConstList.Fetch_ssrc9_const(SSRC:Word;d2:DWORD;rtype:TsrDataType):PsrConst;
|
||||
begin
|
||||
Case SSRC of
|
||||
128:Result:=Fetch(rtype,0);
|
||||
129..192:
|
||||
begin
|
||||
if CompareType(dtUint32,rtype) then
|
||||
begin
|
||||
Result:=Fetch(dtUint32,SSRC-128);
|
||||
end else
|
||||
begin
|
||||
Result:=Fetch(rtype,SSRC-128);
|
||||
end;
|
||||
end;
|
||||
193..208:
|
||||
begin
|
||||
if CompareType(dtInt32,rtype) then
|
||||
begin
|
||||
Result:=Fetchi(dtInt32,-(SSRC-192));
|
||||
end else
|
||||
begin
|
||||
Result:=Fetchi(rtype,-(SSRC-192));
|
||||
end;
|
||||
end;
|
||||
240:Result:=Fetchf(rtype, 0.5);
|
||||
241:Result:=Fetchf(rtype,-0.5);
|
||||
242:Result:=Fetchf(rtype, 1.0);
|
||||
243:Result:=Fetchf(rtype,-1.0);
|
||||
244:Result:=Fetchf(rtype, 2.0);
|
||||
245:Result:=Fetchf(rtype,-2.0);
|
||||
246:Result:=Fetchf(rtype, 4.0);
|
||||
247:Result:=Fetchf(rtype,-4.0);
|
||||
255:Result:=Fetch(rtype,d2);
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrConstList.Fetch_ssrc8_const(SSRC:Byte;d2:DWORD):PsrConst; inline;
|
||||
begin
|
||||
Result:=Fetch_ssrc9_const(SSRC,d2);
|
||||
end;
|
||||
|
||||
function TsrConstList.Fetch_ssrc8_const(SSRC:Byte;d2:DWORD;rtype:TsrDataType):PsrConst; inline;
|
||||
begin
|
||||
Result:=Fetch_ssrc9_const(SSRC,d2,rtype);
|
||||
end;
|
||||
|
||||
function TsrConstList.Fetch_vec(rtype:TsrDataType;count:Byte;nodes:PPsrConst):PsrConst;
|
||||
var
|
||||
rec:record
|
||||
node:TsrConst;
|
||||
align:array[0..3] of Pointer;
|
||||
end;
|
||||
h:PsrConst;
|
||||
i:Byte;
|
||||
begin
|
||||
Assert(count<>0);
|
||||
Assert(count<=4);
|
||||
rec.node:=Default(TsrConst);
|
||||
rec.node.key.dtype:=rtype;
|
||||
rec.node.key.count:=count;
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
h:=nodes[i];
|
||||
h^.mark_read;
|
||||
rec.node.SetCompItem(i,h);
|
||||
end;
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
function TsrConstList.Bitcast(rtype:TsrDataType;old:PsrConst):PsrConst;
|
||||
var
|
||||
data:qword;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (old=nil) then Exit;
|
||||
if (rtype=dtUnknow) or (rtype=old^.key.dtype) then
|
||||
begin
|
||||
old^.mark_read;
|
||||
Exit(old);
|
||||
end;
|
||||
|
||||
if (old^.key.dtype=dtUnknow) then
|
||||
begin
|
||||
data:=old^.Data;
|
||||
Result:=Fetch(rtype,data);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if TryBitcastType(rtype,old^.key.dtype) then
|
||||
begin
|
||||
data:=old^.GetData;
|
||||
Result:=Fetch(rtype,data);
|
||||
end else
|
||||
begin
|
||||
Assert(false,'const bitcast');
|
||||
end;
|
||||
end;
|
||||
|
||||
function get_soffset_const_int(SSRC:Word):Integer;
|
||||
type
|
||||
TRec=packed record
|
||||
Case byte of
|
||||
0:(i:Integer);
|
||||
1:(s:Single);
|
||||
end;
|
||||
begin
|
||||
Case SSRC of
|
||||
128:Result:=0;
|
||||
129..192:Result:=SSRC-128;
|
||||
193..208:Result:=-(SSRC-192);
|
||||
240:TRec(Result).s:= 0.5;
|
||||
241:TRec(Result).s:=-0.5;
|
||||
242:TRec(Result).s:= 1.0;
|
||||
243:TRec(Result).s:=-1.0;
|
||||
244:TRec(Result).s:= 2.0;
|
||||
245:TRec(Result).s:=-2.0;
|
||||
246:TRec(Result).s:= 4.0;
|
||||
247:TRec(Result).s:=-4.0;
|
||||
else
|
||||
Result:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
function is_const_soffset(SSRC:Byte):Boolean; inline;
|
||||
begin
|
||||
Case SSRC of
|
||||
128..192,
|
||||
193..208,
|
||||
240..247:Result:=True;
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function is_const_ssrc8(SSRC:Byte):Boolean; inline;
|
||||
begin
|
||||
Case SSRC of
|
||||
128..192,
|
||||
193..208,
|
||||
240..247,
|
||||
255:Result:=True;
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function is_const_ssrc9(SSRC:Word):Boolean; inline;
|
||||
begin
|
||||
Case SSRC of
|
||||
128..192,
|
||||
193..208,
|
||||
240..247,
|
||||
255:Result:=True;
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function CompareConstCount(buf1,buf2:PPsrConst;count:PtrUint):Boolean;
|
||||
begin
|
||||
Result:=true;
|
||||
While (count<>0) do
|
||||
begin
|
||||
Result:=CompareConst(buf1^,buf2^);
|
||||
if not Result then Exit;
|
||||
Inc(buf1);
|
||||
Inc(buf2);
|
||||
Dec(count);
|
||||
end;
|
||||
end;
|
||||
|
||||
function CompareConst(r1,r2:PsrConst):Boolean;
|
||||
begin
|
||||
Result:=false;
|
||||
if (r1<>nil) and (r2<>nil) then
|
||||
begin
|
||||
Result:=(r1=r2);
|
||||
if Result then Exit;
|
||||
if CompareType(r1^.key.dtype,r2^.key.dtype) and (r1^.key.count=r2^.key.count) then
|
||||
begin
|
||||
if (r1^.key.count=0) then
|
||||
begin
|
||||
Result:=(r1^.Data=r2^.Data);
|
||||
end else
|
||||
begin
|
||||
Result:=CompareConstCount(@r1^.Data,@r2^.Data,r1^.key.count);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
80
spirv/srDecorate.pas
Normal file
80
spirv/srDecorate.pas
Normal file
@ -0,0 +1,80 @@
|
||||
unit srDecorate;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
spirv,
|
||||
srNodes,
|
||||
srOp;
|
||||
|
||||
type
|
||||
PsrDecorateList=^TsrDecorateList;
|
||||
TsrDecorateList=object(TsrOpBlockSimple)
|
||||
FDescriptorSet:DWORD;
|
||||
procedure emit_decorate(ntype:TsrNodeType;Data:Pointer;dec_id,param:DWORD);
|
||||
procedure emit_member_decorate(ntype:TsrNodeType;Data:Pointer;index,offset:DWORD);
|
||||
end;
|
||||
|
||||
PsrDebugInfoList=^TsrDebugInfoList;
|
||||
TsrDebugInfoList=object(TsrOpBlockSimple)
|
||||
procedure emit_source_extension(const n:RawByteString);
|
||||
procedure emit_name(ntype:TsrNodeType;Data:Pointer;const n:RawByteString);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TsrDecorateList.emit_decorate(ntype:TsrNodeType;Data:Pointer;dec_id,param:DWORD);
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
node:=AddSpirvOp(Op.OpDecorate);
|
||||
node^.AddParam(ntype,Data);
|
||||
node^.AddLiteral(dec_id,Decoration.GetStr(dec_id));
|
||||
Case dec_id of
|
||||
Decoration.BuiltIn:
|
||||
node^.AddLiteral(param,BuiltIn.GetStr(param));
|
||||
|
||||
Decoration.ArrayStride,
|
||||
Decoration.MatrixStride,
|
||||
Decoration.Location,
|
||||
Decoration.Index,
|
||||
Decoration.Binding,
|
||||
Decoration.DescriptorSet:
|
||||
node^.AddLiteral(param);
|
||||
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrDecorateList.emit_member_decorate(ntype:TsrNodeType;Data:Pointer;index,offset:DWORD);
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
node:=AddSpirvOp(Op.OpMemberDecorate);
|
||||
node^.AddParam(ntype,Data);
|
||||
node^.AddLiteral(index);
|
||||
node^.AddLiteral(Decoration.Offset,Decoration.GetStr(Decoration.Offset));
|
||||
node^.AddLiteral(offset);
|
||||
end;
|
||||
|
||||
procedure TsrDebugInfoList.emit_source_extension(const n:RawByteString);
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
node:=AddSpirvOp(Op.OpSourceExtension);
|
||||
node^.AddString(n);
|
||||
end;
|
||||
|
||||
procedure TsrDebugInfoList.emit_name(ntype:TsrNodeType;Data:Pointer;const n:RawByteString);
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
node:=AddSpirvOp(Op.OpName);
|
||||
node^.AddParam(ntype,Data);
|
||||
node^.AddString(n);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
182
spirv/srFragLayout.pas
Normal file
182
spirv/srFragLayout.pas
Normal file
@ -0,0 +1,182 @@
|
||||
unit srFragLayout;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
srNodes,
|
||||
srReg,
|
||||
srOp,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srInput,
|
||||
srDecorate;
|
||||
|
||||
type
|
||||
//itPerspSample, //Sample
|
||||
//itPerspCenter,
|
||||
//itPerspCentroid, //Centroid
|
||||
//itLinearSample, //NoPerspective Sample
|
||||
//itLinearCenter, //NoPerspective
|
||||
//itLinearCentroid, //NoPerspective Centroid
|
||||
|
||||
PsrFragLayout=^TsrFragLayout;
|
||||
TsrFragLayout=object(TsrDescriptor)
|
||||
pLeft,pRight:PsrFragLayout;
|
||||
//----
|
||||
itype:TpsslInputType;
|
||||
|
||||
pReg:PsrRegNode;
|
||||
|
||||
function c(n1,n2:PsrFragLayout):Integer; static;
|
||||
function GetName:RawByteString;
|
||||
end;
|
||||
|
||||
TsrFragLayoutList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrFragLayout,TsrFragLayout>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
FNTree:TNodeFetch;
|
||||
procedure Init(cb:TfnAlloc);
|
||||
function Fetch(itype:TpsslInputType;location:DWORD):PsrFragLayout;
|
||||
Function First:PsrFragLayout;
|
||||
Function Next(node:PsrFragLayout):PsrFragLayout;
|
||||
procedure AllocBinding(Decorates:PsrDecorateList);
|
||||
procedure AllocEntryPoint(EntryPoint:PSpirvOp);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TsrFragLayout.c(n1,n2:PsrFragLayout):Integer;
|
||||
begin
|
||||
//first itype
|
||||
Result:=Integer(n1^.itype>n2^.itype)-Integer(n1^.itype<n2^.itype);
|
||||
//second location
|
||||
Result:=Integer(n1^.FBinding>n2^.FBinding)-Integer(n1^.FBinding<n2^.FBinding);
|
||||
//Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrFragLayout.key));
|
||||
end;
|
||||
|
||||
function TsrFragLayout.GetName:RawByteString;
|
||||
begin
|
||||
Case itype of
|
||||
itPerspSample:
|
||||
Result:='itPSample'+IntToStr(FBinding);
|
||||
itPerspCenter:
|
||||
Result:='itParam'+IntToStr(FBinding);
|
||||
itPerspCentroid:
|
||||
Result:='itPCentroid'+IntToStr(FBinding);
|
||||
itLinearSample:
|
||||
Result:='itLSample'+IntToStr(FBinding);
|
||||
itLinearCenter:
|
||||
Result:='itLCenter'+IntToStr(FBinding);
|
||||
itLinearCentroid:
|
||||
Result:='itLCentroid'+IntToStr(FBinding);
|
||||
else
|
||||
Result:='';
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrFragLayoutList.Init(cb:TfnAlloc);
|
||||
begin
|
||||
Alloc:=cb;
|
||||
end;
|
||||
|
||||
function TsrFragLayoutList.Fetch(itype:TpsslInputType;location:DWORD):PsrFragLayout;
|
||||
var
|
||||
node:TsrFragLayout;
|
||||
begin
|
||||
node:=Default(TsrFragLayout);
|
||||
node.itype:=itype;
|
||||
node.FStorage:=StorageClass.Input;
|
||||
node.FBinding:=location;
|
||||
Result:=FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrFragLayout));
|
||||
Move(node,Result^,SizeOf(TsrFragLayout));
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrFragLayoutList.First:PsrFragLayout;
|
||||
begin
|
||||
Result:=FNTree.Min;
|
||||
end;
|
||||
|
||||
Function TsrFragLayoutList.Next(node:PsrFragLayout):PsrFragLayout;
|
||||
begin
|
||||
Result:=FNTree.Next(node);
|
||||
end;
|
||||
|
||||
procedure TsrFragLayoutList.AllocBinding(Decorates:PsrDecorateList);
|
||||
var
|
||||
node:PsrFragLayout;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (Decorates=nil) then Exit;
|
||||
//interpolate param
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,node^.FBinding);
|
||||
|
||||
case node^.itype of
|
||||
itPerspSample: //Sample
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Sample,0);
|
||||
end;
|
||||
itPerspCenter:; //default
|
||||
itPerspCentroid: //Centroid
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Centroid,0);
|
||||
end;
|
||||
itLinearSample: //NoPerspective Sample
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.NoPerspective,0);
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Sample,0);
|
||||
end;
|
||||
itLinearCenter: //NoPerspective
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.NoPerspective,0);
|
||||
end;
|
||||
itLinearCentroid: //NoPerspective Centroid
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.NoPerspective,0);
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Centroid,0);
|
||||
end;
|
||||
else
|
||||
Assert(false,'AllocBinding');
|
||||
end;
|
||||
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrFragLayoutList.AllocEntryPoint(EntryPoint:PSpirvOp);
|
||||
var
|
||||
node:PsrFragLayout;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (EntryPoint=nil) then Exit;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
begin
|
||||
EntryPoint^.AddParam(ntVar,pVar);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
200
spirv/srInput.pas
Normal file
200
spirv/srInput.pas
Normal file
@ -0,0 +1,200 @@
|
||||
unit srInput;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
typinfo,
|
||||
sysutils,
|
||||
spirv,
|
||||
srNodes,
|
||||
srReg,
|
||||
srOp,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srDecorate;
|
||||
|
||||
type
|
||||
TpsslInputType=(
|
||||
itUnknow,
|
||||
|
||||
itVsState,
|
||||
|
||||
itWriteIndex,
|
||||
itOffset,
|
||||
itWaveId,
|
||||
itScratch,
|
||||
|
||||
itVIndex,
|
||||
itVInstance,
|
||||
|
||||
itPsState,
|
||||
itWaveCnt,
|
||||
|
||||
itPerspSample,
|
||||
itPerspCenter,
|
||||
itPerspCentroid,
|
||||
itPerspW,
|
||||
itLinearSample,
|
||||
itLinearCenter,
|
||||
itLinearCentroid,
|
||||
|
||||
itFloatPos,
|
||||
itFrontFace,
|
||||
itAncillary,
|
||||
itSampleCoverage,
|
||||
itPosFixed,
|
||||
|
||||
itTgid,
|
||||
itTgSize,
|
||||
|
||||
itThreadId
|
||||
|
||||
);
|
||||
|
||||
PsrInput=^TsrInput;
|
||||
|
||||
TsrInput=object(TsrDescriptor)
|
||||
pLeft,pRight:PsrInput;
|
||||
//----
|
||||
|
||||
key:packed record
|
||||
itype:TpsslInputType;
|
||||
typeid:Byte;
|
||||
end;
|
||||
|
||||
pReg:PsrRegNode;
|
||||
|
||||
function c(n1,n2:PsrInput):Integer; static;
|
||||
function GetName:RawByteString;
|
||||
end;
|
||||
|
||||
TsrInputList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrInput,TsrInput>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
FNTree:TNodeFetch;
|
||||
procedure Init(cb:TfnAlloc);
|
||||
function Search(itype:TpsslInputType;id:Byte=0):PsrInput;
|
||||
function Fetch(itype:TpsslInputType;id:Byte=0):PsrInput;
|
||||
Function First:PsrInput;
|
||||
Function Next(node:PsrInput):PsrInput;
|
||||
procedure AllocBinding(Decorates:PsrDecorateList);
|
||||
procedure AllocEntryPoint(EntryPoint:PSpirvOp);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TsrInput.c(n1,n2:PsrInput):Integer;
|
||||
begin
|
||||
Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrInput.key));
|
||||
end;
|
||||
|
||||
function TsrInput.GetName:RawByteString;
|
||||
begin
|
||||
Result:=GetEnumName(TypeInfo(TpsslInputType),ord(key.itype))+IntToStr(key.typeid);
|
||||
end;
|
||||
|
||||
procedure TsrInputList.Init(cb:TfnAlloc);
|
||||
begin
|
||||
Alloc:=cb;
|
||||
end;
|
||||
|
||||
function TsrInputList.Search(itype:TpsslInputType;id:Byte=0):PsrInput;
|
||||
var
|
||||
node:TsrInput;
|
||||
begin
|
||||
node:=Default(TsrInput);
|
||||
node.key.itype:=itype;
|
||||
node.key.typeid:=id;
|
||||
Result:=FNTree.Find(@node);
|
||||
end;
|
||||
|
||||
function TsrInputList.Fetch(itype:TpsslInputType;id:Byte=0):PsrInput;
|
||||
var
|
||||
node:TsrInput;
|
||||
begin
|
||||
node:=Default(TsrInput);
|
||||
node.key.itype:=itype;
|
||||
node.key.typeid:=id;
|
||||
node.FStorage:=StorageClass.Input;
|
||||
node.FBinding:=-1;
|
||||
Result:=FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrInput));
|
||||
Move(node,Result^,SizeOf(TsrInput));
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrInputList.First:PsrInput;
|
||||
begin
|
||||
Result:=FNTree.Min;
|
||||
end;
|
||||
|
||||
Function TsrInputList.Next(node:PsrInput):PsrInput;
|
||||
begin
|
||||
Result:=FNTree.Next(node);
|
||||
end;
|
||||
|
||||
procedure TsrInputList.AllocBinding(Decorates:PsrDecorateList);
|
||||
var
|
||||
node:PsrInput;
|
||||
pVar:PsrVariable;
|
||||
|
||||
begin
|
||||
if (Decorates=nil) then Exit;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
begin
|
||||
Case node^.key.itype of
|
||||
itFloatPos:
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.FragCoord);
|
||||
end;
|
||||
itTgid:
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.WorkgroupId);
|
||||
end;
|
||||
itThreadId:
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.LocalInvocationID);
|
||||
end;
|
||||
itVIndex:
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.VertexIndex);
|
||||
end;
|
||||
else
|
||||
Assert(false,'AllocBinding');
|
||||
end;
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrInputList.AllocEntryPoint(EntryPoint:PSpirvOp);
|
||||
var
|
||||
node:PsrInput;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (EntryPoint=nil) then Exit;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
begin
|
||||
EntryPoint^.AddParam(ntVar,pVar);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
111
spirv/srLabel.pas
Normal file
111
spirv/srLabel.pas
Normal file
@ -0,0 +1,111 @@
|
||||
unit srLabel;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srNodes;
|
||||
|
||||
type
|
||||
TSrcAdr=object
|
||||
pBody:PDWORD;
|
||||
Offdw:ptrint;
|
||||
function get_pc:PDWORD;
|
||||
end;
|
||||
|
||||
TsrLCursor=object(TShaderParser)
|
||||
private
|
||||
function get_src_adr:TSrcAdr;
|
||||
Procedure set_src_adr(src:TSrcAdr);
|
||||
public
|
||||
procedure Init(base:Pointer);
|
||||
property Adr:TSrcAdr read get_src_adr write set_src_adr;
|
||||
end;
|
||||
|
||||
TsrLabelType=(ltBranch,ltUnknow,ltBegAdr,ltEndAdr,ltBegCond,ltEndCond,ltBegLoop,ltEndLoop);
|
||||
|
||||
TsrSetLabelType=Set of TsrLabelType;
|
||||
|
||||
TsrBlockType=(btMain,btAdr,btSetpc,btCond,btLoop,btOther);
|
||||
|
||||
PsrLabel=^TsrLabel;
|
||||
TsrLabel=object
|
||||
pLeft,pRight:PsrLabel;
|
||||
//----
|
||||
Adr:TSrcAdr;
|
||||
lType:TsrSetLabelType;
|
||||
function c(n1,n2:PsrLabel):Integer; static;
|
||||
Procedure AddType(t:TsrLabelType);
|
||||
Procedure RemType(t:TsrLabelType);
|
||||
function IsType(t:TsrLabelType):Boolean;
|
||||
end;
|
||||
|
||||
TsrLabels=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrLabel,TsrLabel>;
|
||||
var
|
||||
FNTree:TNodeFetch;
|
||||
end;
|
||||
|
||||
function get_branch_offset(var FSPI:TSPI):ptrint;
|
||||
|
||||
implementation
|
||||
|
||||
function TSrcAdr.get_pc:PDWORD;
|
||||
begin
|
||||
Result:=pBody+Offdw;
|
||||
end;
|
||||
|
||||
procedure TsrLCursor.Init(base:Pointer);
|
||||
begin
|
||||
Body :=base;
|
||||
OFFSET_DW:=0;
|
||||
end;
|
||||
|
||||
function TsrLCursor.get_src_adr:TSrcAdr;
|
||||
begin
|
||||
Result:=Default(TSrcAdr);
|
||||
Result.pBody:=Body;
|
||||
Result.Offdw:=OFFSET_DW;
|
||||
end;
|
||||
|
||||
Procedure TsrLCursor.set_src_adr(src:TSrcAdr);
|
||||
begin
|
||||
Body :=src.pBody;
|
||||
OFFSET_DW:=src.Offdw;
|
||||
end;
|
||||
|
||||
function TsrLabel.c(n1,n2:PsrLabel):Integer;
|
||||
var
|
||||
p1,p2:Pointer;
|
||||
begin
|
||||
p1:=n1^.Adr.get_pc;
|
||||
p2:=n2^.Adr.get_pc;
|
||||
Result:=Integer(p1>p2)-Integer(p1<p2);
|
||||
end;
|
||||
|
||||
Procedure TsrLabel.AddType(t:TsrLabelType);
|
||||
begin
|
||||
lType:=lType+[t];
|
||||
end;
|
||||
|
||||
Procedure TsrLabel.RemType(t:TsrLabelType);
|
||||
begin
|
||||
lType:=lType-[t];
|
||||
end;
|
||||
|
||||
function TsrLabel.IsType(t:TsrLabelType):Boolean;
|
||||
begin
|
||||
Result:=t in lType;
|
||||
end;
|
||||
|
||||
function get_branch_offset(var FSPI:TSPI):ptrint;
|
||||
begin
|
||||
Result:=FSPI.OFFSET_DW+Smallint(FSPI.SOPP.SIMM)+1;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
515
spirv/srLayout.pas
Normal file
515
spirv/srLayout.pas
Normal file
@ -0,0 +1,515 @@
|
||||
unit srLayout;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ps4_shader,
|
||||
srNodes,
|
||||
srParser,
|
||||
srCFG,
|
||||
srTypes,
|
||||
srReg,
|
||||
srVariable,
|
||||
srRefId,
|
||||
srDecorate;
|
||||
|
||||
type
|
||||
TsrResourceType=(
|
||||
rtBufPtr2,
|
||||
rtFunPtr2,
|
||||
rtVSharp4,
|
||||
rtSSharp4,
|
||||
rtTSharp4,
|
||||
rtTSharp8
|
||||
);
|
||||
|
||||
type
|
||||
PsrDataLayout=^TsrDataLayout;
|
||||
|
||||
PsrChainExt=^TsrChainExt;
|
||||
TsrChainExt=object
|
||||
pIndex:PsrRegNode;
|
||||
stride:PtrUint;
|
||||
function c(n1,n2:PsrChainExt):Integer; static;
|
||||
end;
|
||||
|
||||
PsrChain=^TsrChain;
|
||||
TsrChain=object
|
||||
pLeft,pRight:PsrChain;
|
||||
//----
|
||||
read_count:DWORD;
|
||||
write_count:DWORD;
|
||||
parent:PsrDataLayout;
|
||||
key:packed record
|
||||
ext:TsrChainExt;
|
||||
size,offset:PtrUint;
|
||||
end;
|
||||
rSlot:TsrRegSlot;
|
||||
pField:Pointer;
|
||||
pLine:Pointer;
|
||||
ID:TsrRefId; //post id
|
||||
function c(n1,n2:PsrChain):Integer; static;
|
||||
Procedure mark_read;
|
||||
Procedure mark_unread;
|
||||
Procedure mark_write;
|
||||
Procedure SetRegType(rtype:TsrDataType);
|
||||
function GetRegType:TsrDataType;
|
||||
function IsUsed:Boolean;
|
||||
end;
|
||||
|
||||
TsrChains=array[0..7] of PsrChain;
|
||||
|
||||
//----
|
||||
|
||||
TsrDataLayout=object
|
||||
type
|
||||
TChainFetch=specialize TNodeFetch<PsrChain,TsrChain>;
|
||||
var
|
||||
pLeft,pRight:PsrDataLayout;
|
||||
//----
|
||||
key:packed record
|
||||
parent:PsrDataLayout;
|
||||
offset:PtrUint;
|
||||
rtype:TsrResourceType;
|
||||
end;
|
||||
pData:Pointer;
|
||||
FID:Integer;
|
||||
Alloc:TfnAlloc;
|
||||
FList:TChainFetch;
|
||||
function c(n1,n2:PsrDataLayout):Integer; static;
|
||||
function Fetch(o,s:PtrUint;ext:PsrChainExt):PsrChain;
|
||||
Function First:PsrChain;
|
||||
Function Last:PsrChain;
|
||||
Function Next(node:PsrChain):PsrChain;
|
||||
Function Prev(node:PsrChain):PsrChain;
|
||||
function GetData:Pointer;
|
||||
function GetStride:PtrUint;
|
||||
function GetTypeChar:Char;
|
||||
function GetString:RawByteString;
|
||||
function GetFuncString(LEN:DWORD):RawByteString;
|
||||
end;
|
||||
|
||||
TsrDataLayoutList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrDataLayout,TsrDataLayout>;
|
||||
var
|
||||
FTop:TsrDataLayout;
|
||||
FNTree:TNodeFetch;
|
||||
procedure Init(cb:TfnAlloc);
|
||||
procedure SetUserData(pData:Pointer);
|
||||
function Fetch(p:PsrDataLayout;o:PtrUint;t:TsrResourceType):PsrDataLayout;
|
||||
Function First:PsrDataLayout;
|
||||
Function Next(node:PsrDataLayout):PsrDataLayout;
|
||||
function Grouping(const chain:TsrChains;rtype:TsrResourceType):PsrDataLayout;
|
||||
Procedure AllocID;
|
||||
procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
procedure AllocFuncExt(FDebugInfo:PsrDebugInfoList;var Heap:TsrCodeHeap);
|
||||
end;
|
||||
|
||||
//----
|
||||
|
||||
PsrDescriptor=^TsrDescriptor;
|
||||
TsrDescriptor=object
|
||||
pVar:PsrVariable;
|
||||
FStorage:DWORD;
|
||||
FBinding:Integer;
|
||||
end;
|
||||
|
||||
function is_consistents(const chains:TsrChains;count:Byte):Boolean;
|
||||
function is_no_index_chains(const chains:TsrChains;count:Byte):Boolean;
|
||||
function is_userdata_chains(const chains:TsrChains;count:Byte):Boolean;
|
||||
function GetResourceSizeDw(r:TsrResourceType):Byte;
|
||||
|
||||
implementation
|
||||
|
||||
function TsrDataLayout.c(n1,n2:PsrDataLayout):Integer;
|
||||
begin
|
||||
//first parent
|
||||
Result:=Integer(n1^.key.parent>n2^.key.parent)-Integer(n1^.key.parent<n2^.key.parent);
|
||||
if (Result<>0) then Exit;
|
||||
//second offset
|
||||
Result:=Integer(n1^.key.offset>n2^.key.offset)-Integer(n1^.key.offset<n2^.key.offset);
|
||||
if (Result<>0) then Exit;
|
||||
//third rtype
|
||||
Result:=Integer(n1^.key.rtype>n2^.key.rtype)-Integer(n1^.key.rtype<n2^.key.rtype);
|
||||
end;
|
||||
|
||||
function TsrDataLayout.Fetch(o,s:PtrUint;ext:PsrChainExt):PsrChain;
|
||||
var
|
||||
node:TsrChain;
|
||||
begin
|
||||
node:=Default(TsrChain);
|
||||
node.key.offset:=o;
|
||||
node.key.size :=s;
|
||||
if (ext<>nil) then
|
||||
begin
|
||||
node.key.ext:=ext^;
|
||||
end;
|
||||
Result:=FList.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrChain));
|
||||
Result^.parent:=@Self;
|
||||
Result^.key.offset:=o;
|
||||
Result^.key.size :=s;
|
||||
if (ext<>nil) then
|
||||
begin
|
||||
Result^.key.ext:=ext^;
|
||||
end;
|
||||
Result^.rSlot.Init(Alloc,'CHAIN');
|
||||
FList.Insert(Result);
|
||||
end else
|
||||
begin
|
||||
if (ext<>nil) then
|
||||
if (ext^.pIndex<>nil) then
|
||||
begin
|
||||
ext^.pIndex^.mark_unread;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrDataLayout.First:PsrChain;
|
||||
begin
|
||||
Result:=FList.Min;
|
||||
end;
|
||||
|
||||
Function TsrDataLayout.Last:PsrChain;
|
||||
begin
|
||||
Result:=FList.Max;
|
||||
end;
|
||||
|
||||
Function TsrDataLayout.Next(node:PsrChain):PsrChain;
|
||||
begin
|
||||
Result:=FList.Next(node);
|
||||
end;
|
||||
|
||||
Function TsrDataLayout.Prev(node:PsrChain):PsrChain;
|
||||
begin
|
||||
Result:=FList.Prev(node);
|
||||
end;
|
||||
|
||||
function TsrDataLayout.GetData:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (pData<>nil) then
|
||||
Case key.rtype of
|
||||
rtBufPtr2,
|
||||
rtFunPtr2:Result:=pData;
|
||||
rtVSharp4:Result:={%H-}Pointer(PVSharpResource4(pData)^.base);
|
||||
rtTSharp4,
|
||||
rtTSharp8:Result:={%H-}Pointer(PTSharpResource4(pData)^.base shl 8);
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataLayout.GetStride:PtrUint;
|
||||
begin
|
||||
Result:=0;
|
||||
if (pData<>nil) then
|
||||
Case key.rtype of
|
||||
rtBufPtr2:Result:=4;
|
||||
rtVSharp4:Result:=PVSharpResource4(pData)^.stride;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataLayout.GetTypeChar:Char;
|
||||
begin
|
||||
Result:=#0;
|
||||
case key.rtype of
|
||||
rtBufPtr2:Result:='B';
|
||||
rtFunPtr2:Result:='F';
|
||||
rtVSharp4:Result:='V';
|
||||
rtSSharp4:Result:='S';
|
||||
rtTSharp4:Result:='t';
|
||||
rtTSharp8:Result:='T';
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataLayout.GetString:RawByteString;
|
||||
var
|
||||
PID:DWORD;
|
||||
begin
|
||||
PID:=0;
|
||||
if (key.parent<>nil) then
|
||||
begin
|
||||
PID:=key.parent^.FID;
|
||||
end;
|
||||
Result:='#'+GetTypeChar+
|
||||
';PID='+HexStr(PID,8)+
|
||||
';OFS='+HexStr(key.offset,8);
|
||||
end;
|
||||
|
||||
function TsrDataLayout.GetFuncString(LEN:DWORD):RawByteString;
|
||||
begin
|
||||
Result:='FF'+
|
||||
';PID='+HexStr(FID,8)+
|
||||
';LEN='+HexStr(LEN,8);
|
||||
end;
|
||||
|
||||
procedure TsrDataLayoutList.Init(cb:TfnAlloc);
|
||||
begin
|
||||
FTop.Alloc:=cb;
|
||||
FNTree.Insert(@FTop);
|
||||
end;
|
||||
|
||||
procedure TsrDataLayoutList.SetUserData(pData:Pointer);
|
||||
begin
|
||||
FTop.pData:=pData;
|
||||
end;
|
||||
|
||||
function TsrDataLayoutList.Fetch(p:PsrDataLayout;o:PtrUint;t:TsrResourceType):PsrDataLayout;
|
||||
var
|
||||
node:TsrDataLayout;
|
||||
pData:Pointer;
|
||||
begin
|
||||
node:=Default(TsrDataLayout);
|
||||
node.Alloc:=FTop.Alloc;
|
||||
node.key.parent:=p;
|
||||
node.key.offset:=o;
|
||||
node.key.rtype :=t;
|
||||
Result:=FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=FTop.Alloc(SizeOf(TsrDataLayout));
|
||||
Move(node,Result^,SizeOf(TsrDataLayout));
|
||||
FNTree.Insert(Result);
|
||||
|
||||
Result^.FID:=-1;
|
||||
|
||||
if (p<>nil) then
|
||||
begin
|
||||
pData:=p^.GetData;
|
||||
if (pData<>nil) then
|
||||
case t of
|
||||
rtBufPtr2,
|
||||
rtFunPtr2:Result^.pData:={%H-}Pointer(PPtrUint(pData+o)^ and (not 3));
|
||||
rtVSharp4,
|
||||
rtSSharp4,
|
||||
rtTSharp4,
|
||||
rtTSharp8:Result^.pData:=pData+o;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrDataLayoutList.First:PsrDataLayout;
|
||||
begin
|
||||
Result:=FNTree.Min;
|
||||
end;
|
||||
|
||||
Function TsrDataLayoutList.Next(node:PsrDataLayout):PsrDataLayout;
|
||||
begin
|
||||
Result:=FNTree.Next(node);
|
||||
end;
|
||||
|
||||
function GetResourceSizeDw(r:TsrResourceType):Byte;
|
||||
begin
|
||||
Result:=0;
|
||||
Case r of
|
||||
rtBufPtr2:Result:=2;
|
||||
rtFunPtr2:Result:=2;
|
||||
rtVSharp4:Result:=4;
|
||||
rtSSharp4:Result:=4;
|
||||
rtTSharp4:Result:=4;
|
||||
rtTSharp8:Result:=8;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataLayoutList.Grouping(const chain:TsrChains;rtype:TsrResourceType):PsrDataLayout;
|
||||
begin
|
||||
Result:=nil;
|
||||
|
||||
if not is_consistents(chain,GetResourceSizeDw(rtype)) then
|
||||
begin
|
||||
Assert(False,'inconsistent resources not supported');
|
||||
end;
|
||||
|
||||
if not is_no_index_chains(chain,GetResourceSizeDw(rtype)) then
|
||||
begin
|
||||
Assert(False,'indexed chain not support');
|
||||
end;
|
||||
|
||||
Result:=Fetch(chain[0]^.parent,chain[0]^.key.offset,rtype);
|
||||
end;
|
||||
|
||||
Procedure TsrDataLayoutList.AllocID;
|
||||
var
|
||||
node:PsrDataLayout;
|
||||
FID:Integer;
|
||||
begin
|
||||
FID:=1;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.FID=-1) then
|
||||
begin
|
||||
node^.FID:=FID;
|
||||
Inc(FID);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrDataLayoutList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
var
|
||||
node:PsrDataLayout;
|
||||
begin
|
||||
if (FDebugInfo=nil) then Exit;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
FDebugInfo^.emit_source_extension(node^.GetString);
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrDataLayoutList.AllocFuncExt(FDebugInfo:PsrDebugInfoList;var Heap:TsrCodeHeap);
|
||||
var
|
||||
node:PsrDataLayout;
|
||||
block:PsrCodeBlock;
|
||||
begin
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.key.rtype=rtFunPtr2) then
|
||||
begin
|
||||
block:=Heap.FindByPtr(node^.pData);
|
||||
if (block<>nil) then
|
||||
begin
|
||||
FDebugInfo^.emit_source_extension(node^.GetFuncString(block^.Size));
|
||||
end;
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrChainExt.c(n1,n2:PsrChainExt):Integer;
|
||||
begin
|
||||
//first pIndex forward
|
||||
Result:=Integer(n1^.pIndex>n2^.pIndex)-Integer(n1^.pIndex<n2^.pIndex);
|
||||
if (Result<>0) then Exit;
|
||||
|
||||
//second stride forward
|
||||
Result:=Integer(n1^.stride>n2^.stride)-Integer(n1^.stride<n2^.stride);
|
||||
end;
|
||||
|
||||
function TsrChain.c(n1,n2:PsrChain):Integer;
|
||||
begin
|
||||
//first ext
|
||||
Result:=TsrChainExt.c(@n1^.key.ext,@n2^.key.ext);
|
||||
if (Result<>0) then Exit;
|
||||
|
||||
//second size backward
|
||||
Result:=Integer(n1^.key.size<n2^.key.size)-Integer(n1^.key.size>n2^.key.size);
|
||||
if (Result<>0) then Exit;
|
||||
|
||||
//third offset forward
|
||||
Result:=Integer(n1^.key.offset>n2^.key.offset)-Integer(n1^.key.offset<n2^.key.offset);
|
||||
end;
|
||||
|
||||
Procedure TsrChain.mark_read;
|
||||
begin
|
||||
Inc(read_count);
|
||||
end;
|
||||
|
||||
Procedure TsrChain.mark_unread;
|
||||
begin
|
||||
if (read_count<>0) then Dec(read_count);
|
||||
end;
|
||||
|
||||
Procedure TsrChain.mark_write;
|
||||
begin
|
||||
Inc(write_count);
|
||||
end;
|
||||
|
||||
Procedure TsrChain.SetRegType(rtype:TsrDataType);
|
||||
var
|
||||
node:PsrRegNode;
|
||||
begin
|
||||
node:=rSlot.pStory.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
node^.dtype:=rtype;
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrChain.GetRegType:TsrDataType;
|
||||
var
|
||||
pReg:PsrRegNode;
|
||||
begin
|
||||
Result:=dtUnknow;
|
||||
pReg:=rSlot.current;
|
||||
if (pReg=nil) then Exit;
|
||||
Result:=pReg^.dtype;
|
||||
end;
|
||||
|
||||
function TsrChain.IsUsed:Boolean;
|
||||
begin
|
||||
Result:=((read_count<>0) or
|
||||
(write_count<>0)) and
|
||||
(rSlot.current<>nil);
|
||||
end;
|
||||
|
||||
function is_consistents(const chains:TsrChains;count:Byte):Boolean;
|
||||
var
|
||||
parent:PsrDataLayout;
|
||||
offset,t:PtrUint;
|
||||
i:Byte;
|
||||
begin
|
||||
offset:=0;
|
||||
t:=0;
|
||||
if (count<2) then Exit(True);
|
||||
Result:=False;
|
||||
if (chains[0]=nil) then Exit;
|
||||
parent:=chains[0]^.parent;
|
||||
offset:=chains[0]^.key.offset;
|
||||
For i:=1 to count-1 do
|
||||
begin
|
||||
t:=chains[i-1]^.key.size;
|
||||
offset:=offset+t;
|
||||
if (chains[i]=nil) then Exit;
|
||||
if (chains[i]^.parent<>parent) then Exit;
|
||||
t:=chains[i]^.key.offset;
|
||||
if (offset<>t) then Exit;
|
||||
end;
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
function is_no_index_chains(const chains:TsrChains;count:Byte):Boolean;
|
||||
var
|
||||
i:Byte;
|
||||
begin
|
||||
Result:=False;
|
||||
if (count=0) then Exit;
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
if (chains[i]=nil) then Exit;
|
||||
if (chains[i]^.key.ext.pIndex<>nil) then Exit;
|
||||
end;
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
function is_userdata_chains(const chains:TsrChains;count:Byte):Boolean;
|
||||
var
|
||||
parent:PsrDataLayout;
|
||||
i:Byte;
|
||||
begin
|
||||
Result:=False;
|
||||
if (count=0) then Exit;
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
if (chains[i]=nil) then Exit;
|
||||
parent:=chains[i]^.parent;
|
||||
if (parent=nil) then Exit;
|
||||
if (parent^.key.parent<>nil) then Exit;
|
||||
end;
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
570
spirv/srNodes.pas
Normal file
570
spirv/srNodes.pas
Normal file
@ -0,0 +1,570 @@
|
||||
unit srNodes;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
generic TNodeStack<PNode>=object
|
||||
pHead:PNode;
|
||||
procedure Push_head(Node:PNode);
|
||||
function Pop_head:PNode;
|
||||
procedure Move_from(var s:TNodeStack);
|
||||
end;
|
||||
|
||||
generic TNodeQueue<PNode>=object
|
||||
pHead,pTail:PNode;
|
||||
procedure Push_head(Node:PNode);
|
||||
procedure Push_tail(Node:PNode);
|
||||
function Pop_head:PNode;
|
||||
procedure InsertAfter(node,new:PNode);
|
||||
end;
|
||||
|
||||
generic TNodeList<PNode>=object
|
||||
pHead,pTail:PNode;
|
||||
procedure Push_head(Node:PNode);
|
||||
procedure Push_tail(Node:PNode);
|
||||
function Pop_head:PNode;
|
||||
function Pop_tail:PNode;
|
||||
procedure InsertAfter(node,new:PNode);
|
||||
procedure InsertBefore(node,new:PNode);
|
||||
procedure Remove(node:PNode);
|
||||
end;
|
||||
|
||||
generic TNodeFetch<PNode,TNode>=object
|
||||
var
|
||||
pRoot:PNode;
|
||||
function _Splay(node:PNode):Integer;
|
||||
function Min:PNode;
|
||||
function Max:PNode;
|
||||
function Next(node:PNode):PNode;
|
||||
function Prev(node:PNode):PNode;
|
||||
function Find(node:PNode):PNode;
|
||||
function Find_be(node:PNode):PNode;
|
||||
function Find_le(node:PNode):PNode;
|
||||
procedure Insert(new:PNode);
|
||||
end;
|
||||
|
||||
TsrNodeType=(
|
||||
ntUnknow,
|
||||
ntLiteral,
|
||||
ntString,
|
||||
ntConst,
|
||||
ntType,
|
||||
ntLabel,
|
||||
ntBlock,
|
||||
ntFunc,
|
||||
ntVar,
|
||||
ntRefId,
|
||||
ntOp,
|
||||
ntReg,
|
||||
ntVolatile,
|
||||
ntInput,
|
||||
ntVertLayout,
|
||||
ntFragLayout,
|
||||
ntOutput,
|
||||
ntChain,
|
||||
ntUniform,
|
||||
ntBuffer
|
||||
);
|
||||
|
||||
TOpParamSingle=packed object
|
||||
ntype:TsrNodeType;
|
||||
pData:Pointer;
|
||||
procedure SetParam(_ntype:TsrNodeType;_Data:Pointer);
|
||||
function AsConst:Pointer;
|
||||
function AsOp:Pointer;
|
||||
function AsReg:Pointer;
|
||||
function AsVar:Pointer;
|
||||
function AsBlock:Pointer;
|
||||
function AsInput:Pointer;
|
||||
function AsRefId:Pointer;
|
||||
function AsUniform:Pointer;
|
||||
end;
|
||||
|
||||
TfnAlloc=Function(Size:ptruint):Pointer of object;
|
||||
|
||||
function ComparePtruint(buf1,buf2:PPtruint;count:PtrUint):Integer;
|
||||
|
||||
implementation
|
||||
|
||||
function TNodeFetch._Splay(node:PNode):Integer;
|
||||
var
|
||||
aux:TNode;
|
||||
t,l,r,y:PNode;
|
||||
begin
|
||||
t:=pRoot;
|
||||
l:=@aux;
|
||||
r:=@aux;
|
||||
aux.pLeft:=nil;
|
||||
aux.pRight:=nil;
|
||||
while (true) do
|
||||
begin
|
||||
Result:=TNode.c(t,node);
|
||||
if (Result=0) then Break;
|
||||
if (Result>0) then
|
||||
begin
|
||||
if (t^.pLeft=nil) then break;
|
||||
if (TNode.c(node,t^.pLeft)<0) then
|
||||
begin
|
||||
y:=t^.pLeft; // rotate pRight
|
||||
t^.pLeft:=y^.pRight;
|
||||
y^.pRight:=t;
|
||||
t:=y;
|
||||
if (t^.pLeft=nil) then break;
|
||||
end;
|
||||
r^.pLeft:=t; // link pRight
|
||||
r:=t;
|
||||
t:=t^.pLeft;
|
||||
end else
|
||||
begin
|
||||
if (t^.pRight=nil) then break;
|
||||
if (TNode.c(node,t^.pRight)>0) then
|
||||
begin
|
||||
y:=t^.pRight; // rotate pLeft
|
||||
t^.pRight:=y^.pLeft;
|
||||
y^.pLeft:=t;
|
||||
t:=y;
|
||||
if (t^.pRight=nil) then break;
|
||||
end;
|
||||
l^.pRight:=t; // link pLeft
|
||||
l:=t;
|
||||
t:=t^.pRight;
|
||||
end;
|
||||
end;
|
||||
l^.pRight:=t^.pLeft; // assemble
|
||||
r^.pLeft :=t^.pRight;
|
||||
t^.pLeft :=aux.pRight;
|
||||
t^.pRight:=aux.pLeft;
|
||||
pRoot:=t;
|
||||
end;
|
||||
|
||||
function TNodeFetch.Min:PNode;
|
||||
var
|
||||
node:PNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=pRoot;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
Result:=node;
|
||||
node:=node^.pLeft;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TNodeFetch.Max:PNode;
|
||||
var
|
||||
node:PNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=pRoot;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
Result:=node;
|
||||
node:=node^.pRight;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TNodeFetch.Next(node:PNode):PNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (pRoot=nil) or (node=nil) then Exit;
|
||||
if (node^.pRight=nil) then
|
||||
begin
|
||||
_Splay(node);
|
||||
end;
|
||||
node:=node^.pRight;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
Result:=node;
|
||||
node:=node^.pLeft;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TNodeFetch.Prev(node:PNode):PNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (pRoot=nil) or (node=nil) then Exit;
|
||||
if (node^.pLeft=nil) then
|
||||
begin
|
||||
_Splay(node);
|
||||
end;
|
||||
node:=node^.pLeft;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
Result:=node;
|
||||
node:=node^.pRight;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TNodeFetch.Find(node:PNode):PNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (pRoot=nil) or (node=nil) then Exit;
|
||||
if (_Splay(node)=0) then Result:=pRoot;
|
||||
end;
|
||||
|
||||
function TNodeFetch.Find_be(node:PNode):PNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (pRoot=nil) or (node=nil) then Exit;
|
||||
if (_Splay(node)<0) then
|
||||
begin
|
||||
Result:=Next(pRoot);
|
||||
end else
|
||||
begin
|
||||
Result:=pRoot;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TNodeFetch.Find_le(node:PNode):PNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (pRoot=nil) or (node=nil) then Exit;
|
||||
if (_Splay(node)>0) then
|
||||
begin
|
||||
Result:=Prev(pRoot);
|
||||
end else
|
||||
begin
|
||||
Result:=pRoot;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TNodeFetch.Insert(new:PNode);
|
||||
var
|
||||
c:Integer;
|
||||
begin
|
||||
if (new=nil) then Exit;
|
||||
if (pRoot=nil) then
|
||||
begin
|
||||
pRoot:=new;
|
||||
end else
|
||||
begin
|
||||
c:=TNode.c(pRoot,new);
|
||||
if (c<>0) then
|
||||
begin
|
||||
if (c<0) then
|
||||
begin
|
||||
new^.pRight:=pRoot^.pRight;
|
||||
new^.pLeft :=pRoot;
|
||||
pRoot^.pRight:=nil;
|
||||
end else
|
||||
begin
|
||||
new^.pLeft :=pRoot^.pLeft;
|
||||
new^.pRight:=pRoot;
|
||||
pRoot^.pLeft:=nil;
|
||||
end;
|
||||
pRoot:=new;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
//--
|
||||
|
||||
procedure TNodeStack.Push_head(Node:PNode);
|
||||
begin
|
||||
if (pHead=nil) then
|
||||
begin
|
||||
node^.pNext:=nil;
|
||||
end else
|
||||
begin
|
||||
node^.pNext:=pHead;
|
||||
end;
|
||||
pHead:=node;
|
||||
end;
|
||||
|
||||
function TNodeStack.Pop_head:PNode;
|
||||
begin
|
||||
Result:=pHead;
|
||||
if (pHead<>nil) then
|
||||
begin
|
||||
pHead:=pHead^.pNext;
|
||||
end;
|
||||
if (Result<>nil) then
|
||||
begin
|
||||
Result^.pNext:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TNodeStack.Move_from(var s:TNodeStack);
|
||||
var
|
||||
node:PNode;
|
||||
begin
|
||||
repeat
|
||||
node:=s.Pop_head;
|
||||
if (node=nil) then Break;
|
||||
Push_head(node);
|
||||
until false;
|
||||
end;
|
||||
|
||||
//--
|
||||
|
||||
procedure TNodeQueue.Push_head(Node:PNode);
|
||||
begin
|
||||
if (pHead=nil) then
|
||||
begin
|
||||
pTail:=node;
|
||||
node^.pNext:=nil;
|
||||
end else
|
||||
begin
|
||||
node^.pNext:=pHead;
|
||||
end;
|
||||
pHead:=node;
|
||||
end;
|
||||
|
||||
procedure TNodeQueue.Push_tail(Node:PNode);
|
||||
begin
|
||||
if (pTail=nil) then
|
||||
begin
|
||||
pHead:=node;
|
||||
node^.pNext:=nil;
|
||||
end else
|
||||
begin
|
||||
pTail^.pNext:=node;
|
||||
end;
|
||||
pTail:=node;
|
||||
end;
|
||||
|
||||
function TNodeQueue.Pop_head:PNode;
|
||||
begin
|
||||
if (pHead=nil) then
|
||||
begin
|
||||
Result:=nil;
|
||||
end else
|
||||
begin
|
||||
Result:=pHead;
|
||||
pHead:=pHead^.pNext;
|
||||
if (pHead=nil) then
|
||||
begin
|
||||
pTail:=nil;
|
||||
end;
|
||||
Result^.pNext:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TNodeQueue.InsertAfter(node,new:PNode);
|
||||
begin
|
||||
if (node^.pNext=nil) then
|
||||
begin
|
||||
new^.pNext:=nil;
|
||||
pTail:=new;
|
||||
end else
|
||||
begin
|
||||
new^.pNext:=node^.pNext;
|
||||
end;
|
||||
node^.pNext:=new;
|
||||
end;
|
||||
|
||||
//--
|
||||
|
||||
procedure TNodeList.Push_head(Node:PNode);
|
||||
begin
|
||||
if (pHead=nil) then
|
||||
begin
|
||||
pTail:=node;
|
||||
node^.pNext:=nil;
|
||||
end else
|
||||
begin
|
||||
pHead^.pPrev:=node;
|
||||
node^.pNext:=pHead;
|
||||
end;
|
||||
node^.pPrev:=nil;
|
||||
pHead:=node;
|
||||
end;
|
||||
|
||||
procedure TNodeList.Push_tail(Node:PNode);
|
||||
begin
|
||||
if (pTail=nil) then
|
||||
begin
|
||||
pHead:=node;
|
||||
node^.pPrev:=nil;
|
||||
end else
|
||||
begin
|
||||
pTail^.pNext:=node;
|
||||
node^.pPrev:=pTail;
|
||||
end;
|
||||
node^.pNext:=nil;
|
||||
pTail:=node;
|
||||
end;
|
||||
|
||||
function TNodeList.Pop_head:PNode;
|
||||
begin
|
||||
if (pHead=nil) then
|
||||
begin
|
||||
Result:=nil;
|
||||
end else
|
||||
begin
|
||||
Result:=pHead;
|
||||
pHead:=pHead^.pNext;
|
||||
if (pHead=nil) then
|
||||
begin
|
||||
pTail:=nil;
|
||||
end else
|
||||
begin
|
||||
pHead^.pPrev:=nil;
|
||||
end;
|
||||
Result^.pPrev:=nil;
|
||||
Result^.pNext:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TNodeList.Pop_tail:PNode;
|
||||
begin
|
||||
if (pTail=nil) then
|
||||
begin
|
||||
Result:=nil;
|
||||
end else
|
||||
begin
|
||||
Result:=pTail;
|
||||
pTail:=pTail^.pPrev;
|
||||
if (pTail=nil) then
|
||||
begin
|
||||
pHead:=nil;
|
||||
end else
|
||||
begin
|
||||
pTail^.pNext:=nil;
|
||||
end;
|
||||
Result^.pPrev:=nil;
|
||||
Result^.pNext:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TNodeList.InsertAfter(node,new:PNode);
|
||||
begin
|
||||
new^.pPrev:=node;
|
||||
if (node^.pNext=nil) then
|
||||
begin
|
||||
new^.pNext:=nil;
|
||||
pTail:=new;
|
||||
end else
|
||||
begin
|
||||
new^.pNext:=node^.pNext;
|
||||
node^.pNext^.pPrev:=new;
|
||||
end;
|
||||
node^.pNext:=new;
|
||||
end;
|
||||
|
||||
procedure TNodeList.InsertBefore(node,new:PNode);
|
||||
begin
|
||||
new^.pNext:=node;
|
||||
if (node^.pPrev=nil) then
|
||||
begin
|
||||
new^.pPrev:=nil;
|
||||
pHead:=new;
|
||||
end else
|
||||
begin
|
||||
new^.pPrev:=node^.pPrev;
|
||||
node^.pPrev^.pNext:=new;
|
||||
end;
|
||||
node^.pPrev:=new;
|
||||
end;
|
||||
|
||||
procedure TNodeList.Remove(node:PNode);
|
||||
begin
|
||||
if (node^.pPrev=nil) then
|
||||
begin
|
||||
if (pHead=node) then
|
||||
begin
|
||||
pHead:=node^.pNext;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
node^.pPrev^.pNext:=node^.pNext;
|
||||
end;
|
||||
if (node^.pNext=nil) then
|
||||
begin
|
||||
if (pTail=node) then
|
||||
begin
|
||||
pTail:=node^.pPrev;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
node^.pNext^.pPrev:=node^.pPrev;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TOpParamSingle.SetParam(_ntype:TsrNodeType;_Data:Pointer);
|
||||
begin
|
||||
ntype:=_ntype;
|
||||
pData:=_Data;
|
||||
end;
|
||||
|
||||
function TOpParamSingle.AsConst:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (ntype<>ntConst) then Exit;
|
||||
Result:=pData;
|
||||
end;
|
||||
|
||||
function TOpParamSingle.AsOp:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (ntype<>ntOp) then Exit;
|
||||
Result:=pData;
|
||||
end;
|
||||
|
||||
function TOpParamSingle.AsReg:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (ntype<>ntReg) then Exit;
|
||||
Result:=pData;
|
||||
end;
|
||||
|
||||
function TOpParamSingle.AsVar:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (ntype<>ntVar) then Exit;
|
||||
Result:=pData;
|
||||
end;
|
||||
|
||||
function TOpParamSingle.AsBlock:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (ntype<>ntBlock) then Exit;
|
||||
Result:=pData;
|
||||
end;
|
||||
|
||||
function TOpParamSingle.AsInput:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (ntype<>ntInput) then Exit;
|
||||
Result:=pData;
|
||||
end;
|
||||
|
||||
function TOpParamSingle.AsRefId:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (ntype<>ntRefId) then Exit;
|
||||
Result:=pData;
|
||||
end;
|
||||
|
||||
function TOpParamSingle.AsUniform:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (ntype<>ntUniform) then Exit;
|
||||
Result:=pData;
|
||||
end;
|
||||
|
||||
function ComparePtruint(buf1,buf2:PPtruint;count:PtrUint):Integer;
|
||||
begin
|
||||
Result:=0;
|
||||
While (count<>0) do
|
||||
begin
|
||||
Result:=Integer(buf1^>buf2^)-Integer(buf1^<buf2^);
|
||||
if (Result<>0) then Exit;
|
||||
Inc(buf1);
|
||||
Inc(buf2);
|
||||
Dec(count);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
534
spirv/srOp.pas
Normal file
534
spirv/srOp.pas
Normal file
@ -0,0 +1,534 @@
|
||||
unit srOp;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
srNodes,
|
||||
srLabel,
|
||||
srCFG,
|
||||
srParser,
|
||||
srTypes,
|
||||
srRefId,
|
||||
srReg;
|
||||
|
||||
type
|
||||
POpParamNode=^TOpParamNode;
|
||||
TOpParamNode=packed record
|
||||
pNext:POpParamNode;
|
||||
//----
|
||||
ntype:TsrNodeType;
|
||||
Case Byte of
|
||||
0:(pData:Pointer);
|
||||
1:(Value:DWORD;name:record end);
|
||||
end;
|
||||
|
||||
TOpParamQueue=specialize TNodeQueue<POpParamNode>;
|
||||
|
||||
PsrOpBlock=^TsrOpBlock;
|
||||
|
||||
PspirvOp=^TspirvOp;
|
||||
TspirvOp=object
|
||||
pPrev,pNext:PspirvOp;
|
||||
//----
|
||||
pParent:PsrOpBlock;
|
||||
pParam:TOpParamQueue;
|
||||
Adr:TSrcAdr;
|
||||
dst_type:PsrType;
|
||||
dst:TOpParamSingle;
|
||||
OpId:DWORD;
|
||||
procedure InsertAfter(new:PspirvOp);
|
||||
procedure InsertBefore(new:PspirvOp);
|
||||
procedure Remove;
|
||||
function ParamNode(i:Byte):POpParamNode;
|
||||
procedure AddParam(const s:TOpParamSingle);
|
||||
procedure AddParam(ntype:TsrNodeType;Data:Pointer);
|
||||
procedure AddParamAfter(prev:POpParamNode;ntype:TsrNodeType;Data:Pointer);
|
||||
procedure AddLiteral(Value:PtrUint;const name:RawByteString='');
|
||||
procedure AddString(const name:RawByteString);
|
||||
Procedure SetDstReg(r:Pointer);
|
||||
end;
|
||||
|
||||
TsrVolMark=(vmNone,vmEnd,vmBreak,vmCont);
|
||||
|
||||
TsrBlockInfo=packed record
|
||||
b_adr,e_adr:TSrcAdr;
|
||||
bType:TsrBlockType;
|
||||
end;
|
||||
|
||||
TsrOpList=specialize TNodeList<PspirvOp>;
|
||||
|
||||
TsrOpBlockSimple=object(TsrOpList)
|
||||
Alloc:TfnAlloc;
|
||||
procedure Init(cb:TfnAlloc);
|
||||
function NewSpirvOp(OpId:DWORD):PSpirvOp;
|
||||
function AddSpirvOp(node:PSpirvOp):PSpirvOp;
|
||||
function AddSpirvOp(OpId:DWORD):PSpirvOp;
|
||||
end;
|
||||
|
||||
TsrOpBlock=object(TsrOpBlockSimple)
|
||||
pParent:PsrOpBlock;
|
||||
pUpLine:PSpirvOp; //from post
|
||||
|
||||
Block:TsrBlockInfo;
|
||||
|
||||
Labels:record
|
||||
pBegOp:PspirvOp;
|
||||
pEndOp:PspirvOp;
|
||||
pMrgOp:PspirvOp;
|
||||
end;
|
||||
|
||||
FCursor:TsrCursor;
|
||||
|
||||
Regs:record
|
||||
pSnap:PsrRegsSnapshot;
|
||||
FVolMark:TsrVolMark;
|
||||
end;
|
||||
|
||||
Cond:record
|
||||
pReg:PsrRegNode;
|
||||
FVal:Boolean;
|
||||
FUseCont:Boolean;
|
||||
end;
|
||||
|
||||
FLevel:DWORD;
|
||||
|
||||
dummy:TspirvOp;
|
||||
|
||||
function line:PSpirvOp;
|
||||
procedure SetCFGBlock(pLBlock:PsrCFGBlock);
|
||||
procedure SetInfo(const b:TsrBlockInfo);
|
||||
procedure SetInfo(bType:TsrBlockType;b_adr,e_adr:TSrcAdr);
|
||||
procedure SetLabels(pBegOp,pEndOp,pMrgOp:PspirvOp);
|
||||
procedure SetCond(pReg:PsrRegNode;FVal:Boolean);
|
||||
function IsEndOf(Adr:TSrcAdr):Boolean;
|
||||
function FindUpLoop:PsrOpBlock;
|
||||
function FindUpCond(pReg:PsrRegNode):PsrOpBlock;
|
||||
end;
|
||||
|
||||
PSpirvFunc=^TSpirvFunc;
|
||||
TSpirvFunc=object
|
||||
pPrev,pNext,pLeft,pRight:PSpirvFunc;
|
||||
//----
|
||||
read_count:DWORD;
|
||||
FTop:TsrOpBlock;
|
||||
pBlock:PsrOpBlock;
|
||||
ID:TsrRefId; //post id
|
||||
name:RawByteString;
|
||||
function c(n1,n2:PSpirvFunc):Integer; static;
|
||||
Procedure PushBlock(New:PsrOpBlock);
|
||||
function PopBlock:Boolean;
|
||||
function line:PSpirvOp;
|
||||
Procedure Init(const fname:RawByteString;Alloc:TfnAlloc);
|
||||
Procedure mark_read;
|
||||
Procedure mark_unread;
|
||||
function NewSpirvOp(OpId:DWORD):PSpirvOp;
|
||||
function AddSpirvOp(node:PSpirvOp):PSpirvOp;
|
||||
function AddSpirvOp(OpId:DWORD):PSpirvOp;
|
||||
end;
|
||||
|
||||
TsrFuncList=object
|
||||
type
|
||||
TNodeList=specialize TNodeList<PSpirvFunc>;
|
||||
TNodeFetch=specialize TNodeFetch<PSpirvFunc,TSpirvFunc>;
|
||||
var
|
||||
FList:TNodeList;
|
||||
FNTree:TNodeFetch;
|
||||
function Search(const name:RawByteString):PSpirvFunc;
|
||||
procedure Insert(new:PSpirvFunc);
|
||||
end;
|
||||
|
||||
PsrCacheOp=^TsrCacheOp;
|
||||
TsrCacheOp=object
|
||||
pLeft,pRight:PsrCacheOp;
|
||||
//----
|
||||
pReg:PsrRegNode;
|
||||
key:packed record
|
||||
place:PsrOpBlock;
|
||||
OpId:DWORD;
|
||||
dtype:TsrDataType;
|
||||
count:DWORD;
|
||||
end;
|
||||
Data:record end;
|
||||
function c(n1,n2:PsrCacheOp):Integer; static;
|
||||
function GetCompItem(i:Byte):PsrRegNode; inline;
|
||||
Procedure SetCompItem(i:Byte;p:PsrRegNode); inline;
|
||||
end;
|
||||
|
||||
TsrCacheOpList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrCacheOp,TsrCacheOp>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
FNTree:TNodeFetch;
|
||||
function Fetch(place:PsrOpBlock;OpId:DWORD;rtype:TsrDataType;count:Byte;src:PPsrRegNode):PsrCacheOp;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
SprvEmit;
|
||||
|
||||
procedure TspirvOp.InsertAfter(new:PspirvOp);
|
||||
begin
|
||||
Assert(new<>nil);
|
||||
Assert(pParent<>nil);
|
||||
pParent^.InsertAfter(@Self,new);
|
||||
new^.pParent:=pParent;
|
||||
end;
|
||||
|
||||
procedure TspirvOp.InsertBefore(new:PspirvOp);
|
||||
begin
|
||||
Assert(new<>nil);
|
||||
Assert(pParent<>nil);
|
||||
pParent^.InsertAfter(@Self,new);
|
||||
new^.pParent:=pParent;
|
||||
end;
|
||||
|
||||
procedure TspirvOp.Remove;
|
||||
begin
|
||||
Assert(pParent<>nil);
|
||||
pParent^.Remove(@Self);
|
||||
pParent:=nil;
|
||||
end;
|
||||
|
||||
function TspirvOp.ParamNode(i:Byte):POpParamNode;
|
||||
var
|
||||
node:POpParamNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=pParam.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (i=0) then Exit(node);
|
||||
Dec(i);
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TspirvOp.AddParam(const s:TOpParamSingle);
|
||||
var
|
||||
node:POpParamNode;
|
||||
begin
|
||||
node:=pParent^.Alloc(SizeOf(TOpParamNode));
|
||||
node^.ntype:=s.ntype;
|
||||
node^.pData:=s.pData;
|
||||
pParam.Push_tail(node);
|
||||
end;
|
||||
|
||||
procedure TspirvOp.AddParam(ntype:TsrNodeType;Data:Pointer);
|
||||
var
|
||||
node:POpParamNode;
|
||||
begin
|
||||
node:=pParent^.Alloc(SizeOf(TOpParamNode));
|
||||
node^.ntype:=ntype;
|
||||
node^.pData:=Data;
|
||||
pParam.Push_tail(node);
|
||||
end;
|
||||
|
||||
procedure TspirvOp.AddParamAfter(prev:POpParamNode;ntype:TsrNodeType;Data:Pointer);
|
||||
var
|
||||
node:POpParamNode;
|
||||
begin
|
||||
node:=pParent^.Alloc(SizeOf(TOpParamNode));
|
||||
node^.ntype:=ntype;
|
||||
node^.pData:=Data;
|
||||
pParam.InsertAfter(prev,node);
|
||||
end;
|
||||
|
||||
procedure TspirvOp.AddLiteral(Value:PtrUint;const name:RawByteString='');
|
||||
var
|
||||
node:POpParamNode;
|
||||
l:ptruint;
|
||||
begin
|
||||
l:={%H-}ptruint(@TOpParamNode(nil^).name)+Length(name)+1;
|
||||
node:=pParent^.Alloc(l);
|
||||
node^.ntype:=ntLiteral;
|
||||
node^.Value:=Value;
|
||||
Move(PChar(name)^,node^.name,Length(name)+1);
|
||||
pParam.Push_tail(node);
|
||||
end;
|
||||
|
||||
procedure TspirvOp.AddString(const name:RawByteString);
|
||||
var
|
||||
node:POpParamNode;
|
||||
l:ptruint;
|
||||
begin
|
||||
l:={%H-}ptruint(@TOpParamNode(nil^).name)+Length(name)+1;
|
||||
l:=Align(l,SizeOf(DWORD));
|
||||
node:=pParent^.Alloc(l);
|
||||
node^.ntype:=ntString;
|
||||
node^.Value:=0;
|
||||
Move(PChar(name)^,node^.name,Length(name)+1);
|
||||
pParam.Push_tail(node);
|
||||
end;
|
||||
|
||||
Procedure TspirvOp.SetDstReg(r:Pointer);
|
||||
begin
|
||||
Assert(r<>nil);
|
||||
dst.SetParam(ntReg,r);
|
||||
PsrRegNode(r)^.pWriter.SetParam(ntOp,@Self);
|
||||
PsrRegNode(r)^.pLine:=@Self; //update line [bitcast order]
|
||||
end;
|
||||
|
||||
function TsrOpBlock.line:PSpirvOp;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self<>nil) then
|
||||
begin
|
||||
Result:=pTail;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrOpBlock.SetCFGBlock(pLBlock:PsrCFGBlock);
|
||||
begin
|
||||
dummy.Adr :=pLBlock^.pBLabel^.Adr;
|
||||
Block.b_adr:=pLBlock^.pBLabel^.Adr;
|
||||
Block.e_adr:=pLBlock^.pELabel^.Adr;
|
||||
Block.bType:=pLBlock^.bType;
|
||||
end;
|
||||
|
||||
procedure TsrOpBlock.SetInfo(const b:TsrBlockInfo);
|
||||
begin
|
||||
dummy.Adr :=b.b_adr;
|
||||
Block.b_adr:=b.b_adr;
|
||||
Block.e_adr:=b.e_adr;
|
||||
Block.bType:=b.bType;
|
||||
end;
|
||||
|
||||
procedure TsrOpBlock.SetInfo(bType:TsrBlockType;b_adr,e_adr:TSrcAdr);
|
||||
begin
|
||||
dummy.Adr :=b_adr;
|
||||
Block.b_adr:=b_adr;
|
||||
Block.e_adr:=e_adr;
|
||||
Block.bType:=bType;
|
||||
end;
|
||||
|
||||
procedure TsrOpBlock.SetLabels(pBegOp,pEndOp,pMrgOp:PspirvOp);
|
||||
begin
|
||||
Labels.pBegOp:=pBegOp;
|
||||
Labels.pEndOp:=pEndOp;
|
||||
Labels.pMrgOp:=pMrgOp;
|
||||
end;
|
||||
|
||||
procedure TsrOpBlock.SetCond(pReg:PsrRegNode;FVal:Boolean);
|
||||
begin
|
||||
Cond.pReg:=pReg;
|
||||
Cond.FVal:=FVal;
|
||||
end;
|
||||
|
||||
function TsrOpBlock.IsEndOf(Adr:TSrcAdr):Boolean;
|
||||
begin
|
||||
Result:=(Block.e_adr.get_pc<=Adr.get_pc);
|
||||
end;
|
||||
|
||||
function TsrOpBlock.FindUpLoop:PsrOpBlock;
|
||||
var
|
||||
node:PsrOpBlock;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=@Self;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.Block.bType=btLoop) then Exit(node);
|
||||
node:=node^.pParent;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrOpBlock.FindUpCond(pReg:PsrRegNode):PsrOpBlock;
|
||||
var
|
||||
node:PsrOpBlock;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (pReg=nil) then Exit;
|
||||
pReg:=RegDown(pReg);
|
||||
if pReg^.is_const then Exit;
|
||||
node:=@Self;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.Block.bType=btCond) and (pReg=RegDown(node^.Cond.pReg)) then Exit(node);
|
||||
node:=node^.pParent;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TSpirvFunc.c(n1,n2:PSpirvFunc):Integer;
|
||||
var
|
||||
count1,count2:sizeint;
|
||||
begin
|
||||
Count1:=Length(n1^.name);
|
||||
Count2:=Length(n2^.name);
|
||||
Result:=Integer(Count1>Count2)-Integer(Count1<Count2);
|
||||
if (Result=0) then
|
||||
begin
|
||||
Result:=CompareByte(PChar(n1^.name)^,PChar(n2^.name)^,Count1);
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TSpirvFunc.PushBlock(New:PsrOpBlock);
|
||||
begin
|
||||
if (New=nil) then Exit;
|
||||
New^.pParent:=pBlock;
|
||||
New^.FLevel :=pBlock^.FLevel+1;
|
||||
pBlock:=New;
|
||||
end;
|
||||
|
||||
function TSpirvFunc.PopBlock:Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
if (pBlock=nil) then Exit;
|
||||
if (pBlock^.pParent=nil) then Exit;
|
||||
pBlock:=pBlock^.pParent;
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
function TSpirvFunc.line:PSpirvOp;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (pBlock<>nil) then
|
||||
begin
|
||||
Result:=pBlock^.pTail;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TSpirvFunc.Init(const fname:RawByteString;Alloc:TfnAlloc);
|
||||
begin
|
||||
name:=fname;
|
||||
pBlock:=@FTop;
|
||||
pBlock^.Alloc:=Alloc;
|
||||
pBlock^.dummy.pParent:=pBlock;
|
||||
pBlock^.Push_head(@pBlock^.dummy);
|
||||
end;
|
||||
|
||||
Procedure TSpirvFunc.mark_read;
|
||||
begin
|
||||
Inc(read_count);
|
||||
end;
|
||||
|
||||
Procedure TSpirvFunc.mark_unread;
|
||||
begin
|
||||
if (read_count<>0) then Dec(read_count);
|
||||
end;
|
||||
|
||||
function TSpirvFunc.NewSpirvOp(OpId:DWORD):PSpirvOp;
|
||||
begin
|
||||
Result:=FTop.Alloc(SizeOf(TSpirvOp));
|
||||
Result^.OpId:=OpId;
|
||||
end;
|
||||
|
||||
function TSpirvFunc.AddSpirvOp(node:PSpirvOp):PSpirvOp;
|
||||
begin
|
||||
Result:=node;
|
||||
if (node=nil) then Exit;
|
||||
pBlock^.Push_tail(node);
|
||||
node^.pParent:=pBlock;
|
||||
end;
|
||||
|
||||
function TSpirvFunc.AddSpirvOp(OpId:DWORD):PSpirvOp;
|
||||
begin
|
||||
Result:=AddSpirvOp(NewSpirvOp(OpId));
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
procedure TsrOpBlockSimple.Init(cb:TfnAlloc);
|
||||
begin
|
||||
Alloc:=cb;
|
||||
end;
|
||||
|
||||
function TsrOpBlockSimple.NewSpirvOp(OpId:DWORD):PSpirvOp;
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TSpirvOp));
|
||||
Result^.OpId:=OpId;
|
||||
end;
|
||||
|
||||
function TsrOpBlockSimple.AddSpirvOp(node:PSpirvOp):PSpirvOp;
|
||||
begin
|
||||
Result:=node;
|
||||
if (node=nil) then Exit;
|
||||
Push_tail(node);
|
||||
node^.pParent:=@Self;
|
||||
end;
|
||||
|
||||
function TsrOpBlockSimple.AddSpirvOp(OpId:DWORD):PSpirvOp;
|
||||
begin
|
||||
Result:=AddSpirvOp(NewSpirvOp(OpId));
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TsrFuncList.Search(const name:RawByteString):PSpirvFunc;
|
||||
var
|
||||
node:TSpirvFunc;
|
||||
begin
|
||||
node:=Default(TSpirvFunc);
|
||||
node.name:=name;
|
||||
Result:=FNTree.Find(@node);
|
||||
end;
|
||||
|
||||
procedure TsrFuncList.Insert(new:PSpirvFunc);
|
||||
begin
|
||||
FNTree.Insert(new);
|
||||
FList.Push_head(new);
|
||||
end;
|
||||
|
||||
//--
|
||||
|
||||
function TsrCacheOp.c(n1,n2:PsrCacheOp):Integer;
|
||||
var
|
||||
count:DWORD;
|
||||
begin
|
||||
Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrCacheOp.key));
|
||||
if (Result=0) then
|
||||
begin
|
||||
count:=n1^.key.count;
|
||||
if (count<>0) then
|
||||
begin
|
||||
Result:=CompareByte(n1^.Data,n2^.Data,count*SizeOf(Pointer));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrCacheOp.GetCompItem(i:Byte):PsrRegNode; inline;
|
||||
begin
|
||||
Result:=PPsrRegNode(@Data)[i];
|
||||
end;
|
||||
|
||||
Procedure TsrCacheOp.SetCompItem(i:Byte;p:PsrRegNode); inline;
|
||||
begin
|
||||
PPsrRegNode(@Data)[i]:=p;
|
||||
end;
|
||||
|
||||
function TsrCacheOpList.Fetch(place:PsrOpBlock;OpId:DWORD;rtype:TsrDataType;count:Byte;src:PPsrRegNode):PsrCacheOp;
|
||||
var
|
||||
i:Byte;
|
||||
size:ptruint;
|
||||
rec:record
|
||||
node:TsrCacheOp;
|
||||
align:array[0..3] of Pointer;
|
||||
end;
|
||||
begin
|
||||
Assert(place<>nil);
|
||||
Assert((count>0) and (count<=4));
|
||||
Result:=nil;
|
||||
rec.node:=Default(TsrCacheOp);
|
||||
rec.node.key.place:=place;
|
||||
rec.node.key.OpId :=OpId;
|
||||
rec.node.key.dtype:=rtype;
|
||||
rec.node.key.count:=count;
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
rec.node.SetCompItem(i,src[i]);
|
||||
end;
|
||||
Result:=FNTree.Find(@rec.node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
size:=SizeOf(TsrCacheOp)+SizeOf(Pointer)*count;
|
||||
Result:=Alloc(size);
|
||||
Move(rec.node,Result^,Size);
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
357
spirv/srOpUtils.pas
Normal file
357
spirv/srOpUtils.pas
Normal file
@ -0,0 +1,357 @@
|
||||
unit srOpUtils;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$MODESWITCH ADVANCEDRECORDS}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
spirv,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srReg,
|
||||
srConst,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srOp;
|
||||
|
||||
const
|
||||
OpLinks =DWORD(-1);
|
||||
OpBlock =DWORD(-2);
|
||||
OpMakeExp=DWORD(-3);
|
||||
OpMakeVec=DWORD(-4);
|
||||
OpIAddExt=DWORD(-5);
|
||||
OpISubExt=DWORD(-6);
|
||||
OpAbsDiff=DWORD(-7);
|
||||
OpWQM32 =DWORD(-8);
|
||||
OpPackOfs=DWORD(-9);
|
||||
//OpMED3F
|
||||
|
||||
OpCUBEID =DWORD(-10);
|
||||
OpCUBESC =DWORD(-11);
|
||||
OpCUBETC =DWORD(-12);
|
||||
OpCUBEMA =DWORD(-13);
|
||||
|
||||
OpMakeCM =DWORD(-14);
|
||||
|
||||
type
|
||||
TOpParamNodeHelper = record helper for TOpParamNode
|
||||
function AsParam:TOpParamSingle;
|
||||
function AsReg:Pointer;
|
||||
function AsVar:Pointer;
|
||||
function AsChain:Pointer;
|
||||
function TryGetValue(var V:DWORD):Boolean;
|
||||
end;
|
||||
|
||||
function InsSpirvOp(pLine,pNew:PspirvOp):PSpirvOp;
|
||||
Procedure MarkUnreadParamSingle(const node:TOpParamSingle);
|
||||
Function get_inverse_cmp_op(OpId:DWORD):DWORD;
|
||||
Function is_term_op(OpId:DWORD):Boolean;
|
||||
Function is_merge_op(OpId:DWORD):Boolean;
|
||||
Function is_term_op(pLine:PspirvOp):Boolean;
|
||||
procedure _up_merge_line(var pLine:PspirvOp);
|
||||
function FindUpSameOp(pLine,node:PspirvOp):PspirvOp;
|
||||
|
||||
function GreaterThanLine(p1,p2:PspirvOp):Boolean; //(p1>p2)
|
||||
function GetMaxPlace(pLine:PSpirvOp;count:Byte;src:PPsrRegNode):PSpirvOp;
|
||||
|
||||
implementation
|
||||
|
||||
function TOpParamNodeHelper.AsParam:TOpParamSingle;
|
||||
begin
|
||||
Result:=Default(TOpParamSingle);
|
||||
if (@Self=nil) then Exit;
|
||||
Result.ntype:=ntype;
|
||||
Result.pData:=pData;
|
||||
end;
|
||||
|
||||
function TOpParamNodeHelper.AsReg:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (ntype<>ntReg) then Exit;
|
||||
Result:=pData;
|
||||
end;
|
||||
|
||||
function TOpParamNodeHelper.AsVar:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (ntype<>ntVar) then Exit;
|
||||
Result:=pData;
|
||||
end;
|
||||
|
||||
function TOpParamNodeHelper.AsChain:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (ntype<>ntChain) then Exit;
|
||||
Result:=pData;
|
||||
end;
|
||||
|
||||
function TOpParamNodeHelper.TryGetValue(var V:DWORD):Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
if (@Self=nil) then Exit;
|
||||
if (ntype<>ntLiteral) then Exit;
|
||||
V:=Value;
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
//--
|
||||
|
||||
function InsSpirvOp(pLine,pNew:PspirvOp):PSpirvOp;
|
||||
begin
|
||||
Result:=nil;
|
||||
Assert(pLine<>nil);
|
||||
if (pLine=nil) or (pNew=nil) then Exit;
|
||||
|
||||
if (pLine^.pNext<>nil) then
|
||||
begin
|
||||
pNew^.adr:=pLine^.adr;
|
||||
end;
|
||||
|
||||
pLine^.InsertAfter(pNew);
|
||||
Result:=pNew;
|
||||
end;
|
||||
|
||||
Procedure MarkUnreadParamSingle(const node:TOpParamSingle);
|
||||
begin
|
||||
Case node.ntype of
|
||||
ntLiteral:;
|
||||
ntConst:PsrConst (node.pData)^.mark_unread;
|
||||
ntType :PsrType (node.pData)^.mark_unread;
|
||||
ntFunc :PSpirvFunc (node.pData)^.mark_unread;
|
||||
ntVar :PsrVariable(node.pData)^.mark_unread;
|
||||
ntRefId:;
|
||||
ntReg :PsrRegNode (node.pData)^.mark_unread;
|
||||
//ntReg :RegUnmark(node.pData);
|
||||
ntChain:PsrChain (node.pData)^.mark_unread;
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
end;
|
||||
|
||||
function GreaterThanLine(p1,p2:PspirvOp):Boolean; //(p1>p2)
|
||||
begin
|
||||
Result:=False;
|
||||
p2:=p2^.pNext;
|
||||
While (p2<>nil) do
|
||||
begin
|
||||
if (p1=p2) then Exit(True);
|
||||
p2:=p2^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function ParentOf(pLine,pCurr:PsrOpBlock):Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
While (pLine<>nil) do
|
||||
begin
|
||||
if (pLine=pCurr) then Exit(True);
|
||||
pLine:=pLine^.pParent;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetMaxPlace(pLine:PSpirvOp;count:Byte;src:PPsrRegNode):PSpirvOp;
|
||||
var
|
||||
m,t:PSpirvOp;
|
||||
i:Byte;
|
||||
begin
|
||||
Result:=pLine;
|
||||
if (count=0) or (src=nil) then Exit;
|
||||
m:=nil;
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
t:=src[i]^.pLine;
|
||||
if not src[i]^.is_const then
|
||||
if ParentOf(pLine^.pParent,t^.pParent) then
|
||||
begin
|
||||
if (m=nil) then
|
||||
begin
|
||||
m:=t;
|
||||
end else
|
||||
if (m^.pParent=t^.pParent) then
|
||||
begin
|
||||
if GreaterThanLine(t,m) then
|
||||
begin
|
||||
m:=t;
|
||||
end;
|
||||
end else
|
||||
if (t^.pParent^.FLevel>m^.pParent^.FLevel) then
|
||||
begin
|
||||
m:=t;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
if (m<>nil) then
|
||||
begin
|
||||
Result:=m;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function get_inverse_cmp_op(OpId:DWORD):DWORD;
|
||||
begin
|
||||
Result:=0;
|
||||
Case OpId of
|
||||
Op.OpFOrdLessThan :Result:=Op.OpFOrdGreaterThan ;
|
||||
Op.OpFOrdEqual :Result:=Op.OpFOrdEqual ;
|
||||
Op.OpFOrdLessThanEqual :Result:=Op.OpFOrdGreaterThanEqual ;
|
||||
Op.OpFOrdGreaterThan :Result:=Op.OpFOrdLessThan ;
|
||||
Op.OpFOrdNotEqual :Result:=Op.OpFOrdNotEqual ;
|
||||
Op.OpFOrdGreaterThanEqual :Result:=Op.OpFOrdLessThanEqual ;
|
||||
Op.OpOrdered :Result:=Op.OpOrdered ;
|
||||
Op.OpUnordered :Result:=Op.OpUnordered ;
|
||||
Op.OpFUnordLessThan :Result:=Op.OpFUnordGreaterThan ;
|
||||
Op.OpFUnordEqual :Result:=Op.OpFUnordEqual ;
|
||||
Op.OpFUnordLessThanEqual :Result:=Op.OpFUnordGreaterThanEqual;
|
||||
Op.OpFUnordGreaterThan :Result:=Op.OpFUnordLessThan ;
|
||||
Op.OpFUnordNotEqual :Result:=Op.OpFUnordNotEqual ;
|
||||
Op.OpFUnordGreaterThanEqual:Result:=Op.OpFUnordLessThanEqual ;
|
||||
|
||||
Op.OpSLessThan :Result:=Op.OpSGreaterThan ;
|
||||
Op.OpIEqual :Result:=Op.OpIEqual ;
|
||||
Op.OpSLessThanEqual :Result:=Op.OpSGreaterThanEqual ;
|
||||
Op.OpSGreaterThan :Result:=Op.OpSLessThan ;
|
||||
Op.OpINotEqual :Result:=Op.OpINotEqual ;
|
||||
Op.OpSGreaterThanEqual :Result:=Op.OpSLessThanEqual ;
|
||||
|
||||
Op.OpULessThan :Result:=Op.OpUGreaterThan ;
|
||||
Op.OpULessThanEqual :Result:=Op.OpUGreaterThanEqual ;
|
||||
Op.OpUGreaterThan :Result:=Op.OpULessThan ;
|
||||
Op.OpUGreaterThanEqual :Result:=Op.OpULessThanEqual ;
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
end;
|
||||
|
||||
Function is_term_op(OpId:DWORD):Boolean;
|
||||
begin
|
||||
Case OpId of
|
||||
Op.OpBranch,
|
||||
Op.OpBranchConditional,
|
||||
Op.OpSwitch,
|
||||
Op.OpReturn,
|
||||
Op.OpReturnValue,
|
||||
Op.OpKill,
|
||||
Op.OpTerminateInvocation,
|
||||
Op.OpDemoteToHelperInvocation,
|
||||
Op.OpUnreachable:Result:=True;
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function is_merge_op(OpId:DWORD):Boolean;
|
||||
begin
|
||||
Case OpId of
|
||||
Op.OpSelectionMerge,
|
||||
Op.OpLoopMerge:Result:=True;
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function is_term_op(pLine:PspirvOp):Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
if (pLine=nil) then Exit;
|
||||
|
||||
repeat //up
|
||||
Case pLine^.OpId of
|
||||
Op.OpNop,
|
||||
OpLinks:pLine:=pLine^.pPrev;
|
||||
OpBlock:pLine:=PsrOpBlock(pLine^.dst.pData)^.pTail;
|
||||
else
|
||||
Break;
|
||||
end;
|
||||
if (pLine=nil) then Exit;
|
||||
until false;
|
||||
|
||||
Result:=is_term_op(pLine^.OpId);
|
||||
end;
|
||||
|
||||
procedure _up_merge_line(var pLine:PspirvOp);
|
||||
begin
|
||||
repeat
|
||||
if is_merge_op(pLine^.OpId) then
|
||||
begin
|
||||
pLine:=pLine^.pPrev;
|
||||
Assert(pLine<>nil);
|
||||
end else
|
||||
begin
|
||||
Break;
|
||||
end;
|
||||
until false;
|
||||
end;
|
||||
|
||||
function CompareParam(p1,p2:POpParamNode):Boolean;
|
||||
begin
|
||||
Result:=(p1^.ntype=p2^.ntype) and (p1^.pData=p2^.pData);
|
||||
end;
|
||||
|
||||
function CompareOp(p1,p2:PspirvOp):Boolean;
|
||||
var
|
||||
n1,n2:POpParamNode;
|
||||
begin
|
||||
Result:=False;
|
||||
if (p1^.OpId<>p2^.OpId) then Exit;
|
||||
if (p1^.dst_type<>p2^.dst_type) then Exit;
|
||||
|
||||
n1:=p1^.pParam.pHead;
|
||||
n2:=p2^.pParam.pHead;
|
||||
|
||||
While (n1<>nil) do
|
||||
begin
|
||||
if (n2=nil) then Exit;
|
||||
if not CompareParam(n1,n2) then Exit;
|
||||
n1:=n1^.pNext;
|
||||
n2:=n2^.pNext;
|
||||
end;
|
||||
|
||||
Result:=(n2=nil);
|
||||
end;
|
||||
|
||||
function FindUpSameOp(pLine,node:PspirvOp):PspirvOp;
|
||||
var
|
||||
tmp:PspirvOp;
|
||||
pBlock:PsrOpBlock;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (pLine=nil) or (node=nil) then Exit;
|
||||
|
||||
While (pLine<>nil) do
|
||||
begin
|
||||
if CompareOp(pLine,node) then Exit(pLine);
|
||||
tmp:=pLine^.pPrev;
|
||||
if (tmp=nil) then
|
||||
begin
|
||||
pBlock:=pLine^.pParent;
|
||||
if (pBlock=nil) then Exit;
|
||||
tmp:=pBlock^.pUpLine;
|
||||
if (tmp=nil) then
|
||||
begin
|
||||
pBlock:=pBlock^.pParent;
|
||||
if (pBlock=nil) then Exit;
|
||||
tmp:=pBlock^.pHead;
|
||||
While (tmp<>nil) do
|
||||
begin
|
||||
if (tmp^.OpId=OpBlock) and (tmp^.dst.pData=pBlock) then
|
||||
begin
|
||||
tmp:=tmp^.pPrev;
|
||||
Break;
|
||||
end;
|
||||
tmp:=tmp^.pNext;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
tmp:=tmp^.pPrev;
|
||||
end;
|
||||
end;
|
||||
pLine:=tmp;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
140
spirv/srOutput.pas
Normal file
140
spirv/srOutput.pas
Normal file
@ -0,0 +1,140 @@
|
||||
unit srOutput;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
typinfo,
|
||||
spirv,
|
||||
srNodes,
|
||||
srOp,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srDecorate;
|
||||
|
||||
type
|
||||
TpsslExportType=(
|
||||
etMrt0,etMrt1,etMrt2,etMrt3,
|
||||
etMrt4,etMrt5,etMrt6,etMrt7,
|
||||
etMrtz,
|
||||
etNull,
|
||||
etUnknow0,etUnknow1,
|
||||
etPos0,etPos1,etPos2,etPos3,
|
||||
etUnknow2,etUnknow3,
|
||||
etUnknow4,etUnknow5,
|
||||
etUnknow6,etUnknow7,
|
||||
etUnknow8,etUnknow9,
|
||||
etUnknow10,etUnknow11,
|
||||
etUnknow12,etUnknow13,
|
||||
etUnknow14,etUnknow15,
|
||||
etUnknow16,etUnknow17,
|
||||
etParam0 ,etParam1 ,etParam2 ,etParam3,
|
||||
etParam4 ,etParam5 ,etParam6 ,etParam7,
|
||||
etParam8 ,etParam9 ,etParam10,etParam11,
|
||||
etParam12,etParam13,etParam14,etParam15,
|
||||
etParam16,etParam17,etParam18,etParam19,
|
||||
etParam20,etParam21,etParam22,etParam23,
|
||||
etParam24,etParam25,etParam26,etParam27,
|
||||
etParam28,etParam29,etParam30,etParam31
|
||||
);
|
||||
|
||||
PsrOutput=^TsrOutput;
|
||||
TsrOutput=object(TsrDescriptor)
|
||||
etype:TpsslExportType;
|
||||
function GetName:RawByteString;
|
||||
end;
|
||||
|
||||
TsrOutputList=object
|
||||
data:array[TpsslExportType] of TsrOutput;
|
||||
Procedure Init;
|
||||
function Fetch(etype:TpsslExportType):PsrOutput;
|
||||
procedure AllocBinding(Decorates:PsrDecorateList);
|
||||
procedure AllocEntryPoint(EntryPoint:PSpirvOp);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TsrOutput.GetName:RawByteString;
|
||||
begin
|
||||
Result:=GetEnumName(TypeInfo(TpsslExportType),ord(etype));
|
||||
end;
|
||||
|
||||
Procedure TsrOutputList.Init;
|
||||
var
|
||||
i:TpsslExportType;
|
||||
begin
|
||||
For i:=Low(TpsslExportType) to High(TpsslExportType) do
|
||||
begin
|
||||
data[i].etype:=i;
|
||||
data[i].FStorage:=StorageClass.Output;
|
||||
data[i].FBinding:=-1;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrOutputList.Fetch(etype:TpsslExportType):PsrOutput;
|
||||
begin
|
||||
Result:=@data[etype];
|
||||
end;
|
||||
|
||||
procedure TsrOutputList.AllocBinding(Decorates:PsrDecorateList);
|
||||
var
|
||||
i:TpsslExportType;
|
||||
pVar:PsrVariable;
|
||||
FLocation:Integer;
|
||||
begin
|
||||
if (Decorates=nil) then Exit;
|
||||
For i:=Low(TpsslExportType) to High(TpsslExportType) do
|
||||
begin
|
||||
pVar:=data[i].pVar;
|
||||
if (pVar<>nil) then
|
||||
begin
|
||||
Case i of
|
||||
etMrt0..etMrt7:
|
||||
begin
|
||||
if (data[i].FBinding=-1) then //alloc
|
||||
begin
|
||||
FLocation:=ord(i)-ord(etMrt0);
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,FLocation);
|
||||
data[i].FBinding:=FLocation;
|
||||
end;
|
||||
//Decoration.Index; ???
|
||||
end;
|
||||
//etMrtz,
|
||||
etPos0:
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.Position);
|
||||
end;
|
||||
//etPos1..etPos3,
|
||||
etParam0..etParam31: //interpolate param
|
||||
begin
|
||||
FLocation:=ord(i)-ord(etParam0);
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,FLocation);
|
||||
data[i].FBinding:=FLocation;
|
||||
end;
|
||||
else
|
||||
Assert(False,'AllocBinding');
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TsrOutputList.AllocEntryPoint(EntryPoint:PSpirvOp);
|
||||
var
|
||||
i:TpsslExportType;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (EntryPoint=nil) then Exit;
|
||||
For i:=Low(TpsslExportType) to High(TpsslExportType) do
|
||||
begin
|
||||
pVar:=data[i].pVar;
|
||||
if (pVar<>nil) then
|
||||
begin
|
||||
EntryPoint^.AddParam(ntVar,pVar);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
84
spirv/srParser.pas
Normal file
84
spirv/srParser.pas
Normal file
@ -0,0 +1,84 @@
|
||||
unit srParser;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
srLabel,
|
||||
srCFG,
|
||||
srNodes;
|
||||
|
||||
type
|
||||
TsrCursor=object(TsrLCursor)
|
||||
pCode:PsrCodeBlock;
|
||||
pBlock:PsrCFGBlock;
|
||||
function PopBlock:Boolean;
|
||||
end;
|
||||
|
||||
TsrCodeList=specialize TNodeQueue<PsrCodeBlock>;
|
||||
TsrCodeHeap=object(TsrCodeList)
|
||||
Alloc:TfnAlloc;
|
||||
function FindByPtr(base:Pointer):PsrCodeBlock;
|
||||
function FetchByPtr(base:Pointer;bType:TsrBlockType):TsrCursor;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
//
|
||||
|
||||
function TsrCodeHeap.FindByPtr(base:Pointer):PsrCodeBlock;
|
||||
var
|
||||
node:PsrCodeBlock;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if node^.IsContain(base) then
|
||||
begin
|
||||
Exit(node);
|
||||
end;
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrCodeHeap.FetchByPtr(base:Pointer;bType:TsrBlockType):TsrCursor;
|
||||
var
|
||||
node:PsrCodeBlock;
|
||||
adr:TSrcAdr;
|
||||
begin
|
||||
node:=FindByPtr(base);
|
||||
if (node=nil) then
|
||||
begin
|
||||
node:=Alloc(SizeOf(TsrCodeBlock));
|
||||
node^.Alloc:=Alloc;
|
||||
if parse_code_cfg(bType,base,node)>1 then Assert(False);
|
||||
Push_tail(node);
|
||||
end;
|
||||
|
||||
Result:=Default(TsrCursor);
|
||||
Result.Init(node^.Body);
|
||||
Result.pCode :=node;
|
||||
Result.pBlock:=@node^.FTop;
|
||||
|
||||
adr:=Default(TSrcAdr);
|
||||
adr.pBody:=node^.Body;
|
||||
adr.Offdw:=(Pointer(base)-Pointer(adr.pBody)) div 4;
|
||||
Result.Adr:=adr;
|
||||
|
||||
Result.pBlock:=Result.pBlock^.DownBlock(adr);
|
||||
end;
|
||||
|
||||
function TsrCursor.PopBlock:Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
if (pBlock=nil) then Exit;
|
||||
if (pBlock^.pParent=nil) then Exit;
|
||||
pBlock:=pBlock^.pParent;
|
||||
Result:=True;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
49
spirv/srRefId.pas
Normal file
49
spirv/srRefId.pas
Normal file
@ -0,0 +1,49 @@
|
||||
unit srRefId;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
PsrRefId=^TsrRefId;
|
||||
TsrRefId=packed object
|
||||
ID:DWORD;
|
||||
function Alloc:Boolean; inline;
|
||||
end;
|
||||
|
||||
PsrRefIdAlloc=^TsrRefIdAlloc;
|
||||
TsrRefIdAlloc=object
|
||||
FSpirvID:DWORD;
|
||||
function FetchSpirvID:DWORD; inline;
|
||||
procedure FetchSpirvID(P:PsrRefId);
|
||||
function GetSpirvIDBound:DWORD; inline;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TsrRefId.Alloc:Boolean; inline;
|
||||
begin
|
||||
Result:=(ID<>0);
|
||||
end;
|
||||
|
||||
function TsrRefIdAlloc.FetchSpirvID:DWORD; inline;
|
||||
begin
|
||||
Inc(FSpirvID);
|
||||
Result:=FSpirvID;
|
||||
end;
|
||||
|
||||
procedure TsrRefIdAlloc.FetchSpirvID(P:PsrRefId);
|
||||
begin
|
||||
if (P<>nil) and (not P^.Alloc) then
|
||||
begin
|
||||
P^.ID:=FetchSpirvID;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrRefIdAlloc.GetSpirvIDBound:DWORD; inline;
|
||||
begin
|
||||
Result:=FSpirvID+1;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
469
spirv/srReg.pas
Normal file
469
spirv/srReg.pas
Normal file
@ -0,0 +1,469 @@
|
||||
unit srReg;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
srNodes,
|
||||
srRefId,
|
||||
srTypes,
|
||||
srConst;
|
||||
|
||||
type
|
||||
PPsrRegSlot=^PsrRegSlot;
|
||||
PsrRegSlot=^TsrRegSlot;
|
||||
|
||||
PPsrRegNode=^PsrRegNode;
|
||||
PsrRegNode=^TsrRegNode;
|
||||
TsrRegNode=packed object
|
||||
pPrev,pNext:PsrRegNode;
|
||||
//----
|
||||
read_count:DWORD;
|
||||
ID:TsrRefId; //post id
|
||||
pSlot:PsrRegSlot;
|
||||
pWriter:TOpParamSingle; //ntReg,ntConst,ntOp,ntVolatile
|
||||
pLine:Pointer; //PspirvOp;
|
||||
dtype:TsrDataType;
|
||||
function GetName:RawByteString;
|
||||
Procedure mark_read;
|
||||
Procedure mark_unread;
|
||||
procedure SetConst(pConst:PsrConst);
|
||||
function AsConst:PsrConst;
|
||||
function AsOp:Pointer;
|
||||
function AsReg:Pointer;
|
||||
function is_const:Boolean;
|
||||
function is_bool:Boolean;
|
||||
function is_bool_or_const_bool:Boolean;
|
||||
function is_unknow:Boolean;
|
||||
end;
|
||||
|
||||
TRegStory=specialize TNodeList<PsrRegNode>;
|
||||
|
||||
TString5=string[5];
|
||||
|
||||
TsrRegSlot=object
|
||||
Alloc:TfnAlloc;
|
||||
pVar:Pointer;
|
||||
pStory:TRegStory;
|
||||
rid:TString5;
|
||||
Procedure Init(a:TfnAlloc;const n:TString5);
|
||||
function first:PsrRegNode;
|
||||
function current:PsrRegNode;
|
||||
function New(pLine:Pointer;rtype:TsrDataType):PsrRegNode;
|
||||
function NewAfter(rtype:TsrDataType;r:PsrRegNode):PsrRegNode;
|
||||
procedure Remove(r:PsrRegNode);
|
||||
end;
|
||||
|
||||
PsrRegsSnapshot=^TsrRegsSnapshot;
|
||||
TsrRegsSnapshot=object
|
||||
SGRP:array[0..103] of PsrRegNode;
|
||||
VCC:array[0..1] of PsrRegNode;
|
||||
M0:PsrRegNode;
|
||||
EXEC:array[0..1] of PsrRegNode;
|
||||
SCC:PsrRegNode;
|
||||
VGRP:array[0..255] of PsrRegNode;
|
||||
end;
|
||||
|
||||
TForEachSlot=procedure(pSlot:PsrRegSlot) of object;
|
||||
TForEachSnap=procedure(pSlot:PsrRegSlot;var old:PsrRegNode) of object;
|
||||
|
||||
TsrRegsStory=object
|
||||
SGRP:array[0..103] of TsrRegSlot;
|
||||
VCC:array[0..1] of TsrRegSlot;
|
||||
M0:TsrRegSlot;
|
||||
EXEC:array[0..1] of TsrRegSlot;
|
||||
SCC:TsrRegSlot;
|
||||
VGRP:array[0..255] of TsrRegSlot;
|
||||
FUnattach:TsrRegSlot;
|
||||
Procedure Init(Alloc:TfnAlloc);
|
||||
function get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean;
|
||||
function get_sdst7(SDST:Byte):PsrRegSlot;
|
||||
function get_ssrc8(SSRC:Byte):PsrRegSlot;
|
||||
function get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean;
|
||||
function get_ssrc9(SSRC:Word):PsrRegSlot;
|
||||
function get_vsrc8(VSRC:Byte):PsrRegSlot;
|
||||
function get_vdst8(VDST:Byte):PsrRegSlot;
|
||||
function get_sbase(SBASE,count:Byte;src:PPsrRegSlot):Boolean;
|
||||
function get_srsrc(SRSRC,count:Byte;src:PPsrRegSlot):Boolean;
|
||||
|
||||
function get_snapshot:TsrRegsSnapshot;
|
||||
procedure ForEachSlot(cb:TForEachSlot);
|
||||
procedure ForEachSnap(cb:TForEachSnap;old:PsrRegsSnapshot);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
Procedure TsrRegsStory.Init(Alloc:TfnAlloc);
|
||||
var
|
||||
i:Word;
|
||||
n:TString5;
|
||||
begin
|
||||
FillChar(Self,SizeOf(TsrRegsStory),0);
|
||||
For i:=0 to 103 do
|
||||
begin
|
||||
Str(i,n);
|
||||
SGRP[i].Init(Alloc,'S'+n);
|
||||
end;
|
||||
VCC[0].Init(Alloc,'VCCL');
|
||||
VCC[1].Init(Alloc,'VCCH');
|
||||
M0.Init(Alloc,'M0');
|
||||
EXEC[0].Init(Alloc,'EXECL');
|
||||
EXEC[1].Init(Alloc,'EXECH');
|
||||
SCC.Init(Alloc,'SCC');
|
||||
For i:=0 to 255 do
|
||||
begin
|
||||
Str(i,n);
|
||||
VGRP[i].Init(Alloc,'V'+n);
|
||||
end;
|
||||
FUnattach.Init(Alloc,'UNATT');
|
||||
end;
|
||||
|
||||
function TsrRegsStory.get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean;
|
||||
begin
|
||||
Result:=True;
|
||||
if (dst=nil) then Exit(false);
|
||||
Case SDST of
|
||||
0..102:
|
||||
begin
|
||||
dst[0]:=@SGRP[SDST];
|
||||
dst[1]:=@SGRP[SDST+1];
|
||||
end;
|
||||
106:
|
||||
begin
|
||||
dst[0]:=@VCC[0];
|
||||
dst[1]:=@VCC[1];
|
||||
end;
|
||||
126:
|
||||
begin
|
||||
dst[0]:=@EXEC[0];
|
||||
dst[1]:=@EXEC[1];
|
||||
end;
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrRegsStory.get_sdst7(SDST:Byte):PsrRegSlot;
|
||||
begin
|
||||
Case SDST of
|
||||
0..103:Result:=@SGRP[SDST];
|
||||
106:Result:=@VCC[0];
|
||||
107:Result:=@VCC[1];
|
||||
124:Result:=@M0;
|
||||
126:Result:=@EXEC[0];
|
||||
127:Result:=@EXEC[1];
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrRegsStory.get_ssrc8(SSRC:Byte):PsrRegSlot;
|
||||
begin
|
||||
Case SSRC of
|
||||
0..103:Result:=@SGRP[SSRC];
|
||||
106:Result:=@VCC[0];
|
||||
107:Result:=@VCC[1];
|
||||
124:Result:=@M0;
|
||||
126:Result:=@EXEC[0];
|
||||
127:Result:=@EXEC[1];
|
||||
|
||||
//251:Result:=@VCC[0]; //VCCZ
|
||||
//252:Result:=@EXEC[0]; //EXECZ
|
||||
|
||||
253:Result:=@SCC;
|
||||
//254:Write('LDS_DIRECT');
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrRegsStory.get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean;
|
||||
begin
|
||||
Result:=True;
|
||||
if (src=nil) then Exit(False);
|
||||
Case SSRC of
|
||||
0..102:
|
||||
begin
|
||||
src[0]:=@SGRP[SSRC];
|
||||
src[1]:=@SGRP[SSRC+1];
|
||||
end;
|
||||
106:
|
||||
begin
|
||||
src[0]:=@VCC[0];
|
||||
src[1]:=@VCC[1];
|
||||
end;
|
||||
126:
|
||||
begin
|
||||
src[0]:=@EXEC[0];
|
||||
src[1]:=@EXEC[1];
|
||||
end;
|
||||
256..510:
|
||||
begin
|
||||
src[0]:=@VGRP[SSRC-256];
|
||||
src[1]:=@VGRP[SSRC-255];
|
||||
end;
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrRegsStory.get_ssrc9(SSRC:Word):PsrRegSlot;
|
||||
begin
|
||||
Case SSRC of
|
||||
0..103:Result:=@SGRP[SSRC];
|
||||
106:Result:=@VCC[0];
|
||||
107:Result:=@VCC[1];
|
||||
124:Result:=@M0;
|
||||
126:Result:=@EXEC[0];
|
||||
127:Result:=@EXEC[1];
|
||||
|
||||
//251:Result:=@VCC[0]; //VCCZ
|
||||
//252:Result:=@EXEC[0]; //EXECZ
|
||||
|
||||
253:Result:=@SCC;
|
||||
//254:Write('LDS_DIRECT');
|
||||
256..511:Result:=@VGRP[SSRC-256];
|
||||
else
|
||||
Result:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrRegsStory.get_vsrc8(VSRC:Byte):PsrRegSlot;
|
||||
begin
|
||||
Result:=@VGRP[VSRC];
|
||||
end;
|
||||
|
||||
function TsrRegsStory.get_vdst8(VDST:Byte):PsrRegSlot;
|
||||
begin
|
||||
Result:=@VGRP[VDST];
|
||||
end;
|
||||
|
||||
//SBASE 0..63
|
||||
//SGRP:array[0..103] of TpsslRegSlot;
|
||||
function TsrRegsStory.get_sbase(SBASE,count:Byte;src:PPsrRegSlot):Boolean;
|
||||
var
|
||||
i,p:Byte;
|
||||
begin
|
||||
Result:=True;
|
||||
if (SBASE>63) or (count=0) or (src=nil) then Exit(False);
|
||||
p:=SBASE*2;
|
||||
if ((p+count)>104) then Exit(False);
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
src[i]:=@SGRP[p+i];
|
||||
end;
|
||||
end;
|
||||
|
||||
//SRSRC 0..31
|
||||
function TsrRegsStory.get_srsrc(SRSRC,count:Byte;src:PPsrRegSlot):Boolean;
|
||||
var
|
||||
i,p:Byte;
|
||||
begin
|
||||
Result:=True;
|
||||
if (SRSRC>31) or (count=0) or (src=nil) then Exit(False);
|
||||
p:=SRSRC*4;
|
||||
if ((p+count)>104) then Exit(False);
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
src[i]:=@SGRP[p+i];
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TsrRegsStory.get_snapshot:TsrRegsSnapshot;
|
||||
var
|
||||
i:Word;
|
||||
begin
|
||||
Result:=Default(TsrRegsSnapshot);
|
||||
For i:=0 to 103 do
|
||||
begin
|
||||
Result.SGRP[i]:=SGRP[i].current;
|
||||
end;
|
||||
For i:=0 to 1 do
|
||||
begin
|
||||
Result.VCC[i] :=VCC[i].current;
|
||||
end;
|
||||
Result.M0 :=M0.current;
|
||||
For i:=0 to 1 do
|
||||
begin
|
||||
Result.EXEC[i]:=EXEC[i].current;
|
||||
end;
|
||||
Result.SCC :=SCC.current;
|
||||
For i:=0 to 255 do
|
||||
begin
|
||||
Result.VGRP[i]:=VGRP[i].current;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrRegsStory.ForEachSlot(cb:TForEachSlot);
|
||||
var
|
||||
i:Word;
|
||||
begin
|
||||
if (cb=nil) then Exit;
|
||||
For i:=0 to 103 do
|
||||
begin
|
||||
cb(@SGRP[i]);
|
||||
end;
|
||||
For i:=0 to 1 do
|
||||
begin
|
||||
cb(@VCC[i]);
|
||||
end;
|
||||
cb(@M0);
|
||||
For i:=0 to 1 do
|
||||
begin
|
||||
cb(@EXEC[i]);
|
||||
end;
|
||||
cb(@SCC);
|
||||
For i:=0 to 255 do
|
||||
begin
|
||||
cb(@VGRP[i]);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrRegsStory.ForEachSnap(cb:TForEachSnap;old:PsrRegsSnapshot);
|
||||
var
|
||||
i:Word;
|
||||
begin
|
||||
if (cb=nil) or (old=nil) then Exit;
|
||||
For i:=0 to 103 do
|
||||
begin
|
||||
cb(@SGRP[i],Old^.SGRP[i]);
|
||||
end;
|
||||
For i:=0 to 1 do
|
||||
begin
|
||||
cb(@VCC[i],Old^.VCC[i]);
|
||||
end;
|
||||
cb(@M0,Old^.M0);
|
||||
For i:=0 to 1 do
|
||||
begin
|
||||
cb(@EXEC[i],Old^.EXEC[i]);
|
||||
end;
|
||||
cb(@SCC,Old^.SCC);
|
||||
For i:=0 to 255 do
|
||||
begin
|
||||
cb(@VGRP[i],Old^.VGRP[i]);
|
||||
end;
|
||||
end;
|
||||
|
||||
//--
|
||||
|
||||
function TsrRegNode.GetName:RawByteString;
|
||||
begin
|
||||
Result:='';
|
||||
if (pSlot<>nil) then Result:=pSlot^.rid;
|
||||
end;
|
||||
|
||||
Procedure TsrRegNode.mark_read;
|
||||
begin
|
||||
Inc(read_count);
|
||||
end;
|
||||
|
||||
Procedure TsrRegNode.mark_unread;
|
||||
begin
|
||||
Assert(read_count<>0);
|
||||
if (read_count<>0) then Dec(read_count);
|
||||
end;
|
||||
|
||||
procedure TsrRegNode.SetConst(pConst:PsrConst);
|
||||
begin
|
||||
pWriter.SetParam(ntConst,pConst);
|
||||
dtype:=pConst^.key.dtype;
|
||||
end;
|
||||
|
||||
function TsrRegNode.AsConst:PsrConst;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (pWriter.ntype<>ntConst) then Exit;
|
||||
Result:=pWriter.pData;
|
||||
end;
|
||||
|
||||
function TsrRegNode.AsOp:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (pWriter.ntype<>ntOp) then Exit;
|
||||
Result:=pWriter.pData;
|
||||
end;
|
||||
|
||||
function TsrRegNode.AsReg:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (pWriter.ntype<>ntReg) then Exit;
|
||||
Result:=pWriter.pData;
|
||||
end;
|
||||
|
||||
function TsrRegNode.is_const:Boolean;
|
||||
begin
|
||||
Result:=(pWriter.ntype=ntConst);
|
||||
end;
|
||||
|
||||
function TsrRegNode.is_bool:Boolean;
|
||||
begin
|
||||
Result:=(dtype=dtBool);
|
||||
end;
|
||||
|
||||
function TsrRegNode.is_bool_or_const_bool:Boolean;
|
||||
begin
|
||||
Result:=is_bool or
|
||||
(is_const and (AsConst<>nil) and AsConst^.isBoolVal);
|
||||
end;
|
||||
|
||||
function TsrRegNode.is_unknow:Boolean;
|
||||
begin
|
||||
Result:=(dtype=dtUnknow);
|
||||
end;
|
||||
|
||||
//--
|
||||
|
||||
Procedure TsrRegSlot.Init(a:TfnAlloc;const n:TString5);
|
||||
begin
|
||||
Alloc:=a;
|
||||
rid :=n;
|
||||
end;
|
||||
|
||||
function TsrRegSlot.first:PsrRegNode;
|
||||
begin
|
||||
Result:=pStory.pHead;
|
||||
end;
|
||||
|
||||
function TsrRegSlot.current:PsrRegNode;
|
||||
begin
|
||||
Result:=pStory.pTail;
|
||||
end;
|
||||
|
||||
function TsrRegSlot.New(pLine:Pointer;rtype:TsrDataType):PsrRegNode;
|
||||
var
|
||||
node:PsrRegNode;
|
||||
begin
|
||||
node:=Alloc(SizeOf(TsrRegNode));
|
||||
node^.pSlot:=@Self;
|
||||
node^.dtype:=rtype;
|
||||
node^.pLine:=pLine;
|
||||
pStory.Push_tail(node);
|
||||
Result:=node;
|
||||
end;
|
||||
|
||||
function TsrRegSlot.NewAfter(rtype:TsrDataType;r:PsrRegNode):PsrRegNode;
|
||||
var
|
||||
node:PsrRegNode;
|
||||
begin
|
||||
node:=Alloc(SizeOf(TsrRegNode));
|
||||
node^.pSlot:=@Self;
|
||||
node^.dtype:=rtype;
|
||||
node^.pLine:=r^.pLine;
|
||||
pStory.InsertAfter(r,node);
|
||||
Result:=node;
|
||||
end;
|
||||
|
||||
procedure TsrRegSlot.Remove(r:PsrRegNode);
|
||||
begin
|
||||
if (r=nil) then Exit;
|
||||
pStory.Remove(r);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
952
spirv/srTypes.pas
Normal file
952
spirv/srTypes.pas
Normal file
@ -0,0 +1,952 @@
|
||||
unit srTypes;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
bittype,
|
||||
Half16,
|
||||
spirv,
|
||||
srNodes,
|
||||
srRefId;
|
||||
|
||||
type
|
||||
TsrDataType=(
|
||||
//Real types
|
||||
dtUnknow,
|
||||
dtBool,
|
||||
|
||||
dtFloat32,
|
||||
dtHalf16,
|
||||
|
||||
dtInt8,
|
||||
dtUint8,
|
||||
|
||||
dtInt16,
|
||||
dtUint16,
|
||||
|
||||
dtInt32,
|
||||
dtUint32,
|
||||
|
||||
dtInt64,
|
||||
dtUint64,
|
||||
|
||||
//Composite types
|
||||
dtVec2b,
|
||||
dtVec3b,
|
||||
dtVec4b,
|
||||
|
||||
dtStruct2u,
|
||||
|
||||
dtVec2u8,
|
||||
dtVec4u8,
|
||||
|
||||
dtVec2i8,
|
||||
dtVec4i8,
|
||||
|
||||
dtVec2u16,
|
||||
dtVec4u16,
|
||||
|
||||
dtVec2i16,
|
||||
dtVec4i16,
|
||||
|
||||
dtVec2u,
|
||||
dtVec3u,
|
||||
dtVec4u,
|
||||
|
||||
dtVec2i,
|
||||
dtVec3i,
|
||||
dtVec4i,
|
||||
|
||||
dtVec2f,
|
||||
dtVec3f,
|
||||
dtVec4f,
|
||||
|
||||
dtVec2h,
|
||||
dtVec4h,
|
||||
|
||||
//Spirv types
|
||||
dtTypeVoid,
|
||||
dtTypeFunction,
|
||||
dtTypePointer,
|
||||
dtTypeStruct,
|
||||
dtTypeArray,
|
||||
dtTypeRuntimeArray,
|
||||
dtTypeImage,
|
||||
dtTypeSampler,
|
||||
dtTypeSampledImage
|
||||
);
|
||||
|
||||
Pvec2f=^Tvec2f;
|
||||
Tvec2f=array[0..1] of Single;
|
||||
|
||||
Pvec3f=^Tvec3f;
|
||||
Tvec3f=array[0..2] of Single;
|
||||
|
||||
Pvec4f=^Tvec4f;
|
||||
Tvec4f=array[0..3] of Single;
|
||||
|
||||
Pvec2h=^Tvec2h;
|
||||
Tvec2h=array[0..1] of THalf16;
|
||||
|
||||
Pvec4h=^Tvec4h;
|
||||
Tvec4h=array[0..3] of THalf16;
|
||||
|
||||
PPsrType=^PsrType;
|
||||
PsrType=^TsrType;
|
||||
|
||||
//child - result type
|
||||
TsrTypeImageInfo=bitpacked record
|
||||
Dim :bit3; //Dim.*
|
||||
Depth :bit2; //0:no,1:yes,2:any
|
||||
Arrayed:bit1; //0:no,1:yes
|
||||
MS :bit1; //0:no,1:yes
|
||||
Sampled:bit2; //0:runtime,1:sampling,2:read/write
|
||||
Format :bit23; //ImageFormat.*
|
||||
end;
|
||||
|
||||
PsrImageInfo=^TsrImageInfo;
|
||||
TsrImageInfo=packed record
|
||||
dtype:TsrDataType;
|
||||
tinfo:TsrTypeImageInfo;
|
||||
end;
|
||||
|
||||
TsrType=object
|
||||
pPrev,pNext,pLeft,pRight:PsrType;
|
||||
//----
|
||||
ID:TsrRefId; //post id
|
||||
read_count:DWORD;
|
||||
dtype:TsrDataType;
|
||||
key:packed record
|
||||
OpId:DWORD;
|
||||
count:DWORD;
|
||||
ext:packed record
|
||||
case byte of
|
||||
0:(int_size,int_sign:DWORD);
|
||||
1:(float_size:DWORD);
|
||||
2:(storage_class:DWORD);
|
||||
3:(pField:Pointer);
|
||||
4:(array_count,array_stride:DWORD);
|
||||
5:(vector_count:DWORD);
|
||||
6:(image:TsrTypeImageInfo);
|
||||
end;
|
||||
end;
|
||||
Data:record end;
|
||||
function c(n1,n2:PsrType):Integer; static;
|
||||
Procedure mark_read;
|
||||
Procedure mark_unread;
|
||||
function GetCompItem(i:DWORD):PsrType; inline;
|
||||
Procedure SetCompItem(i:DWORD;p:PsrType); inline;
|
||||
Procedure _mark_read_child;
|
||||
Procedure _mark_unread_child;
|
||||
Procedure Clear;
|
||||
end;
|
||||
|
||||
TsrTypeList=object
|
||||
type
|
||||
TNodeList=specialize TNodeList<PsrType>;
|
||||
TNodeFetch=specialize TNodeFetch<PsrType,TsrType>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
FList:TNodeList;
|
||||
FNTree:TNodeFetch;
|
||||
function _New(count:DWORD):PsrType;
|
||||
function _Insert(node:PsrType):PsrType;
|
||||
function _Fetch(node:PsrType):PsrType;
|
||||
function _FetchVector(dtype,ctype:TsrDataType;vector_count:DWORD):PsrType;
|
||||
function Fetch(dtype:TsrDataType):PsrType;
|
||||
function FetchPointer(child:PsrType;storage_class:DWORD):PsrType;
|
||||
function FetchFunction(ret:PsrType):PsrType;
|
||||
function FetchFunction1(ret,param:PsrType):PsrType;
|
||||
function FetchStruct(child:PsrType;pField:Pointer):PsrType;
|
||||
function FetchStructNode(node:PsrType;count:DWORD;pField:Pointer):PsrType;
|
||||
function FetchArrayNode(node,child:PsrType;array_count,array_stride:DWORD):PsrType;
|
||||
function FetchArray(child:PsrType;array_count,array_stride:DWORD):PsrType;
|
||||
function FetchRuntimeArray(child:PsrType;array_stride:DWORD):PsrType;
|
||||
function FetchImage(child:PsrType;image_info:TsrTypeImageInfo):PsrType;
|
||||
function FetchSampledImage(child:PsrType):PsrType;
|
||||
end;
|
||||
|
||||
const
|
||||
ExtImgBuf:TsrTypeImageInfo=(
|
||||
Dim :0; //Dim1D
|
||||
Depth :0;
|
||||
Arrayed:0;
|
||||
MS :0;
|
||||
Sampled:2;
|
||||
Format :0; //Unknown
|
||||
);
|
||||
|
||||
ExtImage2D:TsrTypeImageInfo=(
|
||||
Dim :1; //Dim2D
|
||||
Depth :0;
|
||||
Arrayed:0;
|
||||
MS :0;
|
||||
Sampled:1;
|
||||
Format :0; //Unknown
|
||||
);
|
||||
|
||||
function _GetNodeSize(count:DWORD):ptruint; inline;
|
||||
function LazyType2(t1,t2:TsrDataType):TsrDataType;
|
||||
function LazyType3(t1,t2,t3:TsrDataType):TsrDataType;
|
||||
function isIntVector(rtype:TsrDataType):Boolean; inline;
|
||||
function isIntScalar(rtype:TsrDataType):Boolean; inline;
|
||||
function GetVecChild(rtype:TsrDataType):TsrDataType;
|
||||
function GetVecCount(rtype:TsrDataType):Byte;
|
||||
Function GetVecType(elem:TsrDataType;count:Byte):TsrDataType;
|
||||
function isVector(rtype:TsrDataType):Boolean; inline;
|
||||
function GetTypeHigh(rtype:TsrDataType):QWORD;
|
||||
function CompareType(rtype1,rtype2:TsrDataType):Boolean;
|
||||
function SignType(rtype:TsrDataType):Byte;
|
||||
function BitSizeType(rtype:TsrDataType):Byte;
|
||||
function TryBitcastType(rtype1,rtype2:TsrDataType):Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
function TsrType.c(n1,n2:PsrType):Integer;
|
||||
begin
|
||||
Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrType.key));
|
||||
if (Result<>0) then Exit;
|
||||
Result:=ComparePtruint(@n1^.Data,@n2^.Data,n1^.key.count);
|
||||
end;
|
||||
|
||||
Procedure TsrType.mark_read;
|
||||
begin
|
||||
Inc(read_count);
|
||||
end;
|
||||
|
||||
Procedure TsrType.mark_unread;
|
||||
begin
|
||||
if (read_count<>0) then Dec(read_count);
|
||||
end;
|
||||
|
||||
|
||||
function TsrType.GetCompItem(i:DWORD):PsrType; inline;
|
||||
begin
|
||||
Result:=PPsrType(@Data)[i];
|
||||
end;
|
||||
|
||||
Procedure TsrType.SetCompItem(i:DWORD;p:PsrType); inline;
|
||||
begin
|
||||
PPsrType(@Data)[i]:=p;
|
||||
end;
|
||||
|
||||
Procedure TsrType._mark_read_child;
|
||||
var
|
||||
i:DWORD;
|
||||
begin
|
||||
if (key.count<>0) then
|
||||
For i:=0 to key.count-1 do
|
||||
begin
|
||||
GetCompItem(i)^.mark_read;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrType._mark_unread_child;
|
||||
var
|
||||
i:DWORD;
|
||||
begin
|
||||
if (key.count<>0) then
|
||||
For i:=0 to key.count-1 do
|
||||
begin
|
||||
GetCompItem(i)^.mark_unread;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrType.Clear;
|
||||
var
|
||||
i:DWORD;
|
||||
begin
|
||||
if (key.count<>0) then
|
||||
begin
|
||||
For i:=0 to key.count-1 do
|
||||
begin
|
||||
GetCompItem(i)^.mark_unread;
|
||||
SetCompItem(i,nil);
|
||||
end;
|
||||
key.count:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
function _GetNodeSize(count:DWORD):ptruint; inline;
|
||||
begin
|
||||
Result:=SizeOf(TsrType)+SizeOf(Pointer)*count;
|
||||
end;
|
||||
|
||||
function TsrTypeList._New(count:DWORD):PsrType;
|
||||
begin
|
||||
Result:=Alloc(_GetNodeSize(count));
|
||||
end;
|
||||
|
||||
function TsrTypeList._Insert(node:PsrType):PsrType;
|
||||
begin
|
||||
Result:=FNTree.Find(node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
FNTree.Insert(node);
|
||||
FList.Push_tail(node);
|
||||
Result:=node;
|
||||
end else
|
||||
begin
|
||||
node^._mark_unread_child;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrTypeList._Fetch(node:PsrType):PsrType;
|
||||
var
|
||||
size:ptruint;
|
||||
begin
|
||||
Result:=FNTree.Find(node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
size:=_GetNodeSize(node^.key.count);
|
||||
Result:=Alloc(size);
|
||||
Move(node^,Result^,Size);
|
||||
FNTree.Insert(Result);
|
||||
FList.Push_tail(Result);
|
||||
end else
|
||||
begin
|
||||
node^._mark_unread_child;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrTypeList._FetchVector(dtype,ctype:TsrDataType;vector_count:DWORD):PsrType;
|
||||
var
|
||||
rec:record
|
||||
node:TsrType;
|
||||
align:Pointer;
|
||||
end;
|
||||
child:PsrType;
|
||||
begin
|
||||
Result:=nil;
|
||||
child:=Fetch(ctype);
|
||||
rec.node:=Default(TsrType);
|
||||
rec.node.dtype:=dtype;
|
||||
rec.node.key.OpId:=Op.OpTypeVector;
|
||||
rec.node.key.ext.vector_count:=vector_count;
|
||||
rec.node.key.count:=1;
|
||||
rec.node.SetCompItem(0,child);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
function TsrTypeList.Fetch(dtype:TsrDataType):PsrType;
|
||||
var
|
||||
rec:record
|
||||
node:TsrType;
|
||||
align:array[0..1] of Pointer;
|
||||
end;
|
||||
child:PsrType;
|
||||
begin
|
||||
Result:=nil;
|
||||
rec.node:=Default(TsrType);
|
||||
Case dtype of
|
||||
dtUnknow:;
|
||||
|
||||
dtBool:
|
||||
begin
|
||||
rec.node.dtype:=dtype;
|
||||
rec.node.key.OpId:=Op.OpTypeBool;
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
dtInt8,
|
||||
dtUint8,
|
||||
dtInt16,
|
||||
dtUint16,
|
||||
dtInt32,
|
||||
dtUint32,
|
||||
dtInt64,
|
||||
dtUint64:
|
||||
begin
|
||||
rec.node.dtype:=dtype;
|
||||
rec.node.key.OpId:=Op.OpTypeInt;
|
||||
rec.node.key.ext.int_sign:=SignType(dtype);
|
||||
rec.node.key.ext.int_size:=BitSizeType(dtype);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
dtFloat32,
|
||||
dtHalf16:
|
||||
begin
|
||||
rec.node.dtype:=dtype;
|
||||
rec.node.key.OpId:=Op.OpTypeFloat;
|
||||
rec.node.key.ext.float_size:=BitSizeType(dtype);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
dtTypeVoid:
|
||||
begin
|
||||
rec.node.dtype:=dtype;
|
||||
rec.node.key.OpId:=Op.OpTypeVoid;
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
dtTypeSampler:
|
||||
begin
|
||||
rec.node.dtype:=dtype;
|
||||
rec.node.key.OpId:=Op.OpTypeSampler;
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
dtVec2b,
|
||||
dtVec3b,
|
||||
dtVec4b,
|
||||
|
||||
dtVec2u8,
|
||||
dtVec4u8,
|
||||
|
||||
dtVec2i8,
|
||||
dtVec4i8,
|
||||
|
||||
dtVec2u16,
|
||||
dtVec4u16,
|
||||
|
||||
dtVec2i16,
|
||||
dtVec4i16,
|
||||
|
||||
dtVec2u,
|
||||
dtVec3u,
|
||||
dtVec4u,
|
||||
|
||||
dtVec2i,
|
||||
dtVec3i,
|
||||
dtVec4i,
|
||||
|
||||
dtVec2f,
|
||||
dtVec3f,
|
||||
dtVec4f,
|
||||
|
||||
dtVec2h,
|
||||
dtVec4h:Result:=_FetchVector(dtype,GetVecChild(dtype),GetVecCount(dtype));
|
||||
|
||||
//
|
||||
|
||||
dtStruct2u:
|
||||
begin
|
||||
child:=Fetch(dtUint32);
|
||||
child^.mark_read;
|
||||
rec.node.dtype:=dtStruct2u;
|
||||
rec.node.key.OpId:=Op.OpTypeStruct;
|
||||
rec.node.key.count:=2;
|
||||
rec.node.SetCompItem(0,child);
|
||||
rec.node.SetCompItem(1,child);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
function TsrTypeList.FetchPointer(child:PsrType;storage_class:DWORD):PsrType;
|
||||
var
|
||||
rec:record
|
||||
node:TsrType;
|
||||
align:Pointer;
|
||||
end;
|
||||
begin
|
||||
Assert(child<>nil);
|
||||
rec.node:=Default(TsrType);
|
||||
rec.node.dtype:=dtTypePointer;
|
||||
rec.node.key.OpId:=Op.OpTypePointer;
|
||||
rec.node.key.ext.storage_class:=storage_class;
|
||||
rec.node.key.count:=1;
|
||||
rec.node.SetCompItem(0,child);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
function TsrTypeList.FetchFunction(ret:PsrType):PsrType;
|
||||
var
|
||||
rec:record
|
||||
node:TsrType;
|
||||
align:Pointer;
|
||||
end;
|
||||
begin
|
||||
Assert(ret<>nil);
|
||||
rec.node:=Default(TsrType);
|
||||
rec.node.dtype:=dtTypeFunction;
|
||||
rec.node.key.OpId:=Op.OpTypeFunction;
|
||||
rec.node.key.count:=1;
|
||||
rec.node.SetCompItem(0,ret);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
function TsrTypeList.FetchFunction1(ret,param:PsrType):PsrType;
|
||||
var
|
||||
rec:record
|
||||
node:TsrType;
|
||||
align:array[0..1] of Pointer;
|
||||
end;
|
||||
begin
|
||||
Assert(ret<>nil);
|
||||
rec.node:=Default(TsrType);
|
||||
rec.node.dtype:=dtTypeFunction;
|
||||
rec.node.key.OpId:=Op.OpTypeFunction;
|
||||
rec.node.key.count:=2;
|
||||
rec.node.SetCompItem(0,ret);
|
||||
rec.node.SetCompItem(1,param);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
function TsrTypeList.FetchStruct(child:PsrType;pField:Pointer):PsrType;
|
||||
var
|
||||
rec:record
|
||||
node:TsrType;
|
||||
align:Pointer;
|
||||
end;
|
||||
begin
|
||||
Assert(child<>nil);
|
||||
rec.node:=Default(TsrType);
|
||||
rec.node.dtype:=dtTypeStruct;
|
||||
rec.node.key.OpId:=Op.OpTypeStruct;
|
||||
rec.node.key.ext.pField:=pField;
|
||||
rec.node.key.count:=1;
|
||||
rec.node.SetCompItem(0,child);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
function TsrTypeList.FetchStructNode(node:PsrType;count:DWORD;pField:Pointer):PsrType;
|
||||
begin
|
||||
Assert(node<>nil);
|
||||
node^.dtype:=dtTypeStruct;
|
||||
node^.key.OpId:=Op.OpTypeStruct;
|
||||
node^.key.ext.pField:=pField;
|
||||
node^.key.count:=count;
|
||||
Result:=_Insert(node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
function TsrTypeList.FetchArrayNode(node,child:PsrType;array_count,array_stride:DWORD):PsrType;
|
||||
var
|
||||
aUint:PsrType;
|
||||
begin
|
||||
Assert(node<>nil);
|
||||
Assert(child<>nil);
|
||||
node^:=Default(TsrType);
|
||||
node^.dtype:=dtTypeArray;
|
||||
node^.key.OpId:=Op.OpTypeArray;
|
||||
node^.key.ext.array_count:=array_count;
|
||||
node^.key.ext.array_stride:=array_stride;
|
||||
node^.key.count:=2;
|
||||
node^.SetCompItem(0,child);
|
||||
aUint:=Fetch(dtUInt32);
|
||||
node^.SetCompItem(1,aUint);
|
||||
FList.Push_tail(node);
|
||||
Result:=node;
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
function TsrTypeList.FetchArray(child:PsrType;array_count,array_stride:DWORD):PsrType;
|
||||
var
|
||||
rec:record
|
||||
node:TsrType;
|
||||
align:array[0..1] of Pointer;
|
||||
end;
|
||||
aUint:PsrType;
|
||||
begin
|
||||
Assert(child<>nil);
|
||||
rec.node:=Default(TsrType);
|
||||
rec.node.dtype:=dtTypeArray;
|
||||
rec.node.key.OpId:=Op.OpTypeArray;
|
||||
rec.node.key.ext.array_count:=array_count;
|
||||
rec.node.key.ext.array_stride:=array_stride;
|
||||
rec.node.key.count:=2;
|
||||
rec.node.SetCompItem(0,child);
|
||||
aUint:=Fetch(dtUInt32);
|
||||
rec.node.SetCompItem(1,aUint);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
function TsrTypeList.FetchRuntimeArray(child:PsrType;array_stride:DWORD):PsrType;
|
||||
var
|
||||
rec:record
|
||||
node:TsrType;
|
||||
align:Pointer;
|
||||
end;
|
||||
begin
|
||||
Assert(child<>nil);
|
||||
rec.node:=Default(TsrType);
|
||||
rec.node.dtype:=dtTypeRuntimeArray;
|
||||
rec.node.key.OpId:=Op.OpTypeRuntimeArray;
|
||||
rec.node.key.ext.array_stride:=array_stride;
|
||||
rec.node.key.count:=1;
|
||||
rec.node.SetCompItem(0,child);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
function TsrTypeList.FetchImage(child:PsrType;image_info:TsrTypeImageInfo):PsrType;
|
||||
var
|
||||
rec:record
|
||||
node:TsrType;
|
||||
align:Pointer;
|
||||
end;
|
||||
begin
|
||||
Assert(child<>nil);
|
||||
rec.node:=Default(TsrType);
|
||||
rec.node.dtype:=dtTypeImage;
|
||||
rec.node.key.OpId:=Op.OpTypeImage;
|
||||
rec.node.key.ext.image:=image_info;
|
||||
rec.node.key.count:=1;
|
||||
rec.node.SetCompItem(0,child);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
function TsrTypeList.FetchSampledImage(child:PsrType):PsrType;
|
||||
var
|
||||
rec:record
|
||||
node:TsrType;
|
||||
align:Pointer;
|
||||
end;
|
||||
begin
|
||||
Assert(child<>nil);
|
||||
rec.node:=Default(TsrType);
|
||||
rec.node.dtype:=dtTypeSampledImage;
|
||||
rec.node.key.OpId:=Op.OpTypeSampledImage;
|
||||
rec.node.key.count:=1;
|
||||
rec.node.SetCompItem(0,child);
|
||||
Result:=_Fetch(@rec.node);
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
function LazyType2(t1,t2:TsrDataType):TsrDataType;
|
||||
begin
|
||||
if (t1<>dtUnknow) then Result:=t1 else Result:=t2;
|
||||
end;
|
||||
|
||||
function LazyType3(t1,t2,t3:TsrDataType):TsrDataType;
|
||||
begin
|
||||
if (t1<>dtUnknow) then Result:=t1 else Result:=t2;
|
||||
if (Result=dtUnknow) then Result:=t3;
|
||||
end;
|
||||
|
||||
function isIntVector(rtype:TsrDataType):Boolean; inline;
|
||||
begin
|
||||
Case rtype of
|
||||
dtVec2u8,
|
||||
dtVec4u8,
|
||||
|
||||
dtVec2i8,
|
||||
dtVec4i8,
|
||||
|
||||
dtVec2u16,
|
||||
dtVec4u16,
|
||||
|
||||
dtVec2i16,
|
||||
dtVec4i16,
|
||||
|
||||
dtVec2u,
|
||||
dtVec3u,
|
||||
dtVec4u,
|
||||
|
||||
dtVec2i,
|
||||
dtVec3i,
|
||||
dtVec4i:Result:=True;
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function isIntScalar(rtype:TsrDataType):Boolean; inline;
|
||||
begin
|
||||
Case rtype of
|
||||
dtInt8,
|
||||
dtUint8,
|
||||
|
||||
dtInt16,
|
||||
dtUint16,
|
||||
|
||||
dtInt32 ,
|
||||
dtUint32,
|
||||
|
||||
dtInt64 ,
|
||||
dtUint64:Result:=True;
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetVecChild(rtype:TsrDataType):TsrDataType;
|
||||
begin
|
||||
Case rtype of
|
||||
dtVec2b,
|
||||
dtVec3b,
|
||||
dtVec4b:Result:=dtBool;
|
||||
|
||||
dtVec2u8,
|
||||
dtVec4u8:Result:=dtUint8;
|
||||
|
||||
dtVec2i8,
|
||||
dtVec4i8:Result:=dtInt8;
|
||||
|
||||
dtVec2u16,
|
||||
dtVec4u16:Result:=dtUint16;
|
||||
|
||||
dtVec2i16,
|
||||
dtVec4i16:Result:=dtInt16;
|
||||
|
||||
dtStruct2u,
|
||||
dtVec2u,
|
||||
dtVec3u,
|
||||
dtVec4u:Result:=dtUint32;
|
||||
|
||||
dtVec2i,
|
||||
dtVec3i,
|
||||
dtVec4i:Result:=dtInt32;
|
||||
|
||||
dtVec2f,
|
||||
dtVec3f,
|
||||
dtVec4f:Result:=dtFloat32;
|
||||
|
||||
dtVec2h,
|
||||
dtVec4h:Result:=dtHalf16;
|
||||
else
|
||||
Result:=dtUnknow;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetVecCount(rtype:TsrDataType):Byte;
|
||||
begin
|
||||
Case rtype of
|
||||
dtVec2b,
|
||||
dtVec2u8,
|
||||
dtVec2i8,
|
||||
dtVec2u16,
|
||||
dtVec2i16,
|
||||
dtVec2u,
|
||||
dtVec2i,
|
||||
dtVec2f,
|
||||
dtVec2h,
|
||||
dtStruct2u:Result:=2;
|
||||
|
||||
dtVec3b,
|
||||
dtVec3u,
|
||||
dtVec3i,
|
||||
dtVec3f:Result:=3;
|
||||
|
||||
dtVec4b,
|
||||
dtVec4u8,
|
||||
dtVec4i8,
|
||||
dtVec4u16,
|
||||
dtVec4i16,
|
||||
dtVec4u,
|
||||
dtVec4i,
|
||||
dtVec4f,
|
||||
dtVec4h:Result:=4;
|
||||
else
|
||||
Result:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function GetVecType(elem:TsrDataType;count:Byte):TsrDataType;
|
||||
begin
|
||||
Result:=dtUnknow;
|
||||
if (count<=1) then Exit(elem);
|
||||
Case elem of
|
||||
dtBool:
|
||||
Case count of
|
||||
2:Result:=dtVec2b;
|
||||
3:Result:=dtVec3b;
|
||||
4:Result:=dtVec4b;
|
||||
end;
|
||||
dtUint8:
|
||||
Case count of
|
||||
2:Result:=dtVec2u8;
|
||||
4:Result:=dtVec4u8;
|
||||
end;
|
||||
dtInt8:
|
||||
Case count of
|
||||
2:Result:=dtVec2i8;
|
||||
4:Result:=dtVec4i8;
|
||||
end;
|
||||
dtUint16:
|
||||
Case count of
|
||||
2:Result:=dtVec2u16;
|
||||
4:Result:=dtVec4u16;
|
||||
end;
|
||||
dtInt16:
|
||||
Case count of
|
||||
2:Result:=dtVec2i16;
|
||||
4:Result:=dtVec4i16;
|
||||
end;
|
||||
dtHalf16:
|
||||
Case count of
|
||||
2:Result:=dtVec2h;
|
||||
4:Result:=dtVec4h;
|
||||
end;
|
||||
dtFloat32:
|
||||
Case count of
|
||||
2:Result:=dtVec2f;
|
||||
3:Result:=dtVec3f;
|
||||
4:Result:=dtVec4f;
|
||||
end;
|
||||
dtInt32:
|
||||
Case count of
|
||||
2:Result:=dtVec2i;
|
||||
3:Result:=dtVec3i;
|
||||
4:Result:=dtVec4i;
|
||||
end;
|
||||
dtUint32:
|
||||
Case count of
|
||||
2:Result:=dtVec2u;
|
||||
3:Result:=dtVec3u;
|
||||
4:Result:=dtVec4u;
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
function isVector(rtype:TsrDataType):Boolean; inline;
|
||||
begin
|
||||
Result:=GetVecChild(rtype)<>dtUnknow;
|
||||
end;
|
||||
|
||||
function GetTypeHigh(rtype:TsrDataType):QWORD;
|
||||
var
|
||||
s:Byte;
|
||||
begin
|
||||
Result:=0;
|
||||
if (rtype=dtBool) then Exit(1);
|
||||
s:=BitSizeType(rtype);
|
||||
Case s of
|
||||
8:Result:=High(Byte);
|
||||
16:Result:=High(Word);
|
||||
32:Result:=High(DWord);
|
||||
64:Result:=High(QWord);
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
end;
|
||||
|
||||
function CompareType(rtype1,rtype2:TsrDataType):Boolean;
|
||||
begin
|
||||
Case rtype1 of
|
||||
dtInt8,
|
||||
dtUint8:Result:=(rtype2=dtInt8) or (rtype2=dtUint8);
|
||||
|
||||
dtInt16,
|
||||
dtUint16:Result:=(rtype2=dtInt16) or (rtype2=dtUint16);
|
||||
|
||||
dtInt32,
|
||||
dtUint32:Result:=(rtype2=dtInt32) or (rtype2=dtUint32);
|
||||
|
||||
dtVec2u8,
|
||||
dtVec2i8:Result:=(rtype2=dtVec2u8) or (rtype2=dtVec2i8);
|
||||
|
||||
dtVec4u8,
|
||||
dtVec4i8:Result:=(rtype2=dtVec4u8) or (rtype2=dtVec4i8);
|
||||
|
||||
dtVec2u16,
|
||||
dtVec2i16:Result:=(rtype2=dtVec2u16) or (rtype2=dtVec2i16);
|
||||
|
||||
dtVec4u16,
|
||||
dtVec4i16:Result:=(rtype2=dtVec4u16) or (rtype2=dtVec4i16);
|
||||
|
||||
dtVec2u,
|
||||
dtVec2i:Result:=(rtype2=dtVec2u) or (rtype2=dtVec2i);
|
||||
|
||||
dtVec3u,
|
||||
dtVec3i:Result:=(rtype2=dtVec3u) or (rtype2=dtVec3i);
|
||||
|
||||
dtVec4u,
|
||||
dtVec4i:Result:=(rtype2=dtVec4u) or (rtype2=dtVec4i);
|
||||
|
||||
else
|
||||
Result:=(rtype1=rtype2);
|
||||
end;
|
||||
end;
|
||||
|
||||
function SignType(rtype:TsrDataType):Byte;
|
||||
begin
|
||||
Result:=0;
|
||||
Case rtype of
|
||||
|
||||
dtInt8,
|
||||
dtInt16,
|
||||
dtInt32,
|
||||
dtInt64:Result:=1;
|
||||
|
||||
dtHalf16,
|
||||
dtFloat32,
|
||||
dtVec2h,
|
||||
dtVec4h,
|
||||
dtVec2f,
|
||||
dtVec3f,
|
||||
dtVec4f:Result:=1;
|
||||
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
function BitSizeType(rtype:TsrDataType):Byte;
|
||||
begin
|
||||
Result:=0;
|
||||
Case rtype of
|
||||
|
||||
dtInt8,
|
||||
dtUint8:Result:=8;
|
||||
|
||||
dtInt16,
|
||||
dtUint16,
|
||||
dtVec2u8,
|
||||
dtVec2i8,
|
||||
dtHalf16:Result:=16;
|
||||
|
||||
dtUnknow,
|
||||
dtBool, //for typecast
|
||||
dtFloat32,
|
||||
dtInt32,
|
||||
dtUint32,
|
||||
dtVec4u8,
|
||||
dtVec4i8,
|
||||
dtVec2u16,
|
||||
dtVec2i16,
|
||||
dtVec2h:Result:=32;
|
||||
|
||||
dtInt64,
|
||||
dtUint64,
|
||||
dtVec4u16,
|
||||
dtVec4i16,
|
||||
dtVec2f,
|
||||
dtVec4h,
|
||||
dtStruct2u:Result:=64;
|
||||
|
||||
dtVec3u,
|
||||
dtVec3f:Result:=96;
|
||||
dtVec4f:Result:=128;
|
||||
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TryBitcastType(rtype1,rtype2:TsrDataType):Boolean;
|
||||
var
|
||||
s,d:Byte;
|
||||
begin
|
||||
s:=BitSizeType(rtype1);
|
||||
d:=BitSizeType(rtype2);
|
||||
Result:=(s<>0) and (d<>0) and (s=d);
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
183
spirv/srUniform.pas
Normal file
183
spirv/srUniform.pas
Normal file
@ -0,0 +1,183 @@
|
||||
unit srUniform;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
spirv,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srLayout,
|
||||
srReg,
|
||||
srVariable,
|
||||
srDecorate;
|
||||
|
||||
type
|
||||
String2=String[2];
|
||||
|
||||
PsrUniform=^TsrUniform;
|
||||
TsrUniform=object(TsrDescriptor)
|
||||
pLeft,pRight:PsrUniform;
|
||||
//----
|
||||
|
||||
key:packed record
|
||||
pLayout:PsrDataLayout;
|
||||
pType:PsrType;
|
||||
end;
|
||||
|
||||
pReg:PsrRegNode;
|
||||
|
||||
function c(n1,n2:PsrUniform):Integer; static;
|
||||
function GetTypeChar:String2;
|
||||
function GetString:RawByteString;
|
||||
end;
|
||||
|
||||
TsrUniformList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrUniform,TsrUniform>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
FNTree:TNodeFetch;
|
||||
procedure Init(cb:TfnAlloc);
|
||||
function Fetch(s:PsrDataLayout;t:PsrType):PsrUniform;
|
||||
Function First:PsrUniform;
|
||||
Function Next(node:PsrUniform):PsrUniform;
|
||||
procedure AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList);
|
||||
procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TsrUniform.c(n1,n2:PsrUniform):Integer;
|
||||
begin
|
||||
//first pLayout
|
||||
Result:=Integer(n1^.key.pLayout>n2^.key.pLayout)-Integer(n1^.key.pLayout<n2^.key.pLayout);
|
||||
if (Result<>0) then Exit;
|
||||
//second pType
|
||||
Result:=Integer(n1^.key.pType>n2^.key.pType)-Integer(n1^.key.pType<n2^.key.pType);
|
||||
end;
|
||||
|
||||
function TsrUniform.GetTypeChar:String2;
|
||||
begin
|
||||
Result:='';
|
||||
if (key.pType<>nil) then
|
||||
With key.pType^.key do
|
||||
Case key.pType^.dtype of
|
||||
dtTypeImage:
|
||||
begin
|
||||
if (ext.image.Dim=Dim.Buffer) then
|
||||
begin
|
||||
Case ext.image.Sampled of
|
||||
1:Result:='UB'; //VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
|
||||
2:Result:='SB'; //VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
|
||||
else Result:='RB'; //runtime texel buffer
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
Case ext.image.Sampled of
|
||||
1:Result:='UI'; //VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
|
||||
2:Result:='SI'; //VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
|
||||
else Result:='RI'; //runtime image
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
dtTypeSampler:Result:='US'; //VK_DESCRIPTOR_TYPE_SAMPLER
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrUniform.GetString:RawByteString;
|
||||
var
|
||||
PID:DWORD;
|
||||
begin
|
||||
PID:=0;
|
||||
if (key.pLayout<>nil) then
|
||||
begin
|
||||
PID:=key.pLayout^.FID;
|
||||
end;
|
||||
Result:=GetTypeChar+
|
||||
';PID='+HexStr(PID,8)+
|
||||
';BND='+HexStr(FBinding,8);
|
||||
end;
|
||||
|
||||
procedure TsrUniformList.Init(cb:TfnAlloc);
|
||||
begin
|
||||
Alloc:=cb;
|
||||
end;
|
||||
|
||||
function TsrUniformList.Fetch(s:PsrDataLayout;t:PsrType):PsrUniform;
|
||||
var
|
||||
node:TsrUniform;
|
||||
begin
|
||||
node:=Default(TsrUniform);
|
||||
node.key.pLayout:=s;
|
||||
node.key.pType:=t;
|
||||
node.FStorage:=StorageClass.UniformConstant;
|
||||
node.FBinding:=-1;
|
||||
Result:=FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrUniform));
|
||||
Move(node,Result^,SizeOf(TsrUniform));
|
||||
FNTree.Insert(Result);
|
||||
end else
|
||||
begin
|
||||
t^.mark_unread;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrUniformList.First:PsrUniform;
|
||||
begin
|
||||
Result:=FNTree.Min;
|
||||
end;
|
||||
|
||||
Function TsrUniformList.Next(node:PsrUniform):PsrUniform;
|
||||
begin
|
||||
Result:=FNTree.Next(node);
|
||||
end;
|
||||
|
||||
procedure TsrUniformList.AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList);
|
||||
var
|
||||
node:PsrUniform;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (Decorates=nil) then Exit;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
begin
|
||||
if (node^.FBinding=-1) then //alloc
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Binding,FBinding);
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.DescriptorSet,Decorates^.FDescriptorSet);
|
||||
node^.FBinding:=FBinding;
|
||||
Inc(FBinding);
|
||||
end;
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrUniformList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
var
|
||||
node:PsrUniform;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (FDebugInfo=nil) then Exit;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
begin
|
||||
FDebugInfo^.emit_source_extension(node^.GetString);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
447
spirv/srVBufInfo.pas
Normal file
447
spirv/srVBufInfo.pas
Normal file
@ -0,0 +1,447 @@
|
||||
unit srVBufInfo;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srLayout,
|
||||
spirv;
|
||||
|
||||
type
|
||||
//Destination channel select:
|
||||
//0=0, 1=1, 4=R, 5=G, 6=B, 7=A
|
||||
Tdst_sel=array[0..3] of Byte;
|
||||
|
||||
TBuf_info=packed object
|
||||
grp:PsrDataLayout;
|
||||
dsel:Tdst_sel;
|
||||
DFMT:Byte; //BUF_DATA_FORMAT_*
|
||||
NFMT:Byte; //BUF_NUM_FORMAT_*
|
||||
count:Byte; //count reg dst
|
||||
function GetResultType:TsrDataType;
|
||||
function GetElemType:TsrDataType;
|
||||
function GetElemCount:Byte; inline;
|
||||
function GetElemSize:Byte; inline;
|
||||
function GetSizeFormat:Byte; inline;
|
||||
function GetAlignSize:Byte; inline;
|
||||
function IsComp:Boolean;
|
||||
function IsExtFormat:Boolean;
|
||||
function GetImageFormat:Byte;
|
||||
function GetImageFormatElement:Byte;
|
||||
function GetImageInfo:TsrImageInfo;
|
||||
function GetImageInfoElement:TsrImageInfo;
|
||||
end;
|
||||
|
||||
const
|
||||
dst_sel_identity:Tdst_sel=(4,5,6,7);
|
||||
|
||||
function Buf_info(grp:PsrDataLayout;dsel:Tdst_sel;DFMT,NFMT,count:Byte):TBuf_info; inline;
|
||||
function dst_sel(r,g,b,a:Byte):Tdst_sel; inline;
|
||||
function get_reverse_dst_sel(dst:Tdst_sel):Tdst_sel;
|
||||
function GetElemCount(DFMT:Byte):Byte; inline;
|
||||
|
||||
implementation
|
||||
|
||||
const
|
||||
DFMT_ELEM_COUNT:array[0..15] of Byte=(
|
||||
0, //BUF_DATA_FORMAT_INVALID
|
||||
1, //BUF_DATA_FORMAT_8
|
||||
1, //BUF_DATA_FORMAT_16
|
||||
2, //BUF_DATA_FORMAT_8_8
|
||||
1, //BUF_DATA_FORMAT_32
|
||||
2, //BUF_DATA_FORMAT_16_16
|
||||
3, //BUF_DATA_FORMAT_10_11_11
|
||||
3, //BUF_DATA_FORMAT_11_11_10
|
||||
4, //BUF_DATA_FORMAT_10_10_10_2
|
||||
4, //BUF_DATA_FORMAT_2_10_10_10
|
||||
4, //BUF_DATA_FORMAT_8_8_8_8
|
||||
2, //BUF_DATA_FORMAT_32_32
|
||||
4, //BUF_DATA_FORMAT_16_16_16_16
|
||||
3, //BUF_DATA_FORMAT_32_32_32
|
||||
4, //BUF_DATA_FORMAT_32_32_32_32
|
||||
0); //BUF_DATA_FORMAT_RESERVED
|
||||
|
||||
DFMT_ELEM_SIZE:array[0..15] of Byte=(
|
||||
0, //BUF_DATA_FORMAT_INVALID
|
||||
1, //BUF_DATA_FORMAT_8
|
||||
2, //BUF_DATA_FORMAT_16
|
||||
1, //BUF_DATA_FORMAT_8_8
|
||||
4, //BUF_DATA_FORMAT_32
|
||||
2, //BUF_DATA_FORMAT_16_16
|
||||
4, //BUF_DATA_FORMAT_10_11_11
|
||||
4, //BUF_DATA_FORMAT_11_11_10
|
||||
4, //BUF_DATA_FORMAT_10_10_10_2
|
||||
4, //BUF_DATA_FORMAT_2_10_10_10
|
||||
1, //BUF_DATA_FORMAT_8_8_8_8
|
||||
4, //BUF_DATA_FORMAT_32_32
|
||||
2, //BUF_DATA_FORMAT_16_16_16_16
|
||||
4, //BUF_DATA_FORMAT_32_32_32
|
||||
4, //BUF_DATA_FORMAT_32_32_32_32
|
||||
0); //BUF_DATA_FORMAT_RESERVED
|
||||
|
||||
DFMT_SIZE:array[0..15] of Byte=(
|
||||
0, //BUF_DATA_FORMAT_INVALID
|
||||
1, //BUF_DATA_FORMAT_8 //shr 2
|
||||
2, //BUF_DATA_FORMAT_16 //shr 2
|
||||
2, //BUF_DATA_FORMAT_8_8 //shr 2
|
||||
4, //BUF_DATA_FORMAT_32 //shr 2
|
||||
4, //BUF_DATA_FORMAT_16_16 //shr 2
|
||||
4, //BUF_DATA_FORMAT_10_11_11 //shr 2
|
||||
4, //BUF_DATA_FORMAT_11_11_10 //shr 2
|
||||
4, //BUF_DATA_FORMAT_10_10_10_2 //shr 2
|
||||
4, //BUF_DATA_FORMAT_2_10_10_10 //shr 2
|
||||
4, //BUF_DATA_FORMAT_8_8_8_8 //shr 2
|
||||
8, //BUF_DATA_FORMAT_32_32 //shr 3
|
||||
8, //BUF_DATA_FORMAT_16_16_16_16 //shr 3
|
||||
12, //BUF_DATA_FORMAT_32_32_32 //div 12
|
||||
16, //BUF_DATA_FORMAT_32_32_32_32 //shr 4
|
||||
0); //BUF_DATA_FORMAT_RESERVED
|
||||
|
||||
function Buf_info(grp:PsrDataLayout;dsel:Tdst_sel;DFMT,NFMT,count:Byte):TBuf_info; inline;
|
||||
begin
|
||||
Result.grp :=grp;
|
||||
Result.dsel :=dsel;
|
||||
Result.DFMT :=DFMT;
|
||||
Result.NFMT :=NFMT;
|
||||
Result.count:=count;
|
||||
end;
|
||||
|
||||
function dst_sel(r,g,b,a:Byte):Tdst_sel; inline;
|
||||
begin
|
||||
Result[0]:=r;
|
||||
Result[1]:=g;
|
||||
Result[2]:=b;
|
||||
Result[3]:=a;
|
||||
end;
|
||||
|
||||
function get_reverse_dst_sel(dst:Tdst_sel):Tdst_sel;
|
||||
var
|
||||
i,f,d:Byte;
|
||||
begin
|
||||
Result:=Default(Tdst_sel);
|
||||
For i:=0 to 3 do
|
||||
For f:=0 to 3 do
|
||||
begin
|
||||
d:=dst[f];
|
||||
Case d of
|
||||
4..7:
|
||||
begin
|
||||
d:=d-4;
|
||||
if (i=d) then
|
||||
begin
|
||||
Result[i]:=f+4;
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBuf_info.GetResultType:TsrDataType;
|
||||
begin
|
||||
Result:=dtFloat32;
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UINT:Result:=dtUint32;
|
||||
BUF_NUM_FORMAT_SINT:Result:=dtInt32;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBuf_info.GetElemType:TsrDataType;
|
||||
begin
|
||||
Result:=dtUnknow;
|
||||
Case DFMT_ELEM_SIZE[DFMT] of
|
||||
1:Case NFMT of
|
||||
BUF_NUM_FORMAT_SNORM ,
|
||||
BUF_NUM_FORMAT_SSCALED ,
|
||||
BUF_NUM_FORMAT_SINT ,
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=dtInt8;
|
||||
else Result:=dtUint8;
|
||||
end;
|
||||
2:Case NFMT of
|
||||
BUF_NUM_FORMAT_SNORM ,
|
||||
BUF_NUM_FORMAT_SSCALED ,
|
||||
BUF_NUM_FORMAT_SINT ,
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=dtInt16;
|
||||
BUF_NUM_FORMAT_FLOAT :Result:=dtHalf16;
|
||||
else Result:=dtUint16;
|
||||
end;
|
||||
4:Case NFMT of
|
||||
BUF_NUM_FORMAT_SNORM ,
|
||||
BUF_NUM_FORMAT_SSCALED ,
|
||||
BUF_NUM_FORMAT_SINT ,
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=dtInt32;
|
||||
BUF_NUM_FORMAT_FLOAT :Result:=dtFloat32;
|
||||
else Result:=dtUint32;
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetElemCount(DFMT:Byte):Byte; inline;
|
||||
begin
|
||||
Result:=DFMT_ELEM_COUNT[DFMT];
|
||||
end;
|
||||
|
||||
function TBuf_info.GetElemCount:Byte; inline;
|
||||
begin
|
||||
Result:=DFMT_ELEM_COUNT[DFMT];
|
||||
end;
|
||||
|
||||
function TBuf_info.GetElemSize:Byte; inline;
|
||||
begin
|
||||
Result:=DFMT_ELEM_SIZE[DFMT];
|
||||
end;
|
||||
|
||||
function TBuf_info.GetSizeFormat:Byte; inline;
|
||||
begin
|
||||
Result:=DFMT_SIZE[DFMT];
|
||||
end;
|
||||
|
||||
function Min(a,b:PtrInt):PtrInt; inline;
|
||||
begin
|
||||
if (a<b) then Result:=a else Result:=b;
|
||||
end;
|
||||
|
||||
function TBuf_info.GetAlignSize:Byte; inline;
|
||||
begin
|
||||
Result:=Min(4,GetSizeFormat);
|
||||
end;
|
||||
|
||||
function TBuf_info.IsComp:Boolean;
|
||||
begin
|
||||
Case DFMT of
|
||||
BUF_DATA_FORMAT_8 ,
|
||||
BUF_DATA_FORMAT_16 ,
|
||||
BUF_DATA_FORMAT_8_8 ,
|
||||
BUF_DATA_FORMAT_16_16 ,
|
||||
BUF_DATA_FORMAT_10_11_11 ,
|
||||
BUF_DATA_FORMAT_11_11_10 ,
|
||||
BUF_DATA_FORMAT_10_10_10_2 ,
|
||||
BUF_DATA_FORMAT_2_10_10_10 ,
|
||||
BUF_DATA_FORMAT_8_8_8_8 ,
|
||||
BUF_DATA_FORMAT_16_16_16_16:Result:=True;
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBuf_info.IsExtFormat:Boolean;
|
||||
begin
|
||||
Case DFMT of
|
||||
BUF_DATA_FORMAT_10_11_11 ,
|
||||
BUF_DATA_FORMAT_11_11_10 ,
|
||||
BUF_DATA_FORMAT_10_10_10_2 ,
|
||||
BUF_DATA_FORMAT_2_10_10_10 :Result:=True;
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TBuf_info.GetImageFormat:Byte;
|
||||
begin
|
||||
Result:=ImageFormat.Unknown;
|
||||
Case DFMT of
|
||||
BUF_DATA_FORMAT_8 : //R8 R8Snorm R8ui R8i
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.R8;
|
||||
BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.R8Snorm;
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.R8ui;
|
||||
BUF_NUM_FORMAT_SINT :Result:=ImageFormat.R8i;
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.R8i;
|
||||
else;
|
||||
end;
|
||||
BUF_DATA_FORMAT_16 : //R16 R16Snorm R16ui R16i R16f
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.R16;
|
||||
BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.R16Snorm;
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.R16ui;
|
||||
BUF_NUM_FORMAT_SINT :Result:=ImageFormat.R16i;
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.R16i;
|
||||
BUF_NUM_FORMAT_USCALED ,
|
||||
BUF_NUM_FORMAT_SSCALED ,
|
||||
BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.R16f;
|
||||
end;
|
||||
BUF_DATA_FORMAT_8_8 : //Rg8 Rg8Snorm Rg8ui Rg8i
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.Rg8;
|
||||
BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.Rg8Snorm;
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rg8ui;
|
||||
BUF_NUM_FORMAT_SINT :Result:=ImageFormat.Rg8i;
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.Rg8i;
|
||||
else;
|
||||
end;
|
||||
BUF_DATA_FORMAT_32 : //R32ui R32i R32f
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.R32ui;
|
||||
BUF_NUM_FORMAT_SINT :Result:=ImageFormat.R32i;
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.R32i;
|
||||
BUF_NUM_FORMAT_USCALED ,
|
||||
BUF_NUM_FORMAT_SSCALED ,
|
||||
BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.R32f;
|
||||
else;
|
||||
end;
|
||||
BUF_DATA_FORMAT_16_16 : //Rg16 Rg16Snorm Rg16ui Rg16i Rg16f
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.Rg16;
|
||||
BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.Rg16Snorm;
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rg16ui;
|
||||
BUF_NUM_FORMAT_SINT :Result:=ImageFormat.Rg16i;
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.Rg16i;
|
||||
BUF_NUM_FORMAT_USCALED ,
|
||||
BUF_NUM_FORMAT_SSCALED ,
|
||||
BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.Rg16f;
|
||||
end;
|
||||
BUF_DATA_FORMAT_10_11_11 ,
|
||||
BUF_DATA_FORMAT_11_11_10 : //R11fG11fB10f
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.R11fG11fB10f;
|
||||
else;
|
||||
end;
|
||||
BUF_DATA_FORMAT_10_10_10_2 ,
|
||||
BUF_DATA_FORMAT_2_10_10_10 : //Rgb10A2 Rgb10a2ui
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.Rgb10A2;
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rgb10a2ui;
|
||||
else;
|
||||
end;
|
||||
BUF_DATA_FORMAT_8_8_8_8 : //Rgba8 Rgba8Snorm Rgba8ui Rgba8i
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.Rgba8;
|
||||
BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.Rgba8Snorm;
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rgba8ui;
|
||||
BUF_NUM_FORMAT_SINT :Result:=ImageFormat.Rgba8i;
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.Rgba8i;
|
||||
else;
|
||||
end;
|
||||
BUF_DATA_FORMAT_32_32 : //Rg32ui Rg32i Rg32f
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rg32ui;
|
||||
BUF_NUM_FORMAT_SINT :Result:=ImageFormat.Rg32i;
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.Rg32i;
|
||||
BUF_NUM_FORMAT_USCALED ,
|
||||
BUF_NUM_FORMAT_SSCALED ,
|
||||
BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.Rg32f;
|
||||
else;
|
||||
end;
|
||||
BUF_DATA_FORMAT_16_16_16_16: //Rgba16 Rgba16Snorm Rgba16ui Rgba16i Rgba16f
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.Rgba16;
|
||||
BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.Rgba16Snorm;
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rgba16ui;
|
||||
BUF_NUM_FORMAT_SINT :Result:=ImageFormat.Rgba16i;
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.Rgba16i;
|
||||
BUF_NUM_FORMAT_USCALED ,
|
||||
BUF_NUM_FORMAT_SSCALED ,
|
||||
BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.Rgba16f;
|
||||
end;
|
||||
BUF_DATA_FORMAT_32_32_32 ,
|
||||
BUF_DATA_FORMAT_32_32_32_32: //Rgba32ui Rgba32i Rgba32f
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rgba32ui;
|
||||
BUF_NUM_FORMAT_SINT :Result:=ImageFormat.Rgba32i;
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.Rgba32i;
|
||||
BUF_NUM_FORMAT_USCALED ,
|
||||
BUF_NUM_FORMAT_SSCALED ,
|
||||
BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.Rgba32f;
|
||||
else;
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TBuf_info.GetImageFormatElement:Byte;
|
||||
begin
|
||||
Result:=ImageFormat.Unknown;
|
||||
Case DFMT of
|
||||
BUF_DATA_FORMAT_8 ,
|
||||
BUF_DATA_FORMAT_8_8 ,
|
||||
BUF_DATA_FORMAT_8_8_8_8 : //R8 R8Snorm R8ui R8i
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.R8;
|
||||
BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.R8Snorm;
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.R8ui;
|
||||
BUF_NUM_FORMAT_SINT :Result:=ImageFormat.R8i;
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.R8i;
|
||||
else;
|
||||
end;
|
||||
BUF_DATA_FORMAT_16 ,
|
||||
BUF_DATA_FORMAT_16_16 ,
|
||||
BUF_DATA_FORMAT_16_16_16_16: //R16 R16Snorm R16ui R16i R16f
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.R16;
|
||||
BUF_NUM_FORMAT_SNORM :Result:=ImageFormat.R16Snorm;
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.R16ui;
|
||||
BUF_NUM_FORMAT_SINT :Result:=ImageFormat.R16i;
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.R16i;
|
||||
BUF_NUM_FORMAT_USCALED ,
|
||||
BUF_NUM_FORMAT_SSCALED ,
|
||||
BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.R16f;
|
||||
end;
|
||||
BUF_DATA_FORMAT_32 , //R32ui R32i R32f
|
||||
BUF_DATA_FORMAT_32_32 ,
|
||||
BUF_DATA_FORMAT_32_32_32 ,
|
||||
BUF_DATA_FORMAT_32_32_32_32:
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.R32ui;
|
||||
BUF_NUM_FORMAT_SINT :Result:=ImageFormat.R32i;
|
||||
BUF_NUM_FORMAT_SNORM_NZ:Result:=ImageFormat.R32i;
|
||||
BUF_NUM_FORMAT_USCALED ,
|
||||
BUF_NUM_FORMAT_SSCALED ,
|
||||
BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.R32f;
|
||||
else;
|
||||
end;
|
||||
BUF_DATA_FORMAT_10_11_11 ,
|
||||
BUF_DATA_FORMAT_11_11_10 : //R11fG11fB10f
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_FLOAT :Result:=ImageFormat.R11fG11fB10f;
|
||||
else;
|
||||
end;
|
||||
BUF_DATA_FORMAT_10_10_10_2 ,
|
||||
BUF_DATA_FORMAT_2_10_10_10 : //Rgb10A2 Rgb10a2ui
|
||||
Case NFMT of
|
||||
BUF_NUM_FORMAT_UNORM :Result:=ImageFormat.Rgb10A2;
|
||||
BUF_NUM_FORMAT_UINT :Result:=ImageFormat.Rgb10a2ui;
|
||||
else;
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TBuf_info.GetImageInfo:TsrImageInfo;
|
||||
begin
|
||||
Result:=Default(TsrImageInfo);
|
||||
Result.dtype:=GetResultType;
|
||||
|
||||
Result.tinfo.Dim :=Dim.Buffer;
|
||||
Result.tinfo.Depth :=2;
|
||||
Result.tinfo.Arrayed:=0;
|
||||
Result.tinfo.MS :=0;
|
||||
Result.tinfo.Sampled:=2;
|
||||
Result.tinfo.Format :=GetImageFormat;
|
||||
end;
|
||||
|
||||
function TBuf_info.GetImageInfoElement:TsrImageInfo;
|
||||
begin
|
||||
Result:=Default(TsrImageInfo);
|
||||
Result.dtype:=GetResultType;
|
||||
|
||||
Result.tinfo.Dim :=Dim.Buffer;
|
||||
Result.tinfo.Depth :=2;
|
||||
Result.tinfo.Arrayed:=0;
|
||||
Result.tinfo.MS :=0;
|
||||
Result.tinfo.Sampled:=2;
|
||||
Result.tinfo.Format :=GetImageFormatElement;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
118
spirv/srVariable.pas
Normal file
118
spirv/srVariable.pas
Normal file
@ -0,0 +1,118 @@
|
||||
unit srVariable;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
spirv,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srRefId;
|
||||
|
||||
type
|
||||
PsrVariable=^TsrVariable;
|
||||
|
||||
TsrVariable=object
|
||||
pPrev,pNext:PsrVariable;
|
||||
//----
|
||||
read_count:DWORD;
|
||||
write_count:DWORD;
|
||||
ID:TsrRefId; //post id
|
||||
pType:PsrType;
|
||||
dtype:TsrDataType;
|
||||
pSource:TOpParamSingle; //ntInput,ntVertLayout,ntFragLayout,ntOutput,ntUniform,ntBuffer
|
||||
Procedure mark_read;
|
||||
Procedure mark_unread;
|
||||
Procedure mark_write;
|
||||
Function GetStorageClass:DWORD;
|
||||
Procedure Clear;
|
||||
function GetName:RawByteString;
|
||||
end;
|
||||
|
||||
TsrVariableList=specialize TNodeList<PsrVariable>;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
srLayout,
|
||||
srVertLayout,
|
||||
srFragLayout,
|
||||
srInput,
|
||||
srOutput;
|
||||
|
||||
Procedure TsrVariable.mark_read;
|
||||
begin
|
||||
Inc(read_count);
|
||||
end;
|
||||
|
||||
Procedure TsrVariable.mark_unread;
|
||||
begin
|
||||
if (read_count<>0) then Dec(read_count);
|
||||
end;
|
||||
|
||||
Procedure TsrVariable.mark_write;
|
||||
begin
|
||||
Inc(write_count);
|
||||
end;
|
||||
|
||||
Function TsrVariable.GetStorageClass:DWORD;
|
||||
begin
|
||||
Result:=StorageClass.Private_;
|
||||
if (pSource.pData<>nil) then
|
||||
Case pSource.ntype of
|
||||
ntInput,
|
||||
ntVertLayout,
|
||||
ntFragLayout,
|
||||
ntOutput ,
|
||||
ntUniform ,
|
||||
ntBuffer :Result:=PsrDescriptor(pSource.pData)^.FStorage;
|
||||
else
|
||||
Assert(false,'GetStorageClass');
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrVariable.Clear;
|
||||
begin
|
||||
if (pType<>nil) then
|
||||
begin
|
||||
pType^.mark_unread;
|
||||
pType:=nil;
|
||||
end;
|
||||
if (pSource.pData<>nil) then
|
||||
begin
|
||||
Case pSource.ntype of
|
||||
ntInput ,
|
||||
ntVertLayout,
|
||||
ntFragLayout,
|
||||
ntOutput ,
|
||||
ntUniform ,
|
||||
ntBuffer :PsrDescriptor(pSource.pData)^.pVar:=nil;
|
||||
else
|
||||
Assert(false,'Clear');
|
||||
end;
|
||||
pSource.pData:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrVariable.GetName:RawByteString;
|
||||
begin
|
||||
Result:='';
|
||||
if (pSource.pData<>nil) then
|
||||
begin
|
||||
Case pSource.ntype of
|
||||
ntInput :
|
||||
Result:=PsrInput(pSource.pData)^.GetName;
|
||||
ntVertLayout:
|
||||
Result:=PsrVertLayout(pSource.pData)^.GetName;
|
||||
ntFragLayout:
|
||||
Result:=PsrFragLayout(pSource.pData)^.GetName;
|
||||
ntOutput:
|
||||
Result:=PsrOutput(pSource.pData)^.GetName;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
164
spirv/srVertLayout.pas
Normal file
164
spirv/srVertLayout.pas
Normal file
@ -0,0 +1,164 @@
|
||||
unit srVertLayout;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
srNodes,
|
||||
srReg,
|
||||
srOp,
|
||||
srVariable,
|
||||
srLayout,
|
||||
srDecorate;
|
||||
|
||||
type
|
||||
PsrVertLayout=^TsrVertLayout;
|
||||
TsrVertLayout=object(TsrDescriptor)
|
||||
pLeft,pRight:PsrVertLayout;
|
||||
//----
|
||||
pLayout:PsrDataLayout;
|
||||
pReg:PsrRegNode;
|
||||
function c(n1,n2:PsrVertLayout):Integer; static;
|
||||
function GetString:RawByteString;
|
||||
function GetName:RawByteString;
|
||||
end;
|
||||
|
||||
TsrVertLayoutList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrVertLayout,TsrVertLayout>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
FNTree:TNodeFetch;
|
||||
procedure Init(cb:TfnAlloc);
|
||||
function Fetch(p:PsrDataLayout):PsrVertLayout;
|
||||
Function First:PsrVertLayout;
|
||||
Function Next(node:PsrVertLayout):PsrVertLayout;
|
||||
procedure AllocBinding(Decorates:PsrDecorateList);
|
||||
procedure AllocEntryPoint(EntryPoint:PSpirvOp);
|
||||
procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TsrVertLayout.c(n1,n2:PsrVertLayout):Integer;
|
||||
begin
|
||||
Result:=Integer(n1^.pLayout>n2^.pLayout)-Integer(n1^.pLayout<n2^.pLayout);
|
||||
//Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrVertLayout.key));
|
||||
end;
|
||||
|
||||
function TsrVertLayout.GetString:RawByteString;
|
||||
var
|
||||
PID:DWORD;
|
||||
begin
|
||||
PID:=0;
|
||||
if (pLayout<>nil) then
|
||||
begin
|
||||
PID:=pLayout^.FID;
|
||||
end;
|
||||
Result:='VA;PID='+HexStr(PID,8)+
|
||||
';BND='+HexStr(FBinding,8);
|
||||
end;
|
||||
|
||||
function TsrVertLayout.GetName:RawByteString;
|
||||
begin
|
||||
Result:='atParam'+IntToStr(FBinding);
|
||||
end;
|
||||
|
||||
procedure TsrVertLayoutList.Init(cb:TfnAlloc);
|
||||
begin
|
||||
Alloc:=cb;
|
||||
end;
|
||||
|
||||
function TsrVertLayoutList.Fetch(p:PsrDataLayout):PsrVertLayout;
|
||||
var
|
||||
node:TsrVertLayout;
|
||||
begin
|
||||
node:=Default(TsrVertLayout);
|
||||
node.pLayout:=p;
|
||||
Result:=FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrVertLayout));
|
||||
Result^.pLayout:=p;
|
||||
Result^.FStorage:=StorageClass.Input;
|
||||
Result^.FBinding:=-1;
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrVertLayoutList.First:PsrVertLayout;
|
||||
begin
|
||||
Result:=FNTree.Min;
|
||||
end;
|
||||
|
||||
Function TsrVertLayoutList.Next(node:PsrVertLayout):PsrVertLayout;
|
||||
begin
|
||||
Result:=FNTree.Next(node);
|
||||
end;
|
||||
|
||||
procedure TsrVertLayoutList.AllocBinding(Decorates:PsrDecorateList);
|
||||
var
|
||||
node:PsrVertLayout;
|
||||
pVar:PsrVariable;
|
||||
FBinding:Integer;
|
||||
begin
|
||||
if (Decorates=nil) then Exit;
|
||||
FBinding:=0;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
begin
|
||||
if (node^.FBinding=-1) then //alloc
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,FBinding);
|
||||
node^.FBinding:=FBinding;
|
||||
Inc(FBinding);
|
||||
end;
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrVertLayoutList.AllocEntryPoint(EntryPoint:PSpirvOp);
|
||||
var
|
||||
node:PsrVertLayout;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (EntryPoint=nil) then Exit;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
begin
|
||||
EntryPoint^.AddParam(ntVar,pVar);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrVertLayoutList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
var
|
||||
node:PsrVertLayout;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (FDebugInfo=nil) then Exit;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
begin
|
||||
FDebugInfo^.emit_source_extension(node^.GetString);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
468
spirv/srVolatile.pas
Normal file
468
spirv/srVolatile.pas
Normal file
@ -0,0 +1,468 @@
|
||||
unit srVolatile;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
spirv,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
srVariable,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
SprvEmit;
|
||||
|
||||
type
|
||||
PsrVolatile=^TsrVolatile;
|
||||
TsrVolatile=object
|
||||
pNext:PsrVolatile;
|
||||
pReg:PsrRegNode;
|
||||
pPar:PsrOpBlock;
|
||||
FID:SizeUint;
|
||||
end;
|
||||
|
||||
PsrVolatiles=^TsrVolatiles;
|
||||
_TsrVolatiles=specialize TNodeStack<PsrVolatile>;
|
||||
TsrVolatiles=object(_TsrVolatiles)
|
||||
function pop_reg:PsrRegNode;
|
||||
function find_reg(pReg:PsrRegNode):PsrVolatile;
|
||||
end;
|
||||
|
||||
TEmitVolatile=object(TSprvEmit)
|
||||
procedure NextVolatileID;
|
||||
function AllocVolatile:PsrVolatile;
|
||||
function NewVolatile(pReg:PsrRegNode):PsrVolatile;
|
||||
procedure build_slot_dis(pSlot:PsrRegSlot;var old:PsrRegNode);
|
||||
procedure build_slot_cur(pSlot:PsrRegSlot;var old:PsrRegNode);
|
||||
procedure build_slot_old(pSlot:PsrRegSlot;var old:PsrRegNode);
|
||||
procedure build_volatile_dis(old:PsrRegsSnapshot);
|
||||
procedure build_volatile_cur(old:PsrRegsSnapshot);
|
||||
procedure build_volatile_old(old:PsrRegsSnapshot);
|
||||
procedure make_copy_slot(pSlot:PsrRegSlot);
|
||||
procedure make_copy_all;
|
||||
procedure PrepVolatile(dst:PspirvOp;src:PsrRegNode);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
emit_post;
|
||||
|
||||
function CompareReg(r1,r2:PsrRegNode):Boolean;
|
||||
begin
|
||||
r1:=RegDown(r1);
|
||||
r2:=RegDown(r2);
|
||||
Result:=(r1=r2);
|
||||
if not Result then
|
||||
begin
|
||||
Result:=CompareConst(r1^.AsConst,r2^.AsConst);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrVolatiles.pop_reg:PsrRegNode;
|
||||
var
|
||||
node:PsrVolatile;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=Pop_head;
|
||||
if (node=nil) then Exit;
|
||||
Result:=node^.pReg;
|
||||
end;
|
||||
|
||||
function TsrVolatiles.find_reg(pReg:PsrRegNode):PsrVolatile;
|
||||
var
|
||||
node:PsrVolatile;
|
||||
begin
|
||||
Result:=nil;
|
||||
//pReg:=RegDownSlot(pReg);
|
||||
node:=pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (pReg={RegDownSlot}(node^.pReg)) then Exit(node);
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmitVolatile.NextVolatileID;
|
||||
begin
|
||||
Inc(FVolatileID);
|
||||
end;
|
||||
|
||||
function TEmitVolatile.AllocVolatile:PsrVolatile;
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrVolatile));
|
||||
end;
|
||||
|
||||
function TEmitVolatile.NewVolatile(pReg:PsrRegNode):PsrVolatile;
|
||||
begin
|
||||
Result:=AllocVolatile;
|
||||
Result^.pReg:=pReg;
|
||||
Result^.pPar:=FMain^.pBlock;
|
||||
Result^.FID :=FVolatileID;
|
||||
pReg^.mark_read;
|
||||
end;
|
||||
|
||||
procedure TEmitVolatile.build_slot_dis(pSlot:PsrRegSlot;var old:PsrRegNode);
|
||||
var
|
||||
cur:PsrRegNode;
|
||||
begin
|
||||
cur:=pSlot^.current;
|
||||
While (cur<>old) do
|
||||
begin
|
||||
pSlot^.Remove(cur);
|
||||
cur:=pSlot^.current;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmitVolatile.build_slot_cur(pSlot:PsrRegSlot;var old:PsrRegNode);
|
||||
var
|
||||
cur,prv,new:PsrRegNode;
|
||||
st_cur:TsrVolatiles;
|
||||
rtype:TsrDataType;
|
||||
begin
|
||||
cur:=RegDownSlot(pSlot^.current);
|
||||
prv:=RegDownSlot(old);
|
||||
if CompareReg(cur,prv) then Exit;
|
||||
|
||||
cur:=pSlot^.current;
|
||||
|
||||
if (cur<>nil) then
|
||||
begin
|
||||
rtype:=cur^.dtype;
|
||||
end else
|
||||
begin
|
||||
rtype:=old^.dtype;
|
||||
end;
|
||||
|
||||
if (cur=nil) then
|
||||
begin
|
||||
Assert(false,'WTF');
|
||||
//cur:=pSlot^.New(rtype); //Unresolve
|
||||
end;
|
||||
if (old=nil) then
|
||||
begin
|
||||
//old:=pSlot^.New(rtype); //Unresolve
|
||||
end;
|
||||
|
||||
st_cur:=Default(TsrVolatiles);
|
||||
|
||||
if (old<>nil) then
|
||||
begin
|
||||
st_cur.Push_head(NewVolatile(old));
|
||||
end;
|
||||
|
||||
st_cur.Push_head(NewVolatile(cur));
|
||||
|
||||
new:=pSlot^.New(cur^.pLine,rtype);
|
||||
new^.pWriter.SetParam(ntVolatile,st_cur.pHead);
|
||||
new^.mark_read;
|
||||
PostReg(new);
|
||||
old:=new; //update snap
|
||||
end;
|
||||
|
||||
procedure TEmitVolatile.build_slot_old(pSlot:PsrRegSlot;var old:PsrRegNode);
|
||||
var
|
||||
cur,prv:PsrRegNode;
|
||||
st_old:TsrVolatiles;
|
||||
begin
|
||||
cur:=RegDownSlot(pSlot^.current);
|
||||
prv:=RegDownSlot(old);
|
||||
if (prv=nil) or CompareReg(cur,prv) then Exit;
|
||||
|
||||
cur:=pSlot^.current;
|
||||
|
||||
if (old^.pWriter.ntype=ntVolatile) then
|
||||
begin
|
||||
st_old.pHead:=old^.pWriter.pData;
|
||||
st_old.Push_head(NewVolatile(cur));
|
||||
Exit;
|
||||
end;
|
||||
|
||||
Assert(old^.pWriter.ntype=ntReg);
|
||||
Assert(old^.pWriter.pData<>nil);
|
||||
prv:=old^.pWriter.pData;
|
||||
|
||||
st_old:=Default(TsrVolatiles);
|
||||
st_old.Push_head(NewVolatile(prv));
|
||||
st_old.Push_head(NewVolatile(cur));
|
||||
|
||||
prv^.mark_unread;
|
||||
old^.pWriter.SetParam(ntVolatile,st_old.pHead);
|
||||
end;
|
||||
|
||||
procedure TEmitVolatile.build_volatile_dis(old:PsrRegsSnapshot);
|
||||
begin
|
||||
FRegsStory.ForEachSnap(@build_slot_dis,old);
|
||||
end;
|
||||
|
||||
procedure TEmitVolatile.build_volatile_cur(old:PsrRegsSnapshot);
|
||||
begin
|
||||
NextVolatileID;
|
||||
FRegsStory.ForEachSnap(@build_slot_cur,old);
|
||||
end;
|
||||
|
||||
procedure TEmitVolatile.build_volatile_old(old:PsrRegsSnapshot);
|
||||
begin
|
||||
NextVolatileID;
|
||||
FRegsStory.ForEachSnap(@build_slot_old,old);
|
||||
end;
|
||||
|
||||
procedure TEmitVolatile.make_copy_slot(pSlot:PsrRegSlot);
|
||||
var
|
||||
cur:PsrRegNode;
|
||||
begin
|
||||
if (pSlot^.current<>nil) then
|
||||
begin
|
||||
cur:=pSlot^.current;
|
||||
MakeCopy(pSlot,cur);
|
||||
pSlot^.current^.pLine:=cur^.pLine;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmitVolatile.make_copy_all;
|
||||
begin
|
||||
FRegsStory.ForEachSlot(@make_copy_slot);
|
||||
end;
|
||||
|
||||
|
||||
function get_load_from(r:PsrRegNode):PsrVariable;
|
||||
var
|
||||
pOp:PspirvOp;
|
||||
begin
|
||||
Result:=nil;
|
||||
pOp:=r^.AsOp;
|
||||
if (pOp=nil) then Exit;
|
||||
if (pOp^.OpId<>Op.OpLoad) then Exit;
|
||||
Result:=pOp^.pParam.pHead^.AsVar;
|
||||
end;
|
||||
|
||||
type
|
||||
TsrTypesA=array[Low(TsrDataType)..High(TsrDataType)] of DWORD;
|
||||
|
||||
function calc_best_type(pSlot:PsrRegSlot;st:TsrVolatiles):TsrDataType;
|
||||
var
|
||||
node:PsrVolatile;
|
||||
pReg:PsrRegNode;
|
||||
types:TsrTypesA;
|
||||
i,max_id:TsrDataType;
|
||||
bonly:Boolean;
|
||||
begin
|
||||
Result:=dtUnknow;
|
||||
|
||||
case pSlot^.rid of
|
||||
'SCC':Exit(dtBool); //only bool
|
||||
end;
|
||||
|
||||
types:=Default(TsrTypesA);
|
||||
bonly:=true;
|
||||
node:=st.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.pReg<>nil) then
|
||||
begin
|
||||
pReg:=RegDown(node^.pReg);
|
||||
if (pReg^.dtype<>dtBool) then bonly:=false;
|
||||
Inc(types[pReg^.dtype]);
|
||||
end;
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
|
||||
case pSlot^.rid of
|
||||
'VCCL',
|
||||
'VCCH',
|
||||
'EXECL',
|
||||
'EXECH':if (types[dtBool]<>0) then Exit(dtBool); //prior bool
|
||||
end;
|
||||
|
||||
if bonly and (types[dtBool]<>0) then
|
||||
begin
|
||||
Exit(dtBool);
|
||||
end else
|
||||
begin
|
||||
//types[dtBool]:=0;
|
||||
end;
|
||||
|
||||
max_id:=dtUnknow;
|
||||
For i:=Low(TsrDataType) to High(TsrDataType) do
|
||||
begin
|
||||
if (max_id=dtUnknow) and (types[i]<>0) then
|
||||
begin
|
||||
max_id:=i;
|
||||
end else
|
||||
begin
|
||||
if (types[i]>types[max_id]) then max_id:=i
|
||||
end;
|
||||
end;
|
||||
Result:=max_id;
|
||||
end;
|
||||
|
||||
{
|
||||
procedure MoveVolatiles(dst,src:PsrVolatiles);
|
||||
var
|
||||
node:PsrVolatile;
|
||||
begin
|
||||
repeat
|
||||
node:=src^.Pop_head;
|
||||
if (node=nil) then Break;
|
||||
if (dst^.find_reg(node^.pReg)=nil) then
|
||||
begin
|
||||
//Writeln(node^.pReg^.GetName);
|
||||
dst^.Push_head(node);
|
||||
end else
|
||||
begin
|
||||
RegUnmark(node^.pReg);
|
||||
end;
|
||||
until false;
|
||||
end;
|
||||
|
||||
function TEmitVolatile._PrepVolatile(src:PsrRegNode):Integer;
|
||||
var
|
||||
st_tmp:TsrVolatiles;
|
||||
node:PsrVolatile;
|
||||
pReg:PsrRegNode;
|
||||
begin
|
||||
Result:=0;
|
||||
if (src=nil) then Exit;
|
||||
if (src^.pWriter.ntype<>ntVolatile) then Exit;
|
||||
|
||||
node:=src^.pWriter.pData;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pReg:=RegDownSlot(node^.pReg);
|
||||
|
||||
if (pReg<>nil) then
|
||||
begin
|
||||
if (pReg^.pWriter.ntype=ntVolatile) then
|
||||
begin
|
||||
st_tmp.pHead:=pReg^.pWriter.pData;
|
||||
Assert(st_tmp.pHead<>nil);
|
||||
|
||||
MoveVolatiles(@src^.pWriter.pData,@st_tmp);
|
||||
|
||||
pReg^.pWriter.SetParam(ntReg,src);
|
||||
|
||||
node^.pReg:=nil;
|
||||
Inc(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
}
|
||||
|
||||
procedure TEmitVolatile.PrepVolatile(dst:PspirvOp;src:PsrRegNode);
|
||||
var
|
||||
rtype:TsrDataType;
|
||||
pSlot:PsrRegSlot;
|
||||
pReg,tmp:PsrRegNode;
|
||||
v:PsrVariable;
|
||||
node:PsrVolatile;
|
||||
st,st_tmp:TsrVolatiles;
|
||||
pLine:PspirvOp;
|
||||
begin
|
||||
if (src=nil) then Exit;
|
||||
if (src^.pWriter.ntype<>ntVolatile) then Exit;
|
||||
|
||||
pSlot:=src^.pSlot;
|
||||
|
||||
st.pHead:=src^.pWriter.pData;
|
||||
Assert(st.pHead<>nil);
|
||||
|
||||
//While _PrepVolatile(src)<>0 do;
|
||||
|
||||
v:=pSlot^.pVar;
|
||||
if (v=nil) then
|
||||
begin
|
||||
rtype:=calc_best_type(pSlot,st);
|
||||
|
||||
v:=NewVariable;
|
||||
v^.dtype:=rtype;
|
||||
|
||||
pSlot^.pVar:=v;
|
||||
end else
|
||||
begin
|
||||
rtype:=v^.dtype;
|
||||
end;
|
||||
|
||||
repeat
|
||||
node:=st.Pop_head;
|
||||
if (node=nil) then Break;
|
||||
pReg:=node^.pReg;
|
||||
if (pReg=nil) then Continue;
|
||||
//Assert(pReg<>nil);
|
||||
//Assert(pReg^.pWriter.ntype<>ntVolatile);
|
||||
tmp:=RegDownSlot(pReg);
|
||||
if (v<>get_load_from(tmp)) then
|
||||
begin
|
||||
//mark_read volatile->emit_OpStore
|
||||
pLine:=tmp^.pLine;
|
||||
Assert(pLine<>nil);
|
||||
|
||||
if (tmp^.pWriter.ntype=ntVolatile) then
|
||||
begin
|
||||
st_tmp.pHead:=tmp^.pWriter.pData;
|
||||
Assert(st_tmp.pHead<>nil);
|
||||
|
||||
st.Move_from(st_tmp);
|
||||
|
||||
src^.mark_read;
|
||||
tmp^.pWriter.SetParam(ntReg,src);
|
||||
|
||||
//tmp^.pLine:=dst;
|
||||
//writeln;
|
||||
//PrepVolatile(pReg^.pLine,pReg);
|
||||
|
||||
node^.pReg:=nil;
|
||||
Continue;
|
||||
end;
|
||||
|
||||
{Case pLine^.OpId of
|
||||
OpLinks:Writeln('OpLinks');
|
||||
OpBlock:Writeln('OpBlock');
|
||||
else
|
||||
Writeln(Op.GetStr(pLine^.OpId));
|
||||
end;
|
||||
Writeln(HexStr(pLine^.Adr.Offdw*4,4));
|
||||
|
||||
Assert(pReg^.pWriter.ntype<>ntVolatile);}
|
||||
|
||||
TSprvEmit_post(Self).PrepTypeNode(pReg,rtype);
|
||||
|
||||
{if pLine^.Adr.Offdw*4=$AC then
|
||||
begin
|
||||
writeln('dst:',Op.GetStr(dst^.OpId),' ',HexStr(dst^.Adr.Offdw*4,4));
|
||||
writeln;
|
||||
end;}
|
||||
|
||||
_up_merge_line(pLine);
|
||||
|
||||
TSprvEmit_post(Self).emit_OpStore(pLine,v,pReg); //after reg
|
||||
end else
|
||||
begin
|
||||
RegUnmark(pReg);
|
||||
//pReg^.mark_unread;
|
||||
end;
|
||||
until false;
|
||||
|
||||
v^.mark_read;
|
||||
//src^.dtype:=rtype; //reuse
|
||||
pLine:=dst;
|
||||
Assert(pLine<>nil);
|
||||
pLine:=pLine^.pPrev;
|
||||
Assert(pLine<>nil);
|
||||
|
||||
_up_merge_line(pLine);
|
||||
|
||||
Assert(pLine<>nil);
|
||||
|
||||
TSprvEmit_post(Self).PrepTypeDst(src,rtype); //reuse
|
||||
|
||||
TSprvEmit_post(Self).emit_OpLoad(pLine,src,v); //before reg
|
||||
end;
|
||||
|
||||
end.
|
||||
|
Loading…
Reference in New Issue
Block a user