mirror of https://github.com/red-prig/fpPS4.git
New shader recompiler version
This commit is contained in:
parent
80d3bf043b
commit
818cddd5b7
1557
spirv/SprvEmit.pas
1557
spirv/SprvEmit.pas
File diff suppressed because it is too large
Load Diff
|
@ -7,36 +7,35 @@ interface
|
|||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
srNodes,
|
||||
srNode,
|
||||
srType,
|
||||
srTypes,
|
||||
srConst,
|
||||
srRefId,
|
||||
srReg,
|
||||
srLayout,
|
||||
srBuffer,
|
||||
srVariable,
|
||||
srInput,
|
||||
srOutput,
|
||||
srVertLayout,
|
||||
srFragLayout,
|
||||
srUniform,
|
||||
srBuffer,
|
||||
srDecorate,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
SprvEmit;
|
||||
emit_fetch;
|
||||
|
||||
type
|
||||
TSprvEmit_alloc=object(TSprvEmit)
|
||||
procedure Alloc;
|
||||
TSprvEmit_alloc=class(TEmitFetch)
|
||||
procedure AllocStage;
|
||||
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 AllocListId(node:PsrNode);
|
||||
procedure AllocFuncId;
|
||||
procedure AllocOpId(node:PSpirvOp);
|
||||
procedure AllocOpBlock(pBlock:PsrOpBlock);
|
||||
|
@ -44,134 +43,99 @@ type
|
|||
|
||||
implementation
|
||||
|
||||
procedure TSprvEmit_alloc.Alloc;
|
||||
procedure TSprvEmit_alloc.AllocStage;
|
||||
begin
|
||||
AllocBinding;
|
||||
|
||||
BufferList.AllocTypeBinding;
|
||||
AllocTypeBinding;
|
||||
|
||||
AllocHeader;
|
||||
|
||||
AllocSourceExtension;
|
||||
AllocTypeName;
|
||||
AllocVarName;
|
||||
//Source Extension
|
||||
DataLayoutList.AllocSourceExtension;
|
||||
DataLayoutList.AllocFuncExt;
|
||||
VertLayoutList.AllocSourceExtension;
|
||||
UniformList .AllocSourceExtension;
|
||||
BufferList .AllocSourceExtension;
|
||||
|
||||
AllocHeaderId;
|
||||
//Decorate Name
|
||||
BufferList .AllocName;
|
||||
VariableList.AllocName;
|
||||
|
||||
//header id
|
||||
AllocOpListId(HeaderList.First);
|
||||
AllocOpListId(DebugInfoList.First);
|
||||
AllocOpListId(DecorateList.First);
|
||||
|
||||
//element id
|
||||
AllocListId(TypeList.First);
|
||||
AllocListId(ConstList.First);
|
||||
AllocListId(VariableList.First);
|
||||
|
||||
AllocTypesId;
|
||||
AllocConstId;
|
||||
AllocVariableId;
|
||||
AllocFuncId;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocSpirvID(P:PsrRefId);
|
||||
begin
|
||||
FSpirvIdAlloc.FetchSpirvID(P);
|
||||
RefIdAlloc.FetchSpirvID(P);
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocBinding;
|
||||
var
|
||||
FBinding:Integer;
|
||||
begin
|
||||
FInputs .AllocBinding(@FDecorates);
|
||||
FOutputs .AllocBinding(@FDecorates);
|
||||
FVertLayouts.AllocBinding(@FDecorates);
|
||||
FFragLayouts.AllocBinding(@FDecorates,@FSpirvCaps);
|
||||
InputList .AllocBinding;
|
||||
OutputList.AllocBinding;
|
||||
|
||||
VertLayoutList.AllocBinding;
|
||||
FragLayoutList.AllocBinding;
|
||||
|
||||
FBinding:=0;
|
||||
FUniforms.AllocBinding(FBinding,@FDecorates);
|
||||
FBuffers .AllocBinding(FBinding,@FDecorates);
|
||||
|
||||
UniformList.AllocBinding(FBinding);
|
||||
BufferList .AllocBinding(FBinding);
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocTypeBinding;
|
||||
var
|
||||
node:PsrType;
|
||||
pField:PsrField;
|
||||
begin
|
||||
node:=FSpirvTypes.FList.pHead;
|
||||
node:=TypeList.First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
|
||||
case node^.dtype of
|
||||
dtTypeStruct:
|
||||
case node^.OpId of
|
||||
|
||||
Op.OpTypeArray,
|
||||
Op.OpTypeRuntimeArray:
|
||||
begin
|
||||
pField:=node^.key.ext.pField;
|
||||
if (pField<>nil) then
|
||||
DecorateList.OpDecorate(node,Decoration.ArrayStride,node^.array_stride);
|
||||
end;
|
||||
|
||||
Op.OpTypeFloat:
|
||||
begin
|
||||
if (pField^.GetStructDecorate<>DWORD(-1)) then
|
||||
begin
|
||||
FDecorates.emit_decorate(ntType,node,pField^.GetStructDecorate,0);
|
||||
case node^.dtype.BitSize of
|
||||
16:AddCapability(Capability.Float16);
|
||||
64:AddCapability(Capability.Float64);
|
||||
else;
|
||||
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
|
||||
Op.OpTypeInt:
|
||||
begin
|
||||
FDebugInfo.emit_name(ntType,node,pField^.pBuffer^.GetStructName);
|
||||
case node^.dtype.BitSize of
|
||||
8:AddCapability(Capability.Int8);
|
||||
16:AddCapability(Capability.Int16);
|
||||
64:AddCapability(Capability.Int64);
|
||||
else;
|
||||
end;
|
||||
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;
|
||||
node:=node^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -180,7 +144,7 @@ begin
|
|||
While (node<>nil) do
|
||||
begin
|
||||
AllocOpId(node);
|
||||
node:=node^.pNext;
|
||||
node:=node^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -188,24 +152,24 @@ procedure TSprvEmit_alloc.AllocEntryPoint;
|
|||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
node:=FHeader.AddSpirvOp(Op.OpEntryPoint);
|
||||
node:=HeaderList.AddSpirvOp(Op.OpEntryPoint);
|
||||
|
||||
node^.AddLiteral(FExecutionModel,ExecutionModel.GetStr(FExecutionModel));
|
||||
|
||||
node^.AddParam(ntFunc,FMain);
|
||||
node^.AddString(FMain^.name);
|
||||
node^.AddParam(Main);
|
||||
node^.AddString(Main^.name);
|
||||
|
||||
FInputs .AllocEntryPoint(node);
|
||||
FVertLayouts.AllocEntryPoint(node);
|
||||
FFragLayouts.AllocEntryPoint(node);
|
||||
FOutputs .AllocEntryPoint(node);
|
||||
InputList .AllocEntryPoint(node);
|
||||
VertLayoutList.AllocEntryPoint(node);
|
||||
FragLayoutList.AllocEntryPoint(node);
|
||||
OutputList .AllocEntryPoint(node);
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocHeader;
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
node:=FHeader.AddSpirvOp(Op.OpMemoryModel);
|
||||
node:=HeaderList.AddSpirvOp(Op.OpMemoryModel);
|
||||
node^.AddLiteral(AddressingModel.Logical,AddressingModel.GetStr(AddressingModel.Logical));
|
||||
node^.AddLiteral(MemoryModel.GLSL450,MemoryModel.GetStr(MemoryModel.GLSL450));
|
||||
|
||||
|
@ -214,14 +178,14 @@ begin
|
|||
Case FExecutionModel of
|
||||
ExecutionModel.Fragment:
|
||||
begin
|
||||
node:=FHeader.AddSpirvOp(Op.OpExecutionMode);
|
||||
node^.AddParam(ntFunc,FMain);
|
||||
node:=HeaderList.AddSpirvOp(Op.OpExecutionMode);
|
||||
node^.AddParam(Main);
|
||||
node^.AddLiteral(ExecutionMode.OriginUpperLeft,ExecutionMode.GetStr(ExecutionMode.OriginUpperLeft));
|
||||
end;
|
||||
ExecutionModel.GLCompute:
|
||||
begin
|
||||
node:=FHeader.AddSpirvOp(Op.OpExecutionMode);
|
||||
node^.AddParam(ntFunc,FMain);
|
||||
node:=HeaderList.AddSpirvOp(Op.OpExecutionMode);
|
||||
node^.AddParam(Main);
|
||||
node^.AddLiteral(ExecutionMode.LocalSize,ExecutionMode.GetStr(ExecutionMode.LocalSize));
|
||||
node^.AddLiteral(FLocalSize.x);
|
||||
node^.AddLiteral(FLocalSize.y);
|
||||
|
@ -231,135 +195,12 @@ begin
|
|||
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_alloc.AllocHeaderId;
|
||||
procedure TSprvEmit_alloc.AllocListId(node:PsrNode);
|
||||
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;
|
||||
AllocSpirvID(node^.GetRef);
|
||||
node:=node^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -367,11 +208,11 @@ procedure TSprvEmit_alloc.AllocFuncId;
|
|||
var
|
||||
pFunc:PSpirvFunc;
|
||||
begin
|
||||
pFunc:=FSpirvFuncs.FList.pHead;
|
||||
pFunc:=FuncList.First;
|
||||
While (pFunc<>nil) do
|
||||
begin
|
||||
AllocOpBlock(@pFunc^.FTop);
|
||||
pFunc:=pFunc^.pNext;
|
||||
AllocOpBlock(pFunc^.pTop);
|
||||
pFunc:=pFunc^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -387,34 +228,38 @@ begin
|
|||
|
||||
if Info.result then //dst
|
||||
begin
|
||||
Assert(node^.dst.ntype<>ntUnknow,'AllocOp$1');
|
||||
Assert(node^.dst.pData<>nil ,'AllocOp$2');
|
||||
AllocOpSingle(node^.dst);
|
||||
Assert(node^.pDst<>nil,'AllocOp$1');
|
||||
if (node^.pDst<>nil) then
|
||||
begin
|
||||
AllocSpirvID(node^.pDst^.GetRef);
|
||||
end;
|
||||
end else
|
||||
begin //no dst
|
||||
if (node^.dst.ntype<>ntUnknow) then
|
||||
if (node^.pDst<>nil) then
|
||||
begin
|
||||
Assert(node^.dst.pData<>nil,'AllocOp$3');
|
||||
AllocOpSingle(node^.dst);
|
||||
AllocSpirvID(node^.pDst^.GetRef);
|
||||
end;
|
||||
end;
|
||||
|
||||
if Info.rstype then //dst type
|
||||
begin
|
||||
if (node^.dst_type=nil) then
|
||||
if (node^.pType=nil) then
|
||||
begin
|
||||
pReg:=node^.dst.AsReg;
|
||||
if (pReg^.dtype=dtUnknow) then pReg^.dtype:=dtFloat32;
|
||||
node^.dst_type:=FSpirvTypes.Fetch(pReg^.dtype);
|
||||
//Assert(false,'AllocOp$4');
|
||||
pReg:=node^.pDst^.AsType(ntReg);
|
||||
Assert(pReg<>nil,'AllocOp$2');
|
||||
Assert(pReg^.dtype<>dtUnknow,'AllocOp$3');
|
||||
if (pReg<>nil) then
|
||||
begin
|
||||
node^.pType:=TypeList.Fetch(pReg^.dtype);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Param:=node^.pParam.pHead;
|
||||
Param:=node^.ParamFirst;
|
||||
While (Param<>nil) do
|
||||
begin
|
||||
AllocOpParamNode(Param);
|
||||
Param:=Param^.pNext;
|
||||
AllocSpirvID(Param^.Value^.GetRef);
|
||||
Param:=Param^.Next;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
@ -424,22 +269,14 @@ var
|
|||
node:PSpirvOp;
|
||||
begin
|
||||
if (pBlock=nil) then Exit;
|
||||
node:=pBlock^.pHead;
|
||||
node:=pBlock^.First;
|
||||
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
|
||||
if node^.IsType(ntOp) then
|
||||
begin
|
||||
AllocOpId(node);
|
||||
end;
|
||||
|
||||
node:=node^.pNext;
|
||||
node:=flow_down_next_up(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
|
@ -8,17 +8,16 @@ uses
|
|||
SySutils,
|
||||
Classes,
|
||||
spirv,
|
||||
srNodes,
|
||||
srNode,
|
||||
srType,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
srCap,
|
||||
srCapability,
|
||||
srRefId,
|
||||
SprvEmit;
|
||||
emit_fetch;
|
||||
|
||||
type
|
||||
TSPIRVHeader=packed record
|
||||
|
@ -30,7 +29,7 @@ type
|
|||
TOOL_VERSION:WORD;
|
||||
TOOL_ID:WORD;
|
||||
BOUND:DWORD;
|
||||
RESERVED:DWORD;
|
||||
SCHEMA:DWORD;
|
||||
end;
|
||||
|
||||
PSPIRVInstruction=^TSPIRVInstruction;
|
||||
|
@ -45,31 +44,23 @@ type
|
|||
COUNT:DWORD;
|
||||
Procedure AllocData;
|
||||
Procedure NewOp(OpId:WORD);
|
||||
Procedure Reset;
|
||||
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);
|
||||
procedure AddParam(P:DWORD);
|
||||
procedure AddNode(node:PsrNode);
|
||||
end;
|
||||
|
||||
TSprvEmit_bin=object(TSprvEmit)
|
||||
TSprvEmit_bin=class(TEmitFetch)
|
||||
procedure SaveToStream(Stream:TStream);
|
||||
procedure SaveHeader(Stream:TStream;var Header:TSPIRVHeader);
|
||||
procedure SaveCaps(Stream:TStream);
|
||||
procedure SaveOpList(Stream:TStream;node:PspirvOp);
|
||||
procedure SaveOpBlock(Stream:TStream;pBlock:PsrOpBlock);
|
||||
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
|
||||
|
@ -97,15 +88,20 @@ begin
|
|||
Data[0]:=DWORD(I);
|
||||
end;
|
||||
|
||||
Procedure TSVInstrBuffer.Reset;
|
||||
begin
|
||||
COUNT:=0;
|
||||
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;
|
||||
Reset;
|
||||
end;
|
||||
|
||||
procedure TSVInstrBuffer.AddParamId(P:DWORD);
|
||||
procedure TSVInstrBuffer.AddParam(P:DWORD);
|
||||
var
|
||||
I:DWORD;
|
||||
begin
|
||||
|
@ -116,75 +112,33 @@ begin
|
|||
Data[i]:=P;
|
||||
end;
|
||||
|
||||
procedure TSVInstrBuffer.AddString(const name:PChar);
|
||||
procedure TSVInstrBuffer.AddNode(node:PsrNode);
|
||||
var
|
||||
R:PsrRefId;
|
||||
I,L,D:DWORD;
|
||||
begin
|
||||
Assert(name<>nil);
|
||||
Assert(node<>nil);
|
||||
Assert(COUNT<>0,'new op not created');
|
||||
|
||||
L:=StrLen(name);
|
||||
D:=(L+SizeOf(DWORD)) div SizeOf(DWORD);
|
||||
R:=node^.GetRef;
|
||||
if (R<>nil) then
|
||||
begin
|
||||
I:=COUNT;
|
||||
Inc(COUNT);
|
||||
AllocData;
|
||||
Data[i]:=R^.ID;
|
||||
end else
|
||||
begin
|
||||
L:=node^.GetData(nil); //get size
|
||||
D:=(L+(SizeOf(DWORD)-1)) div 4; //align
|
||||
Assert(D<>0,'AddNode:'+node^.ntype.ClassName);
|
||||
|
||||
I:=COUNT;
|
||||
COUNT:=COUNT+D;
|
||||
AllocData;
|
||||
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');
|
||||
FillDWord(Data[i],D,0);
|
||||
node^.GetData(@Data[i]);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -196,10 +150,12 @@ begin
|
|||
|
||||
Header:=Default(TSPIRVHeader);
|
||||
|
||||
Header.MAGIC:=spirv.MagicNumber;
|
||||
DWORD(Header.VERSION):=FBuffers.cfg.SpvVersion;
|
||||
Header.TOOL_VERSION:=1;
|
||||
Header.BOUND:=FSpirvIdAlloc.GetSpirvIDBound;
|
||||
Header.MAGIC :=MagicNumber;
|
||||
DWORD(Header.VERSION) :=Config.SpvVersion;
|
||||
Header.TOOL_VERSION:=2;
|
||||
Header.TOOL_ID :=0;
|
||||
Header.BOUND :=RefIdAlloc.GetSpirvIDBound;
|
||||
Header.SCHEMA :=0;
|
||||
|
||||
SaveHeader(Stream,Header);
|
||||
|
||||
|
@ -219,199 +175,96 @@ end;
|
|||
procedure TSprvEmit_bin.SaveCaps(Stream:TStream);
|
||||
var
|
||||
buf:TSVInstrBuffer;
|
||||
node:PSpirvCap;
|
||||
node:PsrCapability;
|
||||
begin
|
||||
buf:=Default(TSVInstrBuffer);
|
||||
node:=FSpirvCaps.First;
|
||||
node:=CapabilityList.First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
buf.NewOp(Op.OpCapability);
|
||||
buf.AddParamId(node^.ID);
|
||||
buf.AddParam(node^.ID);
|
||||
buf.Flush(Stream);
|
||||
node:=FSpirvCaps.Next(node);
|
||||
node:=CapabilityList.Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_bin.SaveOpList(Stream:TStream;node:PspirvOp);
|
||||
procedure TSprvEmit_bin.SaveOpBlock(Stream:TStream;pBlock:PsrOpBlock);
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
if (pBlock=nil) then Exit;
|
||||
node:=pBlock^.First;
|
||||
|
||||
While (node<>nil) do
|
||||
begin
|
||||
SaveOp(Stream,node);
|
||||
node:=node^.pNext;
|
||||
if node^.IsType(ntOp) then
|
||||
begin
|
||||
SaveOp(Stream,node);
|
||||
end;
|
||||
node:=flow_down_next_up(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_bin.SaveHeaderInfo(Stream:TStream);
|
||||
begin
|
||||
SaveOpList(Stream,FHeader.pHead);
|
||||
SaveOpList(Stream,FDebugInfo.pHead);
|
||||
SaveOpList(Stream,FDecorates.pHead);
|
||||
SaveOpBlock(Stream,@HeaderList);
|
||||
SaveOpBlock(Stream,@DebugInfoList);
|
||||
SaveOpBlock(Stream,@DecorateList);
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_bin.SaveTypes(Stream:TStream);
|
||||
var
|
||||
buf:TSVInstrBuffer;
|
||||
node:PsrType;
|
||||
pConst:PsrConst;
|
||||
i:dword;
|
||||
ie:Boolean;
|
||||
i:Word;
|
||||
begin
|
||||
buf:=Default(TSVInstrBuffer);
|
||||
node:=FSpirvTypes.FList.pHead;
|
||||
node:=TypeList.First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
ie:=True;
|
||||
buf.NewOp(node^.OpId);
|
||||
buf.AddNode(node);
|
||||
|
||||
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
|
||||
if (node^.ItemCount<>0) then
|
||||
begin
|
||||
For i:=0 to node^.ItemCount-1 do
|
||||
begin
|
||||
For i:=0 to node^.key.count-1 do
|
||||
begin
|
||||
buf.AddTypeId(node^.GetCompItem(i));
|
||||
end;
|
||||
buf.AddNode(node^.GetItem(i));
|
||||
end;
|
||||
end;
|
||||
|
||||
buf.Flush(Stream);
|
||||
|
||||
node:=node^.pNext;
|
||||
node:=node^.Next;
|
||||
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;
|
||||
i:Word;
|
||||
begin
|
||||
buf:=Default(TSVInstrBuffer);
|
||||
node:=FConsts.FList.pHead;
|
||||
node:=ConstList.FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.key.dtype<>dtUnknow) then
|
||||
if (node^.dtype<>dtUnknow) then
|
||||
begin
|
||||
SaveConst(buf,node);
|
||||
buf.NewOp(node^.OpId);
|
||||
buf.AddNode(node^.pType);
|
||||
buf.AddNode(node);
|
||||
|
||||
if (node^.dtype<>dtBool) and (node^.ItemCount<>0) then
|
||||
begin
|
||||
For i:=0 to node^.ItemCount-1 do
|
||||
begin
|
||||
buf.AddNode(node^.GetItem(i));
|
||||
end;
|
||||
end;
|
||||
|
||||
buf.Flush(Stream);
|
||||
end;
|
||||
node:=node^.pNext;
|
||||
node:=node^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -421,52 +274,19 @@ var
|
|||
node:PsrVariable;
|
||||
begin
|
||||
buf:=Default(TSVInstrBuffer);
|
||||
node:=FVariables.pHead;
|
||||
node:=VariableList.First;
|
||||
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.AddNode(node^.pType);
|
||||
buf.AddNode(node);
|
||||
buf.AddParam(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;
|
||||
node:=node^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -474,11 +294,11 @@ procedure TSprvEmit_bin.SaveFunc(Stream:TStream);
|
|||
var
|
||||
pFunc:PSpirvFunc;
|
||||
begin
|
||||
pFunc:=FSpirvFuncs.FList.pHead;
|
||||
pFunc:=FuncList.First;
|
||||
While (pFunc<>nil) do
|
||||
begin
|
||||
SaveOpBlock(Stream,@pFunc^.FTop);
|
||||
pFunc:=pFunc^.pNext;
|
||||
SaveOpBlock(Stream,pFunc^.pTop);
|
||||
pFunc:=pFunc^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -497,58 +317,46 @@ begin
|
|||
|
||||
if Info.rstype then //dst type
|
||||
begin
|
||||
Assert(node^.dst_type<>nil,'SaveOp$4');
|
||||
buf.AddTypeId(node^.dst_type);
|
||||
Assert(node^.pType<>nil,'SaveOp$1');
|
||||
if (node^.pType<>nil) then
|
||||
begin
|
||||
buf.AddNode(node^.pType);
|
||||
end else
|
||||
begin
|
||||
buf.Reset;
|
||||
Exit;
|
||||
end;
|
||||
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);
|
||||
Assert(node^.pDst<>nil,'SaveOp$2');
|
||||
if (node^.pDst<>nil) then
|
||||
begin
|
||||
buf.AddNode(node^.pDst);
|
||||
end else
|
||||
begin
|
||||
buf.Reset;
|
||||
Exit;
|
||||
end;
|
||||
end else
|
||||
begin //no dst
|
||||
if (node^.dst.ntype<>ntUnknow) then
|
||||
if (node^.pDst<>nil) then
|
||||
begin
|
||||
Assert(node^.dst.pData<>nil,'SaveOp$3');
|
||||
SaveOpSingle(buf,node^.dst);
|
||||
buf.AddNode(node^.pDst);
|
||||
end;
|
||||
end;
|
||||
|
||||
Param:=node^.pParam.pHead;
|
||||
Param:=node^.ParamFirst;
|
||||
While (Param<>nil) do
|
||||
begin
|
||||
SaveOpParamNode(buf,Param);
|
||||
Param:=Param^.pNext;
|
||||
buf.AddNode(Param^.Value);
|
||||
Param:=Param^.Next;
|
||||
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.
|
||||
|
||||
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
unit emit_DS;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srReg,
|
||||
spirv,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmit_DS=object(TEmitOp)
|
||||
procedure _emit_DS;
|
||||
procedure _emit_DS_SWIZZLE_B32;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_DS._emit_DS_SWIZZLE_B32; //TODO
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.DS.VDST);
|
||||
SetConst(dst,dtFloat32,0);
|
||||
end;
|
||||
|
||||
procedure TEmit_DS._emit_DS;
|
||||
begin
|
||||
|
||||
Case FSPI.DS.OP of
|
||||
|
||||
DS_NOP:;
|
||||
|
||||
//DS_SWIZZLE_B32 v4 v3 v0 v0 OFFSET:0x80AA GDS:0
|
||||
|
||||
DS_SWIZZLE_B32: //TODO
|
||||
begin;
|
||||
_emit_DS_SWIZZLE_B32;
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(false,'DS?');
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
{
|
||||
OFFSET0:Byte;
|
||||
OFFSET1:Byte;
|
||||
GDS:bit1;
|
||||
ADDR:Byte; (vbindex)
|
||||
DATA0:Byte; (vsrc0)
|
||||
DATA1:Byte; (vsrc1)
|
||||
VDST:Byte;
|
||||
}
|
||||
|
||||
end.
|
||||
|
||||
|
|
@ -6,27 +6,26 @@ interface
|
|||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
ps4_pssl,
|
||||
srNodes,
|
||||
srLabel,
|
||||
srTypes,
|
||||
srCFGLabel,
|
||||
srConfig,
|
||||
srFlow,
|
||||
srType,
|
||||
srReg,
|
||||
srVariable,
|
||||
srOutput,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
emit_fetch;
|
||||
|
||||
type
|
||||
TEmit_EXP=object(TEmitOp)
|
||||
procedure _emit_EXP;
|
||||
TEmit_EXP=class(TEmitFetch)
|
||||
procedure emit_EXP;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_EXP._emit_EXP;
|
||||
procedure TEmit_EXP.emit_EXP;
|
||||
Var
|
||||
exc:PsrRegNode;
|
||||
node:PSpirvOp;
|
||||
|
@ -35,7 +34,7 @@ Var
|
|||
dout:PsrVariable;
|
||||
dst:PsrRegNode;
|
||||
src:array[0..3] of PsrRegNode;
|
||||
rsl:array[0..3] of PsrRegNode;
|
||||
//rsl:array[0..3] of PsrRegNode;
|
||||
rtype:TsrDataType;
|
||||
f,i,p:Byte;
|
||||
|
||||
|
@ -46,12 +45,12 @@ begin
|
|||
if (FSPI.EXP.VM<>0) and (FSPI.EXP.DONE<>0) then
|
||||
begin
|
||||
pOpBlock:=AllocBlockOp;
|
||||
pOpBlock^.SetInfo(btOther,FCursor.Adr,FCursor.Adr);
|
||||
pOpBlock^.SetInfo(btOther,Cursor.Adr,Cursor.Adr);
|
||||
PushBlockOp(line,pOpBlock,nil);
|
||||
|
||||
exc:=MakeRead(@FRegsStory.EXEC[0],dtBool);
|
||||
exc:=MakeRead(get_exec0,dtBool);
|
||||
node:=AddSpirvOp(OpMakeExp);
|
||||
node^.AddParam(ntReg,exc); //<-fetch read
|
||||
node^.AddParam(exc); //<-fetch read
|
||||
end;
|
||||
|
||||
//before
|
||||
|
@ -60,13 +59,13 @@ begin
|
|||
begin
|
||||
if (pOpBlock<>nil) then //is pushed
|
||||
begin
|
||||
FMain^.PopBlock;
|
||||
Main^.PopBlock;
|
||||
end;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
pOpBlock:=AllocBlockOp; //down
|
||||
pOpBlock^.SetInfo(btOther,FCursor.Adr,FCursor.Adr);
|
||||
pOpBlock^.SetInfo(btOther,Cursor.Adr,Cursor.Adr);
|
||||
PushBlockOp(line,pOpBlock,nil);
|
||||
|
||||
//output
|
||||
|
@ -94,7 +93,7 @@ begin
|
|||
Assert(false);
|
||||
end;
|
||||
dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),dtFloat32); //output in FSPI.EXP.TGT
|
||||
emit_OpStore(line,dout,src[0]);
|
||||
OpStore(line,dout,src[0]);
|
||||
end else
|
||||
begin
|
||||
|
||||
|
@ -128,11 +127,10 @@ begin
|
|||
Inc(i);
|
||||
end;
|
||||
|
||||
dst:=emit_OpMakeVec(line,rtype,p,@src);
|
||||
dst^.mark_read;
|
||||
dst:=OpMakeVec(line,rtype,@src);
|
||||
|
||||
dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),rtype); //output in FSPI.EXP.TGT
|
||||
emit_OpStore(line,dout,dst);
|
||||
OpStore(line,dout,dst);
|
||||
end;
|
||||
|
||||
end else
|
||||
|
@ -153,43 +151,31 @@ begin
|
|||
Assert(false);
|
||||
end;
|
||||
|
||||
if FUseOutput16 then
|
||||
if Config.UseOutput16 then
|
||||
begin
|
||||
dst:=emit_OpMakeVec(line,dtVec4h,4,@src);
|
||||
dst^.mark_read;
|
||||
dst:=OpMakeVec(line,dtVec4h,@src);
|
||||
|
||||
rtype:=dtVec4h;
|
||||
end else
|
||||
begin
|
||||
rsl[0]:=NewReg(dtFloat32);
|
||||
rsl[1]:=NewReg(dtFloat32);
|
||||
rsl[2]:=NewReg(dtFloat32);
|
||||
rsl[3]:=NewReg(dtFloat32);
|
||||
|
||||
_emit_Op1(line,Op.OpFConvert,rsl[0],src[0]);
|
||||
_emit_Op1(line,Op.OpFConvert,rsl[1],src[1]);
|
||||
_emit_Op1(line,Op.OpFConvert,rsl[2],src[2]);
|
||||
_emit_Op1(line,Op.OpFConvert,rsl[3],src[3]);
|
||||
|
||||
rsl[0]^.mark_read;
|
||||
rsl[1]^.mark_read;
|
||||
rsl[2]^.mark_read;
|
||||
rsl[3]^.mark_read;
|
||||
|
||||
dst:=emit_OpMakeVec(line,dtVec4f,4,@rsl);
|
||||
dst^.mark_read;
|
||||
src[0]:=OpFToF(src[0],dtFloat32);
|
||||
src[1]:=OpFToF(src[1],dtFloat32);
|
||||
src[2]:=OpFToF(src[2],dtFloat32);
|
||||
src[3]:=OpFToF(src[3],dtFloat32);
|
||||
|
||||
rtype:=dtVec4f;
|
||||
end;
|
||||
|
||||
dst:=OpMakeVec(line,rtype,@src);
|
||||
|
||||
dout:=FetchOutput(TpsslExportType(FSPI.EXP.TGT),rtype); //output in FSPI.EXP.TGT
|
||||
emit_OpStore(line,dout,dst);
|
||||
OpStore(line,dout,dst);
|
||||
end;
|
||||
|
||||
if (pOpBlock<>nil) then //is pushed
|
||||
begin
|
||||
FMain^.PopBlock;
|
||||
FMain^.PopBlock;
|
||||
Main^.PopBlock;
|
||||
Main^.PopBlock;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
|
@ -0,0 +1,613 @@
|
|||
unit emit_fetch;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ps4_pssl,
|
||||
srNode,
|
||||
srBitcast,
|
||||
srType,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
srLayout,
|
||||
srVertLayout,
|
||||
srFragLayout,
|
||||
srVariable,
|
||||
srInput,
|
||||
srOutput,
|
||||
srUniform,
|
||||
srFlow;
|
||||
|
||||
type
|
||||
TEmitFetch=class(TEmitFlow)
|
||||
//
|
||||
function GroupingSharp(src:PPsrRegSlot;rtype:TsrResourceType):PsrDataLayout;
|
||||
//
|
||||
procedure PrepTypeSlot(pSlot:PsrRegSlot;rtype:TsrDataType);
|
||||
function MakeRead(pSlot:PsrRegSlot;rtype:TsrDataType):PsrRegNode;
|
||||
//
|
||||
function PrepTypeNode(var node:PsrRegNode;rtype:TsrDataType;relax:Boolean=true):Integer;
|
||||
function PrepTypeDst(var node:PsrRegNode;rtype:TsrDataType;relax:Boolean=true):Integer;
|
||||
function PrepTypeParam(node:POpParamNode;rtype:TsrDataType;relax:Boolean=true):Integer;
|
||||
//
|
||||
function get_vcc0:PsrRegSlot;
|
||||
function get_vcc1:PsrRegSlot;
|
||||
function get_m0:PsrRegSlot;
|
||||
function get_exec0:PsrRegSlot;
|
||||
function get_exec1:PsrRegSlot;
|
||||
function get_scc:PsrRegSlot;
|
||||
//
|
||||
function get_sdst7(SDST:Byte):PsrRegSlot;
|
||||
function get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean;
|
||||
function get_ssrc8(SSRC:Byte):PsrRegSlot;
|
||||
function get_ssrc9(SSRC:Word):PsrRegSlot;
|
||||
function get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean;
|
||||
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;
|
||||
//
|
||||
function fetch_ssrc8(SOFFSET:Word;rtype:TsrDataType):PsrRegNode;
|
||||
function fetch_ssrc9(SSRC:Word;rtype:TsrDataType):PsrRegNode;
|
||||
function fetch_ssrc9_pair(SSRC:Word;src:PPsrRegNode;rtype:TsrDataType):Boolean;
|
||||
function fetch_vsrc8(VSRC:Word;rtype:TsrDataType):PsrRegNode;
|
||||
function fetch_vdst8(VDST:Word;rtype:TsrDataType):PsrRegNode;
|
||||
procedure fetch_vsrc8_vec2h(VSRC:Word;var dst0,dst1:PsrRegNode);
|
||||
//
|
||||
procedure OpCmpV(OpId:DWORD;dst:PsrRegSlot;src0,src1:PsrRegNode);
|
||||
procedure OpCmpS(OpId:DWORD;dst:PsrRegSlot;src0,src1:PsrRegNode);
|
||||
procedure OpConvFloatToHalf2(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
||||
//
|
||||
function AddInput(dst:PsrRegSlot;rtype:TsrDataType;itype:TpsslInputType;id:Byte=0):PsrRegNode;
|
||||
function AddAncillary(dst:PsrRegSlot):PsrRegNode;
|
||||
function AddVertLayout(pLayout:PsrDataLayout;rtype:TsrDataType):PsrRegNode;
|
||||
function AddFragLayout(itype:TpsslInputType;rtype:TsrDataType;location:DWORD):PsrRegNode;
|
||||
function FetchLoad(pChain:PsrChain;rtype:TsrDataType):PsrRegNode;
|
||||
Procedure FetchStore(pChain:PsrChain;src:PsrRegNode);
|
||||
procedure AddUserdata(dst:PsrRegSlot;offset_dw:Byte);
|
||||
function FetchChain(grp:PsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrRegNode;
|
||||
function MakeChain(pSlot:PsrRegSlot;grp:PsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrRegNode;
|
||||
Procedure AddVecInput(dst:PsrRegSlot;vtype,rtype:TsrDataType;itype:TpsslInputType;id:Byte);
|
||||
function FetchUniform(src:PsrDataLayout;pType:PsrType):PsrNode;
|
||||
function FetchImage(src:PsrDataLayout;dtype:TsrDataType;info:TsrTypeImageInfo):PsrNode;
|
||||
function FetchSampler(src:PsrDataLayout):PsrNode;
|
||||
function FetchOutput(etype:TpsslExportType;rtype:TsrDataType):PsrVariable;
|
||||
end;
|
||||
|
||||
function GetInputRegNode(node:PsrRegNode):PsrInput;
|
||||
|
||||
implementation
|
||||
|
||||
function GetInputRegNode(node:PsrRegNode):PsrInput;
|
||||
var
|
||||
pSource:PsrNode;
|
||||
begin
|
||||
pSource:=GetSourceRegNode(node);
|
||||
Result:=pSource^.AsType(ntInput);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TEmitFetch.GroupingSharp(src:PPsrRegSlot;rtype:TsrResourceType):PsrDataLayout;
|
||||
var
|
||||
chain:TsrChains;
|
||||
i,n:Byte;
|
||||
begin
|
||||
Result:=nil;
|
||||
chain:=Default(TsrChains);
|
||||
n:=GetResourceSizeDw(rtype);
|
||||
|
||||
For i:=0 to n-1 do
|
||||
begin
|
||||
chain[i]:=GetChainRegNode(src[i]^.current);
|
||||
end;
|
||||
|
||||
Result:=DataLayoutList.Grouping(chain,rtype);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
procedure TEmitFetch.PrepTypeSlot(pSlot:PsrRegSlot;rtype:TsrDataType);
|
||||
begin
|
||||
if (pSlot=nil) then Exit;
|
||||
if (pSlot^.current=nil) then
|
||||
begin
|
||||
pSlot^.New(line,rtype); //Unresolve
|
||||
Exit;
|
||||
end;
|
||||
|
||||
pSlot^.current^.PrepType(ord(rtype));
|
||||
end;
|
||||
|
||||
function TEmitFetch.MakeRead(pSlot:PsrRegSlot;rtype:TsrDataType):PsrRegNode;
|
||||
var
|
||||
node:PsrRegNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (pSlot=nil) then Exit;
|
||||
PrepTypeSlot(pSlot,rtype);
|
||||
node:=pSlot^.current;
|
||||
if (rtype<>dtUnknow) and (not CompareType(node^.dtype,rtype)) then
|
||||
begin
|
||||
Result:=BitcastList.FetchRead(rtype,node);
|
||||
end else
|
||||
begin
|
||||
Result:=node;
|
||||
end;
|
||||
if (rtype<>dtUnknow) then
|
||||
begin
|
||||
Result^.Weak:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TEmitFetch.PrepTypeNode(var node:PsrRegNode;rtype:TsrDataType;relax:Boolean=true):Integer;
|
||||
begin
|
||||
Result:=0;
|
||||
if (node=nil) then Exit;
|
||||
if (rtype=dtUnknow) then Exit;
|
||||
|
||||
if is_unprep_type(node^.dtype,rtype,node^.Weak) then
|
||||
begin
|
||||
node^.PrepType(ord(rtype));
|
||||
Inc(Result);
|
||||
end else
|
||||
begin
|
||||
Case relax of
|
||||
True :relax:=CompareType(node^.dtype,rtype);
|
||||
False:relax:=(node^.dtype=rtype);
|
||||
end;
|
||||
if not relax then
|
||||
begin
|
||||
node:=BitcastList.FetchRead(rtype,node);
|
||||
Inc(Result);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TEmitFetch.PrepTypeDst(var node:PsrRegNode;rtype:TsrDataType;relax:Boolean=true):Integer;
|
||||
begin
|
||||
Result:=0;
|
||||
if (node=nil) then Exit;
|
||||
if (rtype=dtUnknow) then Exit;
|
||||
|
||||
if is_unprep_type(node^.dtype,rtype,node^.Weak) then
|
||||
begin
|
||||
node^.PrepType(ord(rtype));
|
||||
Inc(Result);
|
||||
end else
|
||||
begin
|
||||
Case relax of
|
||||
True :relax:=CompareType(node^.dtype,rtype);
|
||||
False:relax:=(node^.dtype=rtype);
|
||||
end;
|
||||
if not relax then
|
||||
begin
|
||||
node:=BitcastList.FetchDstr(rtype,node);
|
||||
Inc(Result);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TEmitFetch.PrepTypeParam(node:POpParamNode;rtype:TsrDataType;relax:Boolean=true):Integer;
|
||||
var
|
||||
pReg:PsrRegNode;
|
||||
begin
|
||||
Result:=0;
|
||||
if (node=nil) then Exit;
|
||||
if (rtype=dtUnknow) then Exit;
|
||||
if node^.Value^.IsType(ntReg) then
|
||||
begin
|
||||
pReg:=node^.AsReg;
|
||||
Result:=PrepTypeNode(pReg,rtype,relax);
|
||||
node^.Value:=pReg;
|
||||
end else
|
||||
begin
|
||||
node^.Value^.PrepType(ord(rtype));
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TEmitFetch.get_vcc0:PsrRegSlot;
|
||||
begin
|
||||
Result:=@RegsStory.VCC[0];
|
||||
end;
|
||||
|
||||
function TEmitFetch.get_vcc1:PsrRegSlot;
|
||||
begin
|
||||
Result:=@RegsStory.VCC[1];
|
||||
end;
|
||||
|
||||
function TEmitFetch.get_m0:PsrRegSlot;
|
||||
begin
|
||||
Result:=@RegsStory.M0;
|
||||
end;
|
||||
|
||||
function TEmitFetch.get_exec0:PsrRegSlot;
|
||||
begin
|
||||
Result:=@RegsStory.EXEC[0];
|
||||
end;
|
||||
|
||||
function TEmitFetch.get_exec1:PsrRegSlot;
|
||||
begin
|
||||
Result:=@RegsStory.EXEC[1];
|
||||
end;
|
||||
|
||||
function TEmitFetch.get_scc:PsrRegSlot;
|
||||
begin
|
||||
Result:=@RegsStory.SCC;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TEmitFetch.get_sdst7(SDST:Byte):PsrRegSlot;
|
||||
begin
|
||||
Result:=RegsStory.get_sdst7(SDST);
|
||||
end;
|
||||
|
||||
function TEmitFetch.get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean;
|
||||
begin
|
||||
Result:=RegsStory.get_sdst7_pair(SDST,dst);
|
||||
end;
|
||||
|
||||
function TEmitFetch.get_ssrc8(SSRC:Byte):PsrRegSlot;
|
||||
begin
|
||||
Result:=RegsStory.get_ssrc8(SSRC);
|
||||
end;
|
||||
|
||||
function TEmitFetch.get_ssrc9(SSRC:Word):PsrRegSlot;
|
||||
begin
|
||||
Result:=RegsStory.get_ssrc9(SSRC);
|
||||
end;
|
||||
|
||||
function TEmitFetch.get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean;
|
||||
begin
|
||||
Result:=RegsStory.get_ssrc9_pair(SSRC,src);
|
||||
end;
|
||||
|
||||
function TEmitFetch.get_vsrc8(VSRC:Byte):PsrRegSlot;
|
||||
begin
|
||||
Result:=RegsStory.get_vsrc8(VSRC);
|
||||
end;
|
||||
|
||||
function TEmitFetch.get_vdst8(VDST:Byte):PsrRegSlot;
|
||||
begin
|
||||
Result:=RegsStory.get_vdst8(VDST);
|
||||
end;
|
||||
|
||||
function TEmitFetch.get_sbase(SBASE,count:Byte;src:PPsrRegSlot):Boolean;
|
||||
begin
|
||||
Result:=RegsStory.get_sbase(SBASE,count,src);
|
||||
end;
|
||||
|
||||
function TEmitFetch.get_srsrc(SRSRC,count:Byte;src:PPsrRegSlot):Boolean;
|
||||
begin
|
||||
Result:=RegsStory.get_srsrc(SRSRC,count,src);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TEmitFetch.get_snapshot:TsrRegsSnapshot;
|
||||
begin
|
||||
Result:=RegsStory.get_snapshot;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TEmitFetch.fetch_ssrc8(SOFFSET:Word;rtype:TsrDataType):PsrRegNode;
|
||||
Var
|
||||
src:PsrRegSlot;
|
||||
pConst:PsrConst;
|
||||
begin
|
||||
if is_const_ssrc8(SOFFSET) then
|
||||
begin
|
||||
pConst:=ConstList.Fetch_ssrc8_const(SOFFSET,0,rtype);
|
||||
Result:=NewReg(pConst);
|
||||
end else
|
||||
begin
|
||||
src:=RegsStory.get_ssrc8(SOFFSET);
|
||||
Result:=MakeRead(src,rtype);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TEmitFetch.fetch_ssrc9(SSRC:Word;rtype:TsrDataType):PsrRegNode;
|
||||
Var
|
||||
src:PsrRegSlot;
|
||||
pConst:PsrConst;
|
||||
begin
|
||||
if is_const_ssrc9(SSRC) then
|
||||
begin
|
||||
pConst:=ConstList.Fetch_ssrc9_const(SSRC,FSPI.INLINE32,rtype);
|
||||
Result:=NewReg(pConst);
|
||||
end else
|
||||
begin
|
||||
src:=RegsStory.get_ssrc9(SSRC);
|
||||
Result:=MakeRead(src,rtype);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TEmitFetch.fetch_ssrc9_pair(SSRC:Word;src:PPsrRegNode;rtype:TsrDataType):Boolean;
|
||||
Var
|
||||
pSlot:array[0..1] of PsrRegSlot;
|
||||
begin
|
||||
if is_const_ssrc9(SSRC) then
|
||||
begin
|
||||
src[0]:=NewReg(ConstList.Fetch_ssrc9_const(SSRC,FSPI.INLINE32,rtype));
|
||||
src[1]:=NewReg(ConstList.Fetch(dtUnknow,0));
|
||||
Result:=True;
|
||||
end else
|
||||
begin
|
||||
pSlot[0]:=nil;
|
||||
pSlot[1]:=nil;
|
||||
Result:=RegsStory.get_ssrc9_pair(SSRC,pSlot);
|
||||
if not Result then Exit;
|
||||
src[0]:=MakeRead(pSlot[0],rtype);
|
||||
src[1]:=MakeRead(pSlot[1],rtype);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TEmitFetch.fetch_vsrc8(VSRC:Word;rtype:TsrDataType):PsrRegNode;
|
||||
var
|
||||
src:PsrRegSlot;
|
||||
begin
|
||||
src:=RegsStory.get_vsrc8(VSRC);
|
||||
Result:=MakeRead(src,rtype);
|
||||
end;
|
||||
|
||||
function TEmitFetch.fetch_vdst8(VDST:Word;rtype:TsrDataType):PsrRegNode;
|
||||
var
|
||||
src:PsrRegSlot;
|
||||
begin
|
||||
src:=RegsStory.get_vdst8(VDST);
|
||||
Result:=MakeRead(src,rtype);
|
||||
end;
|
||||
|
||||
procedure TEmitFetch.fetch_vsrc8_vec2h(VSRC:Word;var dst0,dst1:PsrRegNode);
|
||||
var
|
||||
pSlot:PsrRegSlot;
|
||||
dst:PsrRegNode;
|
||||
begin
|
||||
pSlot:=RegsStory.get_vsrc8(VSRC);
|
||||
|
||||
dst:=MakeRead(pSlot,dtVec2h);
|
||||
|
||||
dst0:=NewReg(dtHalf16);
|
||||
dst1:=NewReg(dtHalf16);;
|
||||
|
||||
OpExtract(line,dst0,dst,0);
|
||||
OpExtract(line,dst1,dst,1);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
procedure TEmitFetch.OpCmpV(OpId:DWORD;dst:PsrRegSlot;src0,src1:PsrRegNode);
|
||||
Var
|
||||
tmp:PsrRegNode;
|
||||
exc:PsrRegNode;
|
||||
begin
|
||||
tmp:=NewReg(dtBool);
|
||||
|
||||
_Op2(line,OpId,tmp,src0,src1);
|
||||
|
||||
exc:=MakeRead(get_exec0,dtBool);
|
||||
OpLogicalAnd(dst,tmp,exc);
|
||||
end;
|
||||
|
||||
procedure TEmitFetch.OpCmpS(OpId:DWORD;dst:PsrRegSlot;src0,src1:PsrRegNode);
|
||||
begin
|
||||
Op2(OpId,dtBool,dst,src0,src1);
|
||||
end;
|
||||
|
||||
procedure TEmitFetch.OpConvFloatToHalf2(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
||||
var
|
||||
rsl:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
rsl[0]:=OpFToF(src0,dtHalf16);
|
||||
rsl[1]:=OpFToF(src1,dtHalf16);
|
||||
|
||||
dst^.New(line,dtVec2h);
|
||||
|
||||
OpMakeCon(line,dst^.current,@rsl);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TEmitFetch.AddInput(dst:PsrRegSlot;rtype:TsrDataType;itype:TpsslInputType;id:Byte=0):PsrRegNode;
|
||||
var
|
||||
i:PsrInput;
|
||||
v:PsrVariable;
|
||||
r:PsrRegNode;
|
||||
begin
|
||||
i:=InputList.Fetch(rtype,itype,id);
|
||||
|
||||
v:=i^.pVar;
|
||||
r:=i^.pReg;
|
||||
|
||||
if (r=nil) then
|
||||
begin
|
||||
r:=dst^.New(line,rtype);
|
||||
i^.pReg :=r;
|
||||
OpLoad(init_line,r,v); //one in any scope
|
||||
end else
|
||||
if (dst^.current<>r) then
|
||||
begin
|
||||
MakeCopy(dst,r);
|
||||
end;
|
||||
|
||||
Result:=r;
|
||||
end;
|
||||
|
||||
function TEmitFetch.AddAncillary(dst:PsrRegSlot):PsrRegNode;
|
||||
var
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
src[0]:=NewReg_q(dtUInt32,0); //vPrimType
|
||||
src[1]:=AddInput(@RegsStory.FUnattach,dtUInt32,itSampleId);
|
||||
src[2]:=AddInput(@RegsStory.FUnattach,dtUInt32,itLayer);
|
||||
|
||||
OpPackAnc(dst,src[0],src[1],src[2]);
|
||||
|
||||
//Render target array index[26:16], BuiltIn.Layer
|
||||
//Iterated sample number[11:8], BuiltIn.SampleId
|
||||
//Primitive type[1:0] 0..3
|
||||
|
||||
//IL_REGTYPE_PRIMTYPE vPrimType
|
||||
//The first component has sign bit = 1, this is a point. Values in other bits are undefined.
|
||||
//The second component has sign bit = 1, this is a line. Values in other bits are undefined.
|
||||
|
||||
//PID ISID RTAI
|
||||
//01|234567|89AB|CDEF|0123456789A|
|
||||
//00|000000| |0000| |
|
||||
|
||||
Result:=dst^.current;
|
||||
end;
|
||||
|
||||
function TEmitFetch.AddVertLayout(pLayout:PsrDataLayout;rtype:TsrDataType):PsrRegNode;
|
||||
var
|
||||
i:PsrVertLayout;
|
||||
v:PsrVariable;
|
||||
dst:PsrRegNode;
|
||||
begin
|
||||
i:=VertLayoutList.Fetch(pLayout,rtype);
|
||||
v:=i^.pVar;
|
||||
dst:=i^.pReg;
|
||||
if (dst=nil) then
|
||||
begin
|
||||
dst:=NewReg(rtype);
|
||||
i^.pReg:=dst;
|
||||
OpLoad(init_line,dst,v); //one in any scope
|
||||
end;
|
||||
Result:=dst;
|
||||
end;
|
||||
|
||||
function TEmitFetch.AddFragLayout(itype:TpsslInputType;rtype:TsrDataType;location:DWORD):PsrRegNode;
|
||||
var
|
||||
i:PsrFragLayout;
|
||||
v:PsrVariable;
|
||||
dst:PsrRegNode;
|
||||
begin
|
||||
i:=FragLayoutList.Fetch(itype,location,rtype);
|
||||
v:=i^.pVar;
|
||||
dst:=i^.pReg;
|
||||
if (dst=nil) then
|
||||
begin
|
||||
dst:=NewReg(rtype);
|
||||
i^.pReg:=dst;
|
||||
OpLoad(init_line,dst,v); //one in any scope
|
||||
end;
|
||||
Result:=dst;
|
||||
end;
|
||||
|
||||
function TEmitFetch.FetchLoad(pChain:PsrChain;rtype:TsrDataType):PsrRegNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (pChain=nil) then Exit;
|
||||
|
||||
Result:=NewReg(rtype);
|
||||
|
||||
pChain^.FetchLoad(line,Result);
|
||||
end;
|
||||
|
||||
Procedure TEmitFetch.FetchStore(pChain:PsrChain;src:PsrRegNode);
|
||||
begin
|
||||
if (pChain=nil) or (src=nil) then Exit;
|
||||
|
||||
pChain^.FetchStore(line,src);
|
||||
end;
|
||||
|
||||
procedure TEmitFetch.AddUserdata(dst:PsrRegSlot;offset_dw:Byte);
|
||||
var
|
||||
lvl_0:TsrChainLvl_0;
|
||||
pLayout:PsrDataLayout;
|
||||
pChain:PsrChain;
|
||||
pReg:PsrRegNode;
|
||||
begin
|
||||
pLayout:=DataLayoutList.pRoot;
|
||||
lvl_0.offset:=offset_dw*4;
|
||||
lvl_0.size :=4;
|
||||
pChain:=pLayout^.Fetch(@lvl_0,nil);
|
||||
pReg:=FetchLoad(pChain,dtUnknow);
|
||||
MakeCopy(dst,pReg);
|
||||
end;
|
||||
|
||||
function TEmitFetch.FetchChain(grp:PsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrRegNode;
|
||||
var
|
||||
pChain:PsrChain;
|
||||
begin
|
||||
pChain:=grp^.Fetch(lvl_0,lvl_1);
|
||||
Result:=FetchLoad(pChain,dtUnknow);
|
||||
end;
|
||||
|
||||
function TEmitFetch.MakeChain(pSlot:PsrRegSlot;grp:PsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrRegNode;
|
||||
var
|
||||
pChain:PsrChain;
|
||||
pReg:PsrRegNode;
|
||||
begin
|
||||
pChain:=grp^.Fetch(lvl_0,lvl_1);
|
||||
pReg:=FetchLoad(pChain,dtUnknow);
|
||||
MakeCopy(pSlot,pReg);
|
||||
Result:=pSlot^.current;
|
||||
end;
|
||||
|
||||
Procedure TEmitFetch.AddVecInput(dst:PsrRegSlot;vtype,rtype:TsrDataType;itype:TpsslInputType;id:Byte);
|
||||
var
|
||||
rsl:PsrRegNode;
|
||||
begin
|
||||
rsl:=AddInput(@RegsStory.FUnattach,vtype,itype,0);
|
||||
OpExtract(init_line,dst^.New(line,rtype),rsl,id);
|
||||
end;
|
||||
|
||||
////
|
||||
|
||||
function TEmitFetch.FetchUniform(src:PsrDataLayout;pType:PsrType):PsrNode;
|
||||
var
|
||||
u:PsrUniform;
|
||||
v:PsrVariable;
|
||||
r:PsrRegUniform;
|
||||
begin
|
||||
u:=UniformList.Fetch(src,pType);
|
||||
v:=u^.pVar;
|
||||
r:=u^.pReg;
|
||||
if (r^.pLine=nil) then
|
||||
begin
|
||||
OpLoad(init_line,pType,r,v); //one in any scope
|
||||
end;
|
||||
Result:=r;
|
||||
end;
|
||||
|
||||
function TEmitFetch.FetchImage(src:PsrDataLayout;dtype:TsrDataType;info:TsrTypeImageInfo):PsrNode;
|
||||
var
|
||||
pType:PsrType;
|
||||
begin
|
||||
pType:=TypeList.Fetch(dtype);
|
||||
pType:=TypeList.FetchImage(pType,info);
|
||||
Result:=FetchUniform(src,pType);
|
||||
end;
|
||||
|
||||
function TEmitFetch.FetchSampler(src:PsrDataLayout):PsrNode;
|
||||
var
|
||||
pType:PsrType;
|
||||
begin
|
||||
pType:=TypeList.Fetch(dtTypeSampler);
|
||||
Result:=FetchUniform(src,pType);
|
||||
end;
|
||||
|
||||
function TEmitFetch.FetchOutput(etype:TpsslExportType;rtype:TsrDataType):PsrVariable;
|
||||
var
|
||||
o:PsrOutput;
|
||||
begin
|
||||
o:=OutputList.Fetch(etype,rtype);
|
||||
Result:=o^.pVar;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -10,24 +10,24 @@ uses
|
|||
si_ci_vi_merged_enum,
|
||||
ps4_shader,
|
||||
ps4_pssl,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srConst,
|
||||
srNode,
|
||||
srType,
|
||||
srReg,
|
||||
srLayout,
|
||||
srOp,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
emit_fetch;
|
||||
|
||||
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);
|
||||
TEmit_MIMG=class(TEmitFetch)
|
||||
procedure emit_MIMG;
|
||||
procedure DistribDmask(dst:PsrRegNode;telem:TsrDataType);
|
||||
function GatherDmask(telem:TsrDataType):PsrRegNode;
|
||||
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:PsrNode;info:PsrImageInfo);
|
||||
procedure emit_image_load(Tgrp:PsrNode;info:PsrImageInfo);
|
||||
procedure emit_image_store(Tgrp:PsrNode;info:PsrImageInfo);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
@ -373,7 +373,7 @@ begin
|
|||
Result.tinfo.Format :=GetImageFormat(PT);
|
||||
end;
|
||||
|
||||
procedure TEmit_MIMG._DistribDmask(dst:PsrRegNode;telem:TsrDataType); //result
|
||||
procedure TEmit_MIMG.DistribDmask(dst:PsrRegNode;telem:TsrDataType); //result
|
||||
var
|
||||
pSlot:PsrRegSlot;
|
||||
i,d:Byte;
|
||||
|
@ -382,14 +382,40 @@ begin
|
|||
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);
|
||||
pSlot:=get_vdst8(FSPI.MIMG.VDATA+d);
|
||||
Inc(d);
|
||||
Assert(pSlot<>nil);
|
||||
dst^.mark_read;
|
||||
emit_OpCompExtract(line,pSlot^.New(line,telem),dst,i);
|
||||
OpExtract(line,pSlot^.New(line,telem),dst,i);
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TEmit_MIMG._GatherCoord_f(var offset:DWORD;dim_id:Byte):PsrRegNode; //src
|
||||
function TEmit_MIMG.GatherDmask(telem:TsrDataType):PsrRegNode;
|
||||
var
|
||||
src:array[0..3] of PsrRegNode;
|
||||
i,d,m:Byte;
|
||||
begin
|
||||
d:=0;
|
||||
For i:=0 to 3 do
|
||||
if Byte(FSPI.MIMG.DMASK).TestBit(i) then
|
||||
begin
|
||||
src[i]:=fetch_vsrc8(FSPI.MIMG.VDATA+d,telem);
|
||||
Inc(d);
|
||||
m:=i;
|
||||
end else
|
||||
begin
|
||||
src[i]:=nil;
|
||||
end;
|
||||
|
||||
//Result:=telem.AsVector(4);
|
||||
For i:=0 to m do
|
||||
begin
|
||||
Assert(src[i]<>nil,'TODO: zero or prev value?');
|
||||
end;
|
||||
|
||||
Result:=OpMakeVec(line,telem.AsVector(m+1),@src);
|
||||
end;
|
||||
|
||||
Function TEmit_MIMG.GatherCoord_f(var offset:DWORD;dim_id:Byte):PsrRegNode; //src
|
||||
var
|
||||
src:array[0..3] of PsrRegNode;
|
||||
i,count:Byte;
|
||||
|
@ -416,8 +442,7 @@ begin
|
|||
src[2]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+2,dtFloat32); //face
|
||||
end;
|
||||
|
||||
Result:=emit_OpMakeCube(line,GetVecType(dtFloat32,count),count,@src);
|
||||
Result^.mark_read;
|
||||
Result:=OpMakeCub(line,TsrDataType(dtFloat32).AsVector(count),@src);
|
||||
|
||||
end else
|
||||
begin
|
||||
|
@ -432,8 +457,7 @@ begin
|
|||
Result:=src[0];
|
||||
end else
|
||||
begin
|
||||
Result:=emit_OpMakeVec(line,GetVecType(dtFloat32,count),count,@src);
|
||||
Result^.mark_read;
|
||||
Result:=OpMakeVec(line,TsrDataType(dtFloat32).AsVector(count),@src);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
@ -441,7 +465,7 @@ begin
|
|||
offset:=offset+count;
|
||||
end;
|
||||
|
||||
Function TEmit_MIMG._GatherCoord_u(var offset:DWORD;dim_id:Byte):PsrRegNode; //src
|
||||
Function TEmit_MIMG.GatherCoord_u(var offset:DWORD;dim_id:Byte):PsrRegNode; //src
|
||||
var
|
||||
src:array[0..3] of PsrRegNode;
|
||||
i,count:Byte;
|
||||
|
@ -468,8 +492,7 @@ begin
|
|||
src[2]:=fetch_vsrc8(FSPI.MIMG.VADDR+offset+2,dtInt32); //face
|
||||
end;
|
||||
|
||||
Result:=emit_OpMakeCube(line,GetVecType(dtInt32,count),count,@src);
|
||||
Result^.mark_read;
|
||||
Result:=OpMakeCub(line,TsrDataType(dtInt32).AsVector(count),@src);
|
||||
|
||||
end else
|
||||
begin
|
||||
|
@ -484,8 +507,7 @@ begin
|
|||
Result:=src[0];
|
||||
end else
|
||||
begin
|
||||
Result:=emit_OpMakeVec(line,GetVecType(dtInt32,count),count,@src);
|
||||
Result^.mark_read;
|
||||
Result:=OpMakeVec(line,TsrDataType(dtInt32).AsVector(count),@src);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
@ -493,7 +515,7 @@ begin
|
|||
offset:=offset+count;
|
||||
end;
|
||||
|
||||
Function TEmit_MIMG._Gather_packed_offset(var offset:DWORD;dim:Byte):PsrRegNode;
|
||||
Function TEmit_MIMG.Gather_packed_offset(var offset:DWORD;dim:Byte):PsrRegNode;
|
||||
var
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
|
@ -503,22 +525,21 @@ begin
|
|||
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);
|
||||
1:Result:=OpPackOfs(line,dtInt32,dim,src);
|
||||
2:Result:=OpPackOfs(line,dtVec2i,dim,src);
|
||||
3:Result:=OpPackOfs(line,dtVec3i,dim,src);
|
||||
else
|
||||
Assert(False);
|
||||
end;
|
||||
|
||||
Result^.mark_read;
|
||||
end;
|
||||
|
||||
procedure TEmit_MIMG._emit_image_sample(Tgrp:PsrRegNode;info:PsrImageInfo);
|
||||
procedure TEmit_MIMG.emit_image_sample(Tgrp:PsrNode;info:PsrImageInfo);
|
||||
var
|
||||
src:array[0..3] of PsrRegSlot;
|
||||
|
||||
pLayout:PsrDataLayout;
|
||||
Sgrp:PsrRegNode;
|
||||
Sgrp:PsrNode;
|
||||
|
||||
dst,cmb,coord,lod,offset:PsrRegNode;
|
||||
|
||||
|
@ -527,72 +548,71 @@ var
|
|||
node:PSpirvOp;
|
||||
|
||||
begin
|
||||
if not FRegsStory.get_srsrc(FSPI.MIMG.SSAMP,4,@src) then Assert(false);
|
||||
if not 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;
|
||||
cmb:=OpSampledImage(line,Tgrp,Sgrp,info^.dtype,info^.tinfo);
|
||||
|
||||
dst:=NewReg(GetVecType(info^.dtype,4));
|
||||
dst:=NewReg(info^.dtype.AsVector(4));
|
||||
|
||||
roffset:=0;
|
||||
|
||||
Case FSPI.MIMG.OP of
|
||||
IMAGE_SAMPLE:
|
||||
begin
|
||||
coord:=_GatherCoord_f(roffset,info^.tinfo.Dim);
|
||||
coord:=GatherCoord_f(roffset,info^.tinfo.Dim);
|
||||
|
||||
if (FExecutionModel=ExecutionModel.Fragment) then
|
||||
begin
|
||||
node:=emit_OpImageSampleImplicitLod(line,dst,cmb,coord);
|
||||
node:=OpImageSampleImplicitLod(line,cmb,dst,coord);
|
||||
end else
|
||||
begin
|
||||
node:=emit_OpImageSampleExplicitLod(line,dst,cmb,coord);
|
||||
node:=OpImageSampleExplicitLod(line,cmb,dst,coord);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
IMAGE_SAMPLE_LZ:
|
||||
begin
|
||||
coord:=_GatherCoord_f(roffset,info^.tinfo.Dim);
|
||||
coord:=GatherCoord_f(roffset,info^.tinfo.Dim);
|
||||
|
||||
node:=emit_OpImageSampleExplicitLod(line,dst,cmb,coord);
|
||||
node:=OpImageSampleExplicitLod(line,cmb,dst,coord);
|
||||
|
||||
node^.AddLiteral(ImageOperands.Lod,'Lod');
|
||||
|
||||
//0
|
||||
lod:=FetchReg(FConsts.Fetchf(dtFloat32,0));
|
||||
node^.AddParam(ntReg,lod);
|
||||
lod:=NewReg_s(dtFloat32,0);
|
||||
node^.AddParam(lod);
|
||||
end;
|
||||
|
||||
IMAGE_SAMPLE_LZ_O:
|
||||
begin
|
||||
offset:=_Gather_packed_offset(roffset,GetDimCount(info^.tinfo.Dim));
|
||||
offset:=Gather_packed_offset(roffset,GetDimCount(info^.tinfo.Dim));
|
||||
|
||||
coord:=_GatherCoord_f(roffset,info^.tinfo.Dim);
|
||||
coord:=GatherCoord_f(roffset,info^.tinfo.Dim);
|
||||
|
||||
node:=emit_OpImageSampleExplicitLod(line,dst,cmb,coord);
|
||||
node:=OpImageSampleExplicitLod(line,cmb,dst,coord);
|
||||
|
||||
node^.AddLiteral(ImageOperands.Lod or ImageOperands.ConstOffset,'Lod|ConstOffset');
|
||||
|
||||
//0
|
||||
lod:=FetchReg(FConsts.Fetchf(dtFloat32,0));
|
||||
node^.AddParam(ntReg,lod);
|
||||
lod:=NewReg_s(dtFloat32,0);
|
||||
node^.AddParam(lod);
|
||||
|
||||
//1
|
||||
node^.AddParam(ntReg,offset);
|
||||
node^.AddParam(offset);
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
_DistribDmask(dst,info^.dtype);
|
||||
DistribDmask(dst,info^.dtype);
|
||||
end;
|
||||
|
||||
procedure TEmit_MIMG._emit_image_load(Tgrp:PsrRegNode;info:PsrImageInfo);
|
||||
procedure TEmit_MIMG.emit_image_load(Tgrp:PsrNode;info:PsrImageInfo);
|
||||
var
|
||||
dst,coord,lod,smp:PsrRegNode;
|
||||
|
||||
|
@ -601,15 +621,15 @@ var
|
|||
node:PSpirvOp;
|
||||
begin
|
||||
|
||||
dst:=NewReg(GetVecType(info^.dtype,4));
|
||||
dst:=NewReg(info^.dtype.AsVector(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);
|
||||
coord:=GatherCoord_u(roffset,info^.tinfo.Dim);
|
||||
node:=OpImageFetch(line,Tgrp,dst,coord);
|
||||
|
||||
if (info^.tinfo.MS<>0) then //fragid T# 2D MSAA
|
||||
begin
|
||||
|
@ -617,35 +637,79 @@ begin
|
|||
Inc(roffset);
|
||||
|
||||
node^.AddLiteral(ImageOperands.Sample,'Sample');
|
||||
node^.AddParam(ntReg,smp);
|
||||
node^.AddParam(smp);
|
||||
end;
|
||||
end;
|
||||
IMAGE_LOAD_MIP: //All except MSAA
|
||||
begin
|
||||
coord:=_GatherCoord_u(roffset,info^.tinfo.Dim);
|
||||
node:=emit_OpImageFetch(line,Tgrp,dst,coord);
|
||||
coord:=GatherCoord_u(roffset,info^.tinfo.Dim);
|
||||
node:=OpImageFetch(line,Tgrp,dst,coord);
|
||||
|
||||
lod:=fetch_vsrc8(FSPI.MIMG.VADDR+roffset,dtUint32);
|
||||
Inc(roffset);
|
||||
|
||||
node^.AddLiteral(ImageOperands.Lod,'Lod');
|
||||
node^.AddParam(ntReg,lod);
|
||||
node^.AddParam(lod);
|
||||
end;
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
_DistribDmask(dst,info^.dtype);
|
||||
DistribDmask(dst,info^.dtype);
|
||||
end;
|
||||
|
||||
procedure TEmit_MIMG._emit_MIMG;
|
||||
procedure TEmit_MIMG.emit_image_store(Tgrp:PsrNode;info:PsrImageInfo);
|
||||
var
|
||||
dst,coord,lod,smp:PsrRegNode;
|
||||
|
||||
roffset:DWORD;
|
||||
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
dst:=GatherDmask(info^.dtype);
|
||||
|
||||
roffset:=0;
|
||||
|
||||
Case FSPI.MIMG.OP of
|
||||
IMAGE_STORE:
|
||||
begin
|
||||
coord:=GatherCoord_u(roffset,info^.tinfo.Dim);
|
||||
node:=OpImageWrite(line,Tgrp,coord,dst);
|
||||
|
||||
if (info^.tinfo.MS<>0) then //fragid T# 2D MSAA
|
||||
begin
|
||||
smp:=fetch_vsrc8(FSPI.MIMG.VADDR+roffset,dtUint32);
|
||||
Inc(roffset);
|
||||
|
||||
node^.AddLiteral(ImageOperands.Sample,'Sample');
|
||||
node^.AddParam(smp);
|
||||
end;
|
||||
end;
|
||||
IMAGE_STORE_MIP: //All except MSAA
|
||||
begin
|
||||
coord:=GatherCoord_u(roffset,info^.tinfo.Dim);
|
||||
node:=OpImageWrite(line,Tgrp,coord,dst);
|
||||
|
||||
lod:=fetch_vsrc8(FSPI.MIMG.VADDR+roffset,dtUint32);
|
||||
Inc(roffset);
|
||||
|
||||
node^.AddLiteral(ImageOperands.Lod,'Lod');
|
||||
node^.AddParam(lod);
|
||||
end;
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure TEmit_MIMG.emit_MIMG;
|
||||
var
|
||||
src:array[0..7] of PsrRegSlot;
|
||||
|
||||
pLayout:PsrDataLayout;
|
||||
info:TsrImageInfo;
|
||||
|
||||
Tgrp:PsrRegNode;
|
||||
Tgrp:PsrNode;
|
||||
|
||||
begin
|
||||
|
||||
|
@ -656,17 +720,13 @@ begin
|
|||
Case FSPI.MIMG.R128 of
|
||||
0:
|
||||
begin
|
||||
if not FRegsStory.get_srsrc(FSPI.MIMG.SRSRC,8,@src) then Assert(false);
|
||||
if not 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);
|
||||
if not get_srsrc(FSPI.MIMG.SRSRC,4,@src) then Assert(false);
|
||||
pLayout:=GroupingSharp(src,rtTSharp8);
|
||||
//print_tsharp8(pLayout^.pData);
|
||||
//Tgrp:=GroupingSharp(@src,rtTSharp4);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -678,7 +738,7 @@ begin
|
|||
info.tinfo.Sampled:=1;
|
||||
Tgrp:=FetchImage(pLayout,info.dtype,info.tinfo);
|
||||
|
||||
_emit_image_sample(Tgrp,@info);
|
||||
emit_image_sample(Tgrp,@info);
|
||||
end;
|
||||
|
||||
IMAGE_LOAD..IMAGE_LOAD_MIP_PCK_SGN: //loaded
|
||||
|
@ -686,10 +746,16 @@ begin
|
|||
info.tinfo.Sampled:=1;
|
||||
Tgrp:=FetchImage(pLayout,info.dtype,info.tinfo);
|
||||
|
||||
_emit_image_load(Tgrp,@info);
|
||||
emit_image_load(Tgrp,@info);
|
||||
end;
|
||||
|
||||
IMAGE_STORE:; //TODO
|
||||
IMAGE_STORE..IMAGE_STORE_MIP_PCK: //stored
|
||||
begin
|
||||
info.tinfo.Sampled:=2;
|
||||
Tgrp:=FetchImage(pLayout,info.dtype,info.tinfo);
|
||||
|
||||
emit_image_store(Tgrp,@info);
|
||||
end;
|
||||
|
||||
else
|
||||
Assert(false,'MIMG?'+IntToStr(FSPI.MIMG.OP));
|
||||
|
|
|
@ -9,33 +9,32 @@ uses
|
|||
ps4_pssl,
|
||||
srReg,
|
||||
srLayout,
|
||||
SprvEmit,
|
||||
emit_fetch,
|
||||
srVBufInfo,
|
||||
emit_vbuf_load,
|
||||
emit_vbuf_store,
|
||||
emit_op;
|
||||
emit_vbuf_store;
|
||||
|
||||
type
|
||||
TEmit_MTBUF=object(TEmitOp)
|
||||
procedure _emit_MTBUF;
|
||||
procedure _emit_TBUFFER_LOAD_FORMAT(count:Byte);
|
||||
procedure _emit_TBUFFER_STORE_FORMAT(count:Byte);
|
||||
TEmit_MTBUF=class(TEmitFetch)
|
||||
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);
|
||||
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);
|
||||
if not get_srsrc(FSPI.MTBUF.SRSRC,4,@src) then Assert(false);
|
||||
|
||||
grp:=GroupingSharp(@src,rtVSharp4);
|
||||
|
||||
TEmit_vbuf_load(Self).buf_load(
|
||||
TEmit_vbuf_load(TObject(Self)).buf_load(
|
||||
Buf_info(grp,
|
||||
dst_sel_identity,
|
||||
FSPI.MTBUF.DFMT,
|
||||
|
@ -45,18 +44,18 @@ begin
|
|||
|
||||
end;
|
||||
|
||||
procedure TEmit_MTBUF._emit_TBUFFER_STORE_FORMAT(count:Byte);
|
||||
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);
|
||||
if not get_srsrc(FSPI.MTBUF.SRSRC,4,@src) then Assert(false);
|
||||
|
||||
grp:=GroupingSharp(@src,rtVSharp4);
|
||||
|
||||
TEmit_vbuf_store(Self).buf_store(
|
||||
TEmit_vbuf_store(TObject(Self)).buf_store(
|
||||
Buf_info(grp,
|
||||
dst_sel_identity,
|
||||
FSPI.MTBUF.DFMT,
|
||||
|
@ -66,19 +65,19 @@ begin
|
|||
|
||||
end;
|
||||
|
||||
procedure TEmit_MTBUF._emit_MTBUF;
|
||||
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_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);
|
||||
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.
|
||||
|
|
|
@ -8,48 +8,53 @@ uses
|
|||
sysutils,
|
||||
ps4_shader,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srConfig,
|
||||
srType,
|
||||
srReg,
|
||||
srLayout,
|
||||
srInput,
|
||||
spirv,
|
||||
SprvEmit,
|
||||
emit_fetch,
|
||||
srVBufInfo,
|
||||
emit_vbuf_load,
|
||||
emit_vbuf_store,
|
||||
emit_op;
|
||||
emit_vbuf_store;
|
||||
|
||||
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);
|
||||
TEmit_MUBUF=class(TEmitFetch)
|
||||
procedure emit_MUBUF;
|
||||
procedure make_load_zero(dst:PsrRegSlot;dtype:TsrDataType);
|
||||
procedure make_load_one(dst:PsrRegSlot;dtype:TsrDataType);
|
||||
procedure make_load_comp(dst:PsrRegSlot;dtype:TsrDataType;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);
|
||||
procedure TEmit_MUBUF.make_load_zero(dst:PsrRegSlot;dtype:TsrDataType);
|
||||
begin
|
||||
SetConst(dst,FConsts.Fetchi(dtFloat32,0));
|
||||
SetConst_q(dst,dtype,0);
|
||||
end;
|
||||
|
||||
procedure TEmit_MUBUF._make_load_one(dst:PsrRegSlot);
|
||||
procedure TEmit_MUBUF.make_load_one(dst:PsrRegSlot;dtype:TsrDataType);
|
||||
begin
|
||||
SetConst(dst,FConsts.Fetchf(dtFloat32,1));
|
||||
if (dtype=dtFloat32) then
|
||||
begin
|
||||
SetConst_s(dst,dtype,1);
|
||||
end else
|
||||
begin
|
||||
SetConst_i(dst,dtype,1);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_MUBUF._make_load_comp(dst:PsrRegSlot;rsl:PsrRegNode;i:Byte);
|
||||
procedure TEmit_MUBUF.make_load_comp(dst:PsrRegSlot;dtype:TsrDataType;rsl:PsrRegNode;i:Byte);
|
||||
begin
|
||||
dst^.New(line,dtFloat32);
|
||||
rsl^.mark_read;
|
||||
emit_OpCompExtract(line,dst^.current,rsl,i);
|
||||
dst^.New(line,dtype);
|
||||
OpExtract(line,dst^.current,rsl,i);
|
||||
end;
|
||||
|
||||
function TEmit_MUBUF._emit_BUFFER_LOAD_VA(src:PPsrRegSlot;count:Byte):Boolean;
|
||||
function TEmit_MUBUF.emit_BUFFER_LOAD_VA(src:PPsrRegSlot;count:Byte):Boolean;
|
||||
var
|
||||
dst:PsrRegSlot;
|
||||
|
||||
|
@ -61,59 +66,69 @@ var
|
|||
|
||||
inp_idx:PsrInput;
|
||||
|
||||
dsel:Tdst_sel;
|
||||
info:TBuf_info;
|
||||
elem_res:TsrDataType;
|
||||
elem_vec:TsrDataType;
|
||||
|
||||
i,d,elem_count:Byte;
|
||||
|
||||
begin
|
||||
Result:=False;
|
||||
|
||||
idx:=FRegsStory.get_vsrc8(FSPI.MUBUF.VADDR+0)^.current;
|
||||
idx:=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
|
||||
if (inp_idx^.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);
|
||||
info:=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);
|
||||
|
||||
elem_res:=info.GetResultType;
|
||||
elem_vec:=elem_res.AsVector(info.GetElemCount);
|
||||
|
||||
rsl:=AddVertLayout(grp,elem_vec);
|
||||
|
||||
elem_count:=GetElemCount(PV^.dfmt);
|
||||
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.MUBUF.VDATA+i);
|
||||
dst:=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
|
||||
Case info.dsel[i] of
|
||||
0:begin //0
|
||||
_make_load_zero(dst);
|
||||
make_load_zero(dst,elem_res);
|
||||
end;
|
||||
1:begin //1
|
||||
_make_load_one(dst);
|
||||
make_load_one(dst,elem_res);
|
||||
end;
|
||||
4..7:
|
||||
begin //RGBA
|
||||
d:=dsel[i]-4;
|
||||
d:=info.dsel[i]-4;
|
||||
|
||||
if (d<elem_count) then
|
||||
begin
|
||||
_make_load_comp(dst,rsl,d);
|
||||
make_load_comp(dst,elem_res,rsl,d);
|
||||
end else
|
||||
begin //as zero
|
||||
_make_load_zero(dst);
|
||||
make_load_zero(dst,elem_res);
|
||||
end;
|
||||
|
||||
end;
|
||||
else
|
||||
begin //as zero
|
||||
_make_load_zero(dst);
|
||||
make_load_zero(dst,elem_res);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -124,32 +139,31 @@ begin
|
|||
|
||||
end;
|
||||
|
||||
procedure TEmit_MUBUF._emit_BUFFER_LOAD_FORMAT(count:Byte);
|
||||
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 not get_srsrc(FSPI.MUBUF.SRSRC,4,@src) then Assert(false);
|
||||
|
||||
if FUseVertexInput then
|
||||
if Config.UseVertexInput 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;
|
||||
if emit_BUFFER_LOAD_VA(@src,count) then Exit;
|
||||
end;
|
||||
|
||||
grp:=GroupingSharp(@src,rtVSharp4);
|
||||
PV:=grp^.pData;
|
||||
|
||||
TEmit_vbuf_load(Self).buf_load(
|
||||
TEmit_vbuf_load(TObject(Self)).buf_load(
|
||||
Buf_info(grp,
|
||||
dst_sel(PV^.dst_sel_x,
|
||||
PV^.dst_sel_y,
|
||||
|
@ -162,7 +176,7 @@ begin
|
|||
|
||||
end;
|
||||
|
||||
procedure TEmit_MUBUF._emit_BUFFER_STORE_FORMAT(count:Byte);
|
||||
procedure TEmit_MUBUF.emit_BUFFER_STORE_FORMAT(count:Byte);
|
||||
var
|
||||
src:array[0..3] of PsrRegSlot;
|
||||
|
||||
|
@ -172,12 +186,12 @@ var
|
|||
begin
|
||||
Assert(FSPI.MUBUF.LDS=0,'FSPI.MUBUF.LDS');
|
||||
|
||||
if not FRegsStory.get_srsrc(FSPI.MUBUF.SRSRC,4,@src) then Assert(false);
|
||||
if not get_srsrc(FSPI.MUBUF.SRSRC,4,@src) then Assert(false);
|
||||
|
||||
grp:=GroupingSharp(@src,rtVSharp4);
|
||||
PV:=grp^.pData;
|
||||
|
||||
TEmit_vbuf_store(Self).buf_store(
|
||||
TEmit_vbuf_store(TObject(Self)).buf_store(
|
||||
Buf_info(grp,
|
||||
dst_sel(PV^.dst_sel_x,
|
||||
PV^.dst_sel_y,
|
||||
|
@ -190,42 +204,18 @@ begin
|
|||
|
||||
end;
|
||||
|
||||
procedure TEmit_MUBUF._emit_MUBUF;
|
||||
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_LOAD_FORMAT_X : emit_BUFFER_LOAD_FORMAT(1);
|
||||
BUFFER_LOAD_FORMAT_XY : emit_BUFFER_LOAD_FORMAT(2);
|
||||
BUFFER_LOAD_FORMAT_XYZ : emit_BUFFER_LOAD_FORMAT(3);
|
||||
BUFFER_LOAD_FORMAT_XYZW : emit_BUFFER_LOAD_FORMAT(4);
|
||||
|
||||
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;
|
||||
BUFFER_STORE_FORMAT_X : emit_BUFFER_STORE_FORMAT(1);
|
||||
BUFFER_STORE_FORMAT_XY : emit_BUFFER_STORE_FORMAT(2);
|
||||
BUFFER_STORE_FORMAT_XYZ : emit_BUFFER_STORE_FORMAT(3);
|
||||
BUFFER_STORE_FORMAT_XYZW: emit_BUFFER_STORE_FORMAT(4);
|
||||
|
||||
else
|
||||
Assert(false,'MUBUF?'+IntToStr(FSPI.MUBUF.OP));
|
||||
|
|
1935
spirv/emit_op.pas
1935
spirv/emit_op.pas
File diff suppressed because it is too large
Load Diff
1140
spirv/emit_post.pas
1140
spirv/emit_post.pas
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -7,32 +7,27 @@ interface
|
|||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
srNodes,
|
||||
srNode,
|
||||
srType,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
srCap,
|
||||
srRefId,
|
||||
Half16,
|
||||
SprvEmit;
|
||||
srCapability,
|
||||
emit_fetch;
|
||||
|
||||
type
|
||||
TSprvEmit_print=object(TSprvEmit)
|
||||
TSprvEmit_print=class(TEmitFetch)
|
||||
procedure Print;
|
||||
procedure PrintCaps;
|
||||
procedure PrintOpList(node:PspirvOp);
|
||||
procedure PrintOpBlock(pBlock:PsrOpBlock);
|
||||
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
|
||||
|
@ -42,637 +37,141 @@ 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);
|
||||
procedure PrintNode(Node:PsrNode);
|
||||
var
|
||||
s:Single;
|
||||
i:Int64;
|
||||
u:QWORD;
|
||||
name:RawByteString;
|
||||
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
|
||||
Assert(Node<>nil,'PrintNode$1');
|
||||
name:=node^.GetPrintName;
|
||||
if (name<>'') then
|
||||
begin
|
||||
n:=P^.GetName;
|
||||
if (n<>'') then
|
||||
begin
|
||||
Write('%',n);
|
||||
end else
|
||||
begin
|
||||
Write('%v',P^.ID.ID);
|
||||
end;
|
||||
Write('%',name);
|
||||
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');
|
||||
name:=node^.GetPrintData;
|
||||
Assert(name<>'','PrintNode$2');
|
||||
Write(name);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_print.PrintCaps;
|
||||
var
|
||||
node:PSpirvCap;
|
||||
node:PsrCapability;
|
||||
begin
|
||||
node:=FSpirvCaps.First;
|
||||
node:=CapabilityList.First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
Writeln(Op.GetStr(Op.OpCapability),' ',Capability.GetStr(node^.ID));
|
||||
node:=FSpirvCaps.Next(node);
|
||||
node:=CapabilityList.Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_print.PrintOpList(node:PspirvOp);
|
||||
procedure TSprvEmit_print.PrintOpBlock(pBlock:PsrOpBlock);
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
if (pBlock=nil) then Exit;
|
||||
node:=pBlock^.First;
|
||||
|
||||
While (node<>nil) do
|
||||
begin
|
||||
PrintOp(node,false);
|
||||
node:=node^.pNext;
|
||||
if node^.IsType(ntOp) then
|
||||
begin
|
||||
pBlock:=node^.Parent;
|
||||
Write(Space(pBlock^.Level));
|
||||
PrintOp(node,false);
|
||||
end;
|
||||
node:=flow_down_next_up(node);
|
||||
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;
|
||||
PrintOpBlock(@HeaderList);
|
||||
if (HeaderList.First<>nil) then Writeln;
|
||||
PrintOpBlock(@DebugInfoList);
|
||||
if (DebugInfoList.First<>nil) then Writeln;
|
||||
PrintOpBlock(@DecorateList);
|
||||
if (DecorateList.First<>nil) then Writeln;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_print.PrintTypes;
|
||||
var
|
||||
node:PsrType;
|
||||
pConst:PsrConst;
|
||||
i:dword;
|
||||
ie:Boolean;
|
||||
i:Word;
|
||||
begin
|
||||
node:=FSpirvTypes.FList.pHead;
|
||||
node:=TypeList.First;
|
||||
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
|
||||
PrintNode(node);
|
||||
Write(' = ',Op.GetStr(node^.OpId));
|
||||
if (node^.ItemCount<>0) then
|
||||
begin
|
||||
For i:=0 to node^.ItemCount-1 do
|
||||
begin
|
||||
For i:=0 to node^.key.count-1 do
|
||||
begin
|
||||
Write(' ');
|
||||
PrintTypeId(node^.GetCompItem(i));
|
||||
end;
|
||||
Write(' ');
|
||||
PrintNode(node^.GetItem(i));
|
||||
end;
|
||||
|
||||
end;
|
||||
Writeln;
|
||||
|
||||
node:=node^.pNext;
|
||||
node:=node^.Next;
|
||||
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;
|
||||
i:Word;
|
||||
begin
|
||||
node:=FConsts.FList.pHead;
|
||||
node:=ConstList.First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
|
||||
//if not node^.is_first then
|
||||
//begin
|
||||
if (node^.key.dtype=dtUnknow) then
|
||||
if (node^.dtype=dtUnknow) then
|
||||
begin
|
||||
Write('; ');
|
||||
Writeln(' = dtUnknow: read_count=',node^.read_count,' value=',node^.GetData);
|
||||
end else
|
||||
begin
|
||||
PrintNode(node);
|
||||
Write(' = ',Op.GetStr(node^.OpId),' ');
|
||||
PrintNode(node^.pType);
|
||||
if (node^.dtype<>dtBool) 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;
|
||||
For i:=0 to node^.ItemCount-1 do
|
||||
begin
|
||||
Write(' ');
|
||||
PrintNode(node^.GetItem(i));
|
||||
end;
|
||||
end;
|
||||
Writeln;
|
||||
end;
|
||||
node:=node^.Next;
|
||||
end;
|
||||
if (ConstList.First<>nil) then Writeln;
|
||||
end;
|
||||
|
||||
procedure TSprvEmit_print.PrintVariable;
|
||||
var
|
||||
node:PsrVariable;
|
||||
begin
|
||||
node:=FVariables.pHead;
|
||||
node:=VariableList.First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.pType<>nil) then
|
||||
begin
|
||||
PrintVar(node);
|
||||
PrintNode(node);
|
||||
Write(' = ',Op.GetStr(Op.OpVariable),' ');
|
||||
PrintTypeId(node^.pType);
|
||||
PrintNode(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;
|
||||
node:=node^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -680,12 +179,12 @@ procedure TSprvEmit_print.PrintFunc;
|
|||
var
|
||||
pFunc:PSpirvFunc;
|
||||
begin
|
||||
pFunc:=FSpirvFuncs.FList.pHead;
|
||||
pFunc:=FuncList.First;
|
||||
While (pFunc<>nil) do
|
||||
begin
|
||||
Writeln;
|
||||
PrintOpBlock(@pFunc^.FTop);
|
||||
pFunc:=pFunc^.pNext;
|
||||
PrintOpBlock(pFunc^.pTop);
|
||||
pFunc:=pFunc^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -700,35 +199,39 @@ begin
|
|||
|
||||
if Info.result then //dst
|
||||
begin
|
||||
Assert(node^.dst.ntype<>ntUnknow,'PrintOp$1');
|
||||
Assert(node^.dst.pData<>nil,'PrintOp$2');
|
||||
PrintOpParamSingle(node^.dst);
|
||||
Assert(node^.pDst<>nil,'PrintOp$1');
|
||||
if (node^.pDst<>nil) then
|
||||
begin
|
||||
PrintNode(node^.pDst);
|
||||
end;
|
||||
Write(' = ');
|
||||
Write(Op.GetStr(node^.OpId));
|
||||
end else
|
||||
begin //no dst
|
||||
Write(Op.GetStr(node^.OpId));
|
||||
if (node^.dst.ntype<>ntUnknow) then
|
||||
if (node^.pDst<>nil) then
|
||||
begin
|
||||
Assert(node^.dst.pData<>nil,'PrintOp$3');
|
||||
Write(' ');
|
||||
PrintOpParamSingle(node^.dst);
|
||||
PrintNode(node^.pDst);
|
||||
end;
|
||||
end;
|
||||
|
||||
if Info.rstype then //dst type
|
||||
begin
|
||||
Assert(node^.dst_type<>nil,'PrintOp$4');
|
||||
Assert(node^.pType<>nil,'PrintOp$2');
|
||||
Write(' ');
|
||||
PrintTypeId(node^.dst_type);
|
||||
if (node^.pType<>nil) then
|
||||
begin
|
||||
PrintNode(node^.pType);
|
||||
end;
|
||||
end;
|
||||
|
||||
Param:=node^.pParam.pHead;
|
||||
Param:=node^.ParamFirst;
|
||||
While (Param<>nil) do
|
||||
begin
|
||||
Write(' ');
|
||||
PrintOpParamNode(Param);
|
||||
Param:=Param^.pNext;
|
||||
PrintNode(Param^.Value);
|
||||
Param:=Param^.Next;
|
||||
end;
|
||||
|
||||
if (node^.OpId=Op.OpLabel) then
|
||||
|
@ -742,31 +245,6 @@ begin
|
|||
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.
|
||||
|
||||
|
|
|
@ -7,30 +7,29 @@ interface
|
|||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srType,
|
||||
srReg,
|
||||
srLayout,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
emit_fetch;
|
||||
|
||||
type
|
||||
TEmit_SMRD=object(TEmitOp)
|
||||
procedure _emit_SMRD;
|
||||
procedure _emit_LOAD_DWORDX(grp:PsrDataLayout;count:Byte);
|
||||
TEmit_SMRD=class(TEmitFetch)
|
||||
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);
|
||||
procedure TEmit_SMRD.emit_LOAD_DWORDX(grp:PsrDataLayout;count:Byte);
|
||||
var
|
||||
dst:PsrRegSlot;
|
||||
|
||||
ofs_r,idx_r:PsrRegNode;
|
||||
dtype:TsrDataType;
|
||||
|
||||
ext:TsrChainExt;
|
||||
lvl_0:TsrChainLvl_0;
|
||||
lvl_1:TsrChainLvl_1;
|
||||
|
||||
i:Byte;
|
||||
|
||||
|
@ -40,22 +39,23 @@ begin
|
|||
begin
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SMRD.SDST+i);
|
||||
dst:=get_sdst7(FSPI.SMRD.SDST+i);
|
||||
Assert(dst<>nil);
|
||||
MakeChain(dst,grp,(FSPI.SMRD.OFFSET+i)*4,4,nil);
|
||||
|
||||
lvl_0.offset:=(FSPI.SMRD.OFFSET+i)*4;
|
||||
lvl_0.size :=4;
|
||||
|
||||
MakeChain(dst,grp,@lvl_0,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)));
|
||||
idx_r:=OpShrTo(ofs_r,2);
|
||||
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SMRD.SDST+i);
|
||||
dst:=get_sdst7(FSPI.SMRD.SDST+i);
|
||||
Assert(dst<>nil);
|
||||
|
||||
if (i=0) then
|
||||
|
@ -63,17 +63,16 @@ 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)));
|
||||
ofs_r:=OpIAddTo(idx_r,i);
|
||||
end;
|
||||
|
||||
ofs_r^.mark_read;
|
||||
lvl_0.offset:=0;
|
||||
lvl_0.size :=4;
|
||||
|
||||
ext:=Default(TsrChainExt);
|
||||
ext.pIndex:=ofs_r;
|
||||
ext.stride:=4;
|
||||
MakeChain(dst,grp,0,4,@ext);
|
||||
lvl_1.pIndex:=ofs_r;
|
||||
lvl_1.stride:=4;
|
||||
|
||||
MakeChain(dst,grp,@lvl_0,@lvl_1);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -84,9 +83,9 @@ var
|
|||
src:array[0..3] of PsrRegSlot;
|
||||
grp:PsrDataLayout;
|
||||
begin
|
||||
if not FRegsStory.get_sbase(FSPI.SMRD.SBASE,2,@src) then Assert(false);
|
||||
if not get_sbase(FSPI.SMRD.SBASE,2,@src) then Assert(false);
|
||||
grp:=GroupingSharp(@src,rtBufPtr2);
|
||||
_emit_LOAD_DWORDX(grp,count);
|
||||
emit_LOAD_DWORDX(grp,count);
|
||||
end;
|
||||
|
||||
procedure TEmit_SMRD.emit_BUFFER_LOAD_DWORDX(count:Byte);
|
||||
|
@ -94,56 +93,26 @@ var
|
|||
src:array[0..3] of PsrRegSlot;
|
||||
grp:PsrDataLayout;
|
||||
begin
|
||||
if not FRegsStory.get_sbase(FSPI.SMRD.SBASE,4,@src) then Assert(false);
|
||||
if not get_sbase(FSPI.SMRD.SBASE,4,@src) then Assert(false);
|
||||
grp:=GroupingSharp(@src,rtVSharp4);
|
||||
_emit_LOAD_DWORDX(grp,count);
|
||||
emit_LOAD_DWORDX(grp,count);
|
||||
end;
|
||||
|
||||
procedure TEmit_SMRD._emit_SMRD;
|
||||
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_BUFFER_LOAD_DWORD : emit_BUFFER_LOAD_DWORDX(1);
|
||||
S_BUFFER_LOAD_DWORDX2 : emit_BUFFER_LOAD_DWORDX(2);
|
||||
S_BUFFER_LOAD_DWORDX4 : emit_BUFFER_LOAD_DWORDX(4);
|
||||
S_BUFFER_LOAD_DWORDX8 : emit_BUFFER_LOAD_DWORDX(8);
|
||||
S_BUFFER_LOAD_DWORDX16: emit_BUFFER_LOAD_DWORDX(16);
|
||||
|
||||
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;
|
||||
S_LOAD_DWORD : emit_LOAD_DWORDX(1);
|
||||
S_LOAD_DWORDX2 : emit_LOAD_DWORDX(2);
|
||||
S_LOAD_DWORDX4 : emit_LOAD_DWORDX(4);
|
||||
S_LOAD_DWORDX8 : emit_LOAD_DWORDX(8);
|
||||
S_LOAD_DWORDX16: emit_LOAD_DWORDX(16);
|
||||
|
||||
else
|
||||
Assert(false,'SMRD?'+IntToStr(FSPI.SMRD.OP));
|
||||
|
|
|
@ -7,172 +7,148 @@ interface
|
|||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srLabel,
|
||||
srTypes,
|
||||
srCFGLabel,
|
||||
srFlow,
|
||||
srType,
|
||||
srConst,
|
||||
srReg,
|
||||
srLayout,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
srOpUtils,
|
||||
emit_fetch;
|
||||
|
||||
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;
|
||||
TEmit_SOP1=class(TEmitFetch)
|
||||
procedure emit_SOP1;
|
||||
Function GetFuncPtr(src:PPsrRegNode):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;
|
||||
Function TEmit_SOP1.GetFuncPtr(src:PPsrRegNode):Pointer;
|
||||
var
|
||||
chain:TsrChains;
|
||||
pConst:array[0..1] of PsrConst;
|
||||
pLayout:PsrDataLayout;
|
||||
|
||||
begin
|
||||
Result:=nil;
|
||||
|
||||
chain:=Default(TsrChains);
|
||||
chain[0]:=GetChainRegNode(src[0]^.current);
|
||||
chain[1]:=GetChainRegNode(src[1]^.current);
|
||||
src[0]:=RegDown(src[0]);
|
||||
src[1]:=RegDown(src[1]);
|
||||
|
||||
pLayout:=FDataLayouts.Grouping(chain,rtFunPtr2);
|
||||
Result:=pLayout^.pData;
|
||||
Assert(src[0]<>nil);
|
||||
Assert(src[1]<>nil);
|
||||
|
||||
if (src[0]^.is_const) and (src[1]^.is_const) then
|
||||
begin
|
||||
pConst[0]:=src[0]^.AsConst;
|
||||
pConst[1]:=src[1]^.AsConst;
|
||||
|
||||
QWORD(Result):=QWORD(pConst[0]^.AsUint32) or (QWORD(pConst[1]^.AsUint32) shl 32);
|
||||
end else
|
||||
begin
|
||||
chain:=Default(TsrChains);
|
||||
chain[0]:=GetChainRegNode(src[0]);
|
||||
chain[1]:=GetChainRegNode(src[1]);
|
||||
|
||||
pLayout:=DataLayoutList.Grouping(chain,rtFunPtr2);
|
||||
Result:=pLayout^.pData;
|
||||
end;
|
||||
|
||||
Assert(Result<>nil);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP1._emit_S_MOV_B32;
|
||||
procedure TEmit_SOP1.emit_S_MOV_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SOP1.SDST);
|
||||
dst:=get_sdst7(FSPI.SOP1.SDST);
|
||||
src:=fetch_ssrc9(FSPI.SOP1.SSRC,dtUnknow);
|
||||
_MakeCopy(dst,src);
|
||||
MakeCopy(dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP1._emit_S_MOV_B64;
|
||||
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);
|
||||
dst[0]:=get_sdst7(FSPI.SOP1.SDST+0);
|
||||
dst[1]:=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]);
|
||||
MakeCopy(dst[0],src[0]);
|
||||
MakeCopy(dst[1],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP1._emit_S_SWAPPC_B64;
|
||||
procedure TEmit_SOP1.emit_S_SWAPPC_B64;
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
src:array[0..1] of PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
|
||||
oldptr,newptr:Pointer;
|
||||
|
||||
begin
|
||||
if not FRegsStory.get_sdst7_pair(FSPI.SOP1.SDST,@dst) then Assert(false);
|
||||
if not get_sdst7_pair(FSPI.SOP1.SDST,@dst) then Assert(false);
|
||||
|
||||
Assert(not is_const_ssrc9(FSPI.SOP1.SSRC));
|
||||
if not fetch_ssrc9_pair(FSPI.SOP1.SSRC,@src,dtUnknow) then Assert(false);
|
||||
|
||||
if not FRegsStory.get_ssrc9_pair(FSPI.SOP1.SSRC,@src) then Assert(false);
|
||||
newptr:=GetFuncPtr(@src);
|
||||
|
||||
newptr:=_GetFuncPtr(@src);
|
||||
Assert(newptr<>nil);
|
||||
oldptr:=GetPtr;
|
||||
|
||||
oldptr:=FCursor.Adr.get_pc;
|
||||
|
||||
SetConst(dst[0],dtUint32,{%H-}QWORD(oldptr));
|
||||
SetConst(dst[1],dtUint32,{%H-}QWORD(oldptr) shr 32);
|
||||
SetConst_q(dst[0],dtUint32,QWORD(oldptr));
|
||||
SetConst_q(dst[1],dtUint32,QWORD(oldptr) shr 32);
|
||||
|
||||
SetPtr(newptr,btSetpc);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP1._emit_S_SETPC_B64;
|
||||
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;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
|
||||
newptr:Pointer;
|
||||
|
||||
begin
|
||||
Assert(not is_const_ssrc9(FSPI.SOP1.SSRC));
|
||||
if not FRegsStory.get_ssrc9_pair(FSPI.SOP1.SSRC,@src) then Assert(false);
|
||||
if not fetch_ssrc9_pair(FSPI.SOP1.SSRC,@src,dtUnknow) 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;
|
||||
newptr:=GetFuncPtr(@src);
|
||||
|
||||
SetPtr(newptr,btMain);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP1._emit_S_AND_SAVEEXEC_B64; //sdst.du = EXEC;| EXEC = (ssrc.du & EXEC);| SCC = (sdst != 0)
|
||||
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
|
||||
if not get_sdst7_pair(FSPI.SOP1.SDST,@dst) then Assert(False);
|
||||
|
||||
dst[0]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+0);
|
||||
dst[1]:=FRegsStory.get_sdst7(FSPI.SOP1.SDST+1);
|
||||
if not fetch_ssrc9_pair(FSPI.SOP1.SSRC,@src,dtUnknow) then Assert(False); //ssrc8
|
||||
|
||||
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;
|
||||
exc[0]:=MakeRead(get_exec0,dtUnknow);
|
||||
exc[1]:=MakeRead(get_exec1,dtUnknow);
|
||||
|
||||
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]);
|
||||
OpBitwiseAnd(get_exec0,src[0],exc[0]);
|
||||
OpBitwiseAnd(get_exec1,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)
|
||||
OpLogicalOr(get_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;
|
||||
procedure TEmit_SOP1.emit_S_WQM_B64;
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
|
@ -184,51 +160,24 @@ begin
|
|||
//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);
|
||||
if not get_sdst7_pair(FSPI.SOP1.SDST,@dst) then Assert(False);
|
||||
|
||||
Assert(dst[0]<>nil);
|
||||
Assert(dst[1]<>nil);
|
||||
if not fetch_ssrc9_pair(FSPI.SOP1.SSRC,@src,dtUnknow) then Assert(False); //ssrc8
|
||||
|
||||
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]);
|
||||
OpWQM32(dst[0],src[0]);
|
||||
OpWQM32(dst[1],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP1._emit_SOP1;
|
||||
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;
|
||||
S_MOV_B32 : emit_S_MOV_B32;
|
||||
S_MOV_B64 : emit_S_MOV_B64;
|
||||
S_WQM_B64 : emit_S_WQM_B64;
|
||||
S_SWAPPC_B64 : emit_S_SWAPPC_B64;
|
||||
S_SETPC_B64 : emit_S_SETPC_B64;
|
||||
S_AND_SAVEEXEC_B64: emit_S_AND_SAVEEXEC_B64;
|
||||
|
||||
else
|
||||
Assert(false,'SOP1?'+IntToStr(FSPI.SOP1.OP));
|
||||
|
|
|
@ -6,359 +6,276 @@ interface
|
|||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srConst,
|
||||
srType,
|
||||
srReg,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
emit_fetch;
|
||||
|
||||
|
||||
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_CSELECT_B64;
|
||||
procedure _emit_S_BFE_U32;
|
||||
TEmit_SOP2=class(TEmitFetch)
|
||||
procedure emit_SOP2;
|
||||
procedure emit_S_ADD_I32;
|
||||
procedure emit_S_MUL_I32;
|
||||
procedure OpISccNotZero(src:PsrRegNode);
|
||||
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_CSELECT_B64;
|
||||
procedure emit_S_BFE_U32;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_SOP2._emit_S_ADD_I32;
|
||||
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;
|
||||
dst:=get_sdst7(FSPI.SOP2.SDST);
|
||||
car:=get_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]);
|
||||
OpIAddExt(dst,car,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_MUL_I32;
|
||||
procedure TEmit_SOP2.emit_S_MUL_I32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST);
|
||||
dst:=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]);
|
||||
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;
|
||||
procedure TEmit_SOP2.OpISccNotZero(src:PsrRegNode); //SCC = (sdst.u != 0)
|
||||
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);
|
||||
MakeCopy(get_scc,src);
|
||||
get_scc^.current^.dtype:=dtBool; //implict cast (int != 0)
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_LSHR_B32; //SCC = (sdst.u != 0)
|
||||
procedure TEmit_SOP2.emit_S_LSHL_B32;
|
||||
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;
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST);
|
||||
dst:=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]);
|
||||
src[1]:=OpBitwiseAndTo(src[1],31);
|
||||
src[1]^.PrepType(ord(dtUInt32));
|
||||
|
||||
tmp:=@FRegsStory.SCC;
|
||||
MakeCopy(tmp,dst^.current);
|
||||
tmp^.current^.dtype:=dtBool;
|
||||
Op2(Op.OpShiftLeftLogical,src[0]^.dtype,dst,src[0],src[1]);
|
||||
|
||||
OpISccNotZero(dst^.current); //SCC = (sdst.u != 0)
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_AND_B64; //SCC = (sdst[2] != 0)
|
||||
procedure TEmit_SOP2.emit_S_LSHR_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=get_sdst7(FSPI.SOP2.SDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUInt32);
|
||||
src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUInt32);
|
||||
|
||||
src[1]:=OpBitwiseAndTo(src[1],31);
|
||||
src[1]^.PrepType(ord(dtUInt32));
|
||||
|
||||
Op2(Op.OpShiftRightLogical,src[0]^.dtype,dst,src[0],src[1]);
|
||||
|
||||
OpISccNotZero(dst^.current); //SCC = (sdst.u != 0)
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2.emit_S_AND_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=get_sdst7(FSPI.SOP2.SDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUInt32);
|
||||
src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUInt32);
|
||||
|
||||
OpBitwiseAnd(dst,src[0],src[1]);
|
||||
|
||||
OpISccNotZero(dst^.current); //SCC = (sdst.u != 0)
|
||||
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 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);
|
||||
if not fetch_ssrc9_pair(FSPI.SOP2.SSRC0,@src0,dtUInt32) then Assert(False);
|
||||
if not fetch_ssrc9_pair(FSPI.SOP2.SSRC1,@src1,dtUInt32) then Assert(False);
|
||||
|
||||
emit_OpBitwiseAnd(dst[0],src0[0],src1[0]);
|
||||
emit_OpBitwiseAnd(dst[1],src0[1],src1[1]);
|
||||
OpBitwiseAnd(dst[0],src0[0],src1[0]);
|
||||
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)
|
||||
OpLogicalOr(get_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)
|
||||
procedure TEmit_SOP2.emit_S_ANDN2_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 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);
|
||||
if not fetch_ssrc9_pair(FSPI.SOP2.SSRC0,@src0,dtUInt32) then Assert(False);
|
||||
if not fetch_ssrc9_pair(FSPI.SOP2.SSRC1,@src1,dtUInt32) then Assert(False);
|
||||
|
||||
emit_OpBitwiseOr(dst[0],src0[0],src1[0]);
|
||||
emit_OpBitwiseOr(dst[1],src0[1],src1[1]);
|
||||
src1[0]:=OpNotTo(src1[0]);
|
||||
src1[1]:=OpNotTo(src1[1]);
|
||||
|
||||
OpBitwiseAnd(dst[0],src0[0],src1[0]);
|
||||
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)
|
||||
OpLogicalOr(get_scc,src2[0],src2[1]); //implict cast (int != 0)
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_NOR_B64; //SCC = (sdst[2] != 0)
|
||||
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 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);
|
||||
if not fetch_ssrc9_pair(FSPI.SOP2.SSRC0,@src0,dtUInt32) then Assert(False);
|
||||
if not fetch_ssrc9_pair(FSPI.SOP2.SSRC1,@src1,dtUInt32) then Assert(False);
|
||||
|
||||
emit_OpBitwiseOr(dst[0],src0[0],src1[0]);
|
||||
emit_OpBitwiseOr(dst[1],src0[1],src1[1]);
|
||||
OpBitwiseOr(dst[0],src0[0],src1[0]);
|
||||
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)
|
||||
OpLogicalOr(get_scc,src2[0],src2[1]); //implict cast (int != 0)
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_CSELECT_B32; //sdst = SCC ? ssrc0 : ssrc1
|
||||
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 get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False);
|
||||
|
||||
if not fetch_ssrc9_pair(FSPI.SOP2.SSRC0,@src0,dtUInt32) then Assert(False);
|
||||
if not fetch_ssrc9_pair(FSPI.SOP2.SSRC1,@src1,dtUInt32) then Assert(False);
|
||||
|
||||
src2[0]:=OpBitwiseOrTo(src0[0],src1[0]);
|
||||
src2[1]:=OpBitwiseOrTo(src0[1],src1[1]);
|
||||
|
||||
OpNot(dst[0],src2[0]);
|
||||
OpNot(dst[1],src2[1]);
|
||||
|
||||
src2[0]:=dst[0]^.current;
|
||||
src2[1]:=dst[1]^.current;
|
||||
|
||||
OpLogicalOr(get_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..1] of PsrRegNode;
|
||||
scc:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SOP2.SDST);
|
||||
dst:=get_sdst7(FSPI.SOP2.SDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUnknow);
|
||||
src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUnknow);
|
||||
scc:=MakeRead(@FRegsStory.SCC,dtBool);
|
||||
scc:=MakeRead(get_scc,dtBool);
|
||||
|
||||
emit_OpSelect(dst,src[0],src[1],scc);
|
||||
OpSelect(dst,src[0],src[1],scc);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_S_CSELECT_B64; //sdst[2] = SCC ? ssrc0[2] : ssrc1[2]
|
||||
procedure TEmit_SOP2.emit_S_CSELECT_B64; //sdst[2] = SCC ? ssrc0[2] : ssrc1[2]
|
||||
Var
|
||||
dst:array[0..1] of PsrRegSlot;
|
||||
src0,src1:array[0..1] of PsrRegNode;
|
||||
scc:PsrRegNode;
|
||||
begin
|
||||
if not FRegsStory.get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False);
|
||||
if not get_sdst7_pair(FSPI.SOP2.SDST,@dst) then Assert(False);
|
||||
|
||||
if not fetch_ssrc9_pair(@src0,FSPI.SOP2.SSRC0,dtUnknow) then Assert(False);
|
||||
if not fetch_ssrc9_pair(@src1,FSPI.SOP2.SSRC1,dtUnknow) then Assert(False);
|
||||
if not fetch_ssrc9_pair(FSPI.SOP2.SSRC0,@src0,dtUnknow) then Assert(False);
|
||||
if not fetch_ssrc9_pair(FSPI.SOP2.SSRC1,@src1,dtUnknow) then Assert(False);
|
||||
|
||||
scc:=MakeRead(@FRegsStory.SCC,dtBool);
|
||||
scc^.mark_read;
|
||||
scc:=MakeRead(get_scc,dtBool);
|
||||
|
||||
emit_OpSelect(dst[0],src0[0],src1[0],scc);
|
||||
emit_OpSelect(dst[1],src0[1],src1[1],scc);
|
||||
OpSelect(dst[0],src0[0],src1[0],scc);
|
||||
OpSelect(dst[1],src0[1],src1[1],scc);
|
||||
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)
|
||||
procedure TEmit_SOP2.emit_S_BFE_U32; //sdst.u = bitFieldExtract(ssrc0); SCC = (sdst.u != 0)
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
dst: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;
|
||||
dst:=get_sdst7(FSPI.SOP2.SDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.SOP2.SSRC0,dtUint32);
|
||||
src[1]:=fetch_ssrc9(FSPI.SOP2.SSRC1,dtUint32);
|
||||
|
||||
num_31:=FetchReg(FConsts.Fetch(dtUInt32,31));
|
||||
offset:=OpBitwiseAndTo(src[1],31);
|
||||
count :=OpShrTo(src[1],16);
|
||||
|
||||
emit_OpBitwiseAnd(tmp,src[1],num_31);
|
||||
offset:=MakeRead(tmp,dtUInt32);
|
||||
Op3(Op.OpBitFieldUExtract,dtUInt32,dst,src[0],offset,count);
|
||||
|
||||
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;
|
||||
OpISccNotZero(dst^.current); //SCC = (sdst.u != 0)
|
||||
end;
|
||||
|
||||
procedure TEmit_SOP2._emit_SOP2;
|
||||
procedure TEmit_SOP2.emit_SOP2;
|
||||
begin
|
||||
|
||||
Case FSPI.SOP2.OP of
|
||||
|
||||
S_ADD_I32:
|
||||
begin
|
||||
_emit_S_ADD_I32;
|
||||
end;
|
||||
S_ADD_I32: emit_S_ADD_I32;
|
||||
S_MUL_I32: emit_S_MUL_I32;
|
||||
|
||||
S_MUL_I32: //& 0xFFFFFFFF
|
||||
begin
|
||||
_emit_S_MUL_I32;
|
||||
end;
|
||||
S_LSHL_B32: emit_S_LSHL_B32;
|
||||
S_LSHR_B32: emit_S_LSHR_B32;
|
||||
|
||||
S_LSHL_B32: //SCC = (sdst.u != 0)
|
||||
begin
|
||||
_emit_S_LSHL_B32;
|
||||
end;
|
||||
S_AND_B32: emit_S_AND_B32;
|
||||
S_AND_B64: emit_S_AND_B64;
|
||||
|
||||
S_LSHR_B32:
|
||||
begin
|
||||
_emit_S_LSHR_B32;
|
||||
end;
|
||||
S_ANDN2_B64: emit_S_ANDN2_B64;
|
||||
|
||||
S_AND_B32:
|
||||
begin
|
||||
_emit_S_AND_B32;
|
||||
end;
|
||||
S_OR_B64: emit_S_OR_B64;
|
||||
|
||||
S_AND_B64:
|
||||
begin
|
||||
_emit_S_AND_B64;
|
||||
end;
|
||||
S_NOR_B64: emit_S_NOR_B64;
|
||||
|
||||
S_ANDN2_B64:
|
||||
begin
|
||||
_emit_S_ANDN2_B64;
|
||||
end;
|
||||
S_CSELECT_B32: emit_S_CSELECT_B32;
|
||||
S_CSELECT_B64: emit_S_CSELECT_B64;
|
||||
|
||||
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_CSELECT_B64:
|
||||
begin
|
||||
_emit_S_CSELECT_B64;
|
||||
end;
|
||||
|
||||
S_BFE_U32:
|
||||
begin
|
||||
_emit_S_BFE_U32;
|
||||
end;
|
||||
S_BFE_U32: emit_S_BFE_U32;
|
||||
|
||||
else
|
||||
Assert(False,'SOP2?'+IntToStr(FSPI.SOP2.OP));
|
||||
|
|
|
@ -8,48 +8,47 @@ uses
|
|||
sysutils,
|
||||
spirv,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srType,
|
||||
srReg,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
emit_fetch;
|
||||
|
||||
type
|
||||
TEmit_SOPC=object(TEmitOp)
|
||||
procedure _emit_SOPC;
|
||||
procedure _emit_S_CMP_32(OpId:DWORD;rtype:TsrDataType);
|
||||
TEmit_SOPC=class(TEmitFetch)
|
||||
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);
|
||||
procedure TEmit_SOPC.emit_S_CMP_32(OpId:DWORD;rtype:TsrDataType);
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=@FRegsStory.SCC;
|
||||
dst:=get_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]);
|
||||
OpCmpS(OpId,dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOPC._emit_SOPC;
|
||||
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_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_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:;
|
||||
|
|
|
@ -7,39 +7,32 @@ interface
|
|||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srConst,
|
||||
srType,
|
||||
srReg,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
emit_fetch;
|
||||
|
||||
type
|
||||
TEmit_SOPK=object(TEmitOp)
|
||||
procedure _emit_SOPK;
|
||||
procedure _emit_S_MOVK_I32;
|
||||
TEmit_SOPK=class(TEmitFetch)
|
||||
procedure emit_SOPK;
|
||||
procedure emit_S_MOVK_I32;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_SOPK._emit_S_MOVK_I32;
|
||||
procedure TEmit_SOPK.emit_S_MOVK_I32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_sdst7(FSPI.SOPK.SDST);
|
||||
src:=FetchReg(FConsts.Fetchi(dtInt32,SmallInt(FSPI.SOPK.SIMM)));
|
||||
_MakeCopy(dst,src);
|
||||
dst:=get_sdst7(FSPI.SOPK.SDST);
|
||||
SetConst_i(dst,dtInt32,SmallInt(FSPI.SOPK.SIMM));
|
||||
end;
|
||||
|
||||
procedure TEmit_SOPK._emit_SOPK;
|
||||
procedure TEmit_SOPK.emit_SOPK;
|
||||
begin
|
||||
|
||||
Case FSPI.SOPK.OP of
|
||||
|
||||
S_MOVK_I32:
|
||||
begin
|
||||
_emit_S_MOVK_I32;
|
||||
end;
|
||||
S_MOVK_I32: emit_S_MOVK_I32;
|
||||
|
||||
else
|
||||
Assert(false,'SOPK?'+IntToStr(FSPI.SOPK.OP));
|
||||
|
|
|
@ -7,22 +7,23 @@ interface
|
|||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srParser,
|
||||
srLabel,
|
||||
srCFG,
|
||||
srType,
|
||||
srCFGParser,
|
||||
srCFGLabel,
|
||||
srCFGCursor,
|
||||
srFlow,
|
||||
srReg,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
spirv,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
emit_fetch;
|
||||
|
||||
type
|
||||
TEmit_SOPP=object(TEmitOp)
|
||||
procedure _emit_SOPP;
|
||||
procedure _emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean);
|
||||
procedure _emit_S_BRANCH;
|
||||
TEmit_SOPP=class(TEmitFetch)
|
||||
procedure emit_SOPP;
|
||||
procedure emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean);
|
||||
procedure emit_S_BRANCH;
|
||||
procedure mark_end_of;
|
||||
function IsBegLoop(Adr:TSrcAdr):Boolean;
|
||||
function IsEndLoop(Adr:TSrcAdr):Boolean;
|
||||
function IsUnknow(Adr:TSrcAdr):Boolean;
|
||||
|
@ -35,9 +36,6 @@ type
|
|||
|
||||
implementation
|
||||
|
||||
uses
|
||||
srVolatile;
|
||||
|
||||
procedure TEmit_SOPP.emit_cond_block(pSlot:PsrRegSlot;n:Boolean;adr:TSrcAdr);
|
||||
var
|
||||
src:PsrRegNode;
|
||||
|
@ -49,11 +47,11 @@ var
|
|||
begin
|
||||
src:=MakeRead(pSlot,dtBool); //get before OpBranchConditional
|
||||
|
||||
pOpLabel[0]:=NewLabelOp;
|
||||
pOpLabel[1]:=NewLabelOp;
|
||||
pOpLabel[0]:=NewLabelOp(False);
|
||||
pOpLabel[1]:=NewLabelOp(False);
|
||||
|
||||
pLBlock:=FCursor.pCode^.FTop.DownBlock(adr);
|
||||
Assert(pLBlock<>@FCursor.pCode^.FTop,'not found');
|
||||
pLBlock:=Cursor.pCode^.FTop.DownBlock(adr);
|
||||
Assert(pLBlock<>@Cursor.pCode^.FTop,'not found');
|
||||
|
||||
Info[0]:=Default(TsrBlockInfo);
|
||||
Info[1]:=Default(TsrBlockInfo);
|
||||
|
@ -61,8 +59,8 @@ begin
|
|||
Case pLBlock^.bType of
|
||||
btAdr: //set new adr
|
||||
begin
|
||||
Info[0].b_adr:=FCursor.Adr;
|
||||
Info[0].e_adr:=FCursor.Adr;
|
||||
Info[0].b_adr:=Cursor.Adr;
|
||||
Info[0].e_adr:=Cursor.Adr;
|
||||
Info[0].bType:=btCond;
|
||||
//
|
||||
Info[1].b_adr:=pLBlock^.pBLabel^.Adr;
|
||||
|
@ -86,18 +84,18 @@ begin
|
|||
pOpLabel[0]^.Adr:=Info[0].b_adr;
|
||||
pOpLabel[1]^.Adr:=Info[0].e_adr;
|
||||
|
||||
pOpBlock:=NewBlockOp(FRegsStory.get_snapshot);
|
||||
pOpBlock:=NewBlockOp(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]);
|
||||
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);
|
||||
True :OpBranchCond(line,pOpLabel[1],pOpLabel[0],src);
|
||||
False:OpBranchCond(line,pOpLabel[0],pOpLabel[1],src);
|
||||
end;
|
||||
|
||||
AddSpirvOp(line,pOpLabel[0]);
|
||||
|
@ -117,57 +115,56 @@ procedure TEmit_SOPP.UpBuildVol(last:PsrOpBlock);
|
|||
var
|
||||
node:PsrOpBlock;
|
||||
begin
|
||||
node:=FMain^.pBlock;
|
||||
node:=Main^.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);
|
||||
btCond:PrivateList.build_volatile_cur(node^.Regs.pSnap);
|
||||
btLoop:PrivateList.build_volatile_old(node^.Regs.pSnap);
|
||||
else;
|
||||
end;
|
||||
|
||||
if (node=last) then Break;
|
||||
node:=node^.pParent;
|
||||
node:=node^.Parent;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_SOPP.emit_loop(adr:TSrcAdr);
|
||||
var
|
||||
node,pOpBlock:PsrOpBlock;
|
||||
pOpLabel:array[0..1] of PspirvOp;
|
||||
pOpLabel:PspirvOp;
|
||||
FVolMark:TsrVolMark;
|
||||
bnew:Boolean;
|
||||
begin
|
||||
|
||||
node:=FMain^.pBlock;
|
||||
node:=Main^.pBlock;
|
||||
pOpBlock:=node^.FindUpLoop;
|
||||
Assert(pOpBlock<>nil,'not found');
|
||||
|
||||
pOpLabel[0]:=nil;
|
||||
pOpLabel:=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
|
||||
pOpLabel:=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;
|
||||
pOpLabel:=pOpBlock^.Labels.pEndOp;
|
||||
FVolMark:=vmBreak;
|
||||
end else
|
||||
begin
|
||||
Assert(false,'emit_loop');
|
||||
end;
|
||||
|
||||
Assert(pOpLabel[0]<>nil);
|
||||
Assert(pOpLabel<>nil);
|
||||
|
||||
bnew:=true;
|
||||
if FCursor.pBlock^.IsEndOf(FCursor.Adr) then //is last
|
||||
if Cursor.pBlock^.IsEndOf(Cursor.Adr) then //is last
|
||||
begin
|
||||
Assert(node^.Block.e_adr.get_pc=FCursor.Adr.get_pc);
|
||||
Assert(node^.Block.e_adr.get_pc=Cursor.Adr.get_pc);
|
||||
Case node^.Block.bType of
|
||||
btSetpc:;
|
||||
else
|
||||
|
@ -180,11 +177,10 @@ begin
|
|||
UpBuildVol(pOpBlock);
|
||||
node^.Regs.FVolMark:=FVolMark; //mark end of
|
||||
|
||||
emit_OpBranch(line,pOpLabel[0]);
|
||||
OpBranch(line,pOpLabel);
|
||||
if bnew then
|
||||
begin
|
||||
pOpLabel[1]:=NewLabelOp;
|
||||
AddSpirvOp(line,pOpLabel[1]);
|
||||
AddSpirvOp(line,NewLabelOp(True));
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -197,7 +193,7 @@ var
|
|||
begin
|
||||
src:=MakeRead(pSlot,dtBool);
|
||||
|
||||
node:=FMain^.pBlock;
|
||||
node:=Main^.pBlock;
|
||||
pOpBlock:=node^.FindUpLoop;
|
||||
Assert(pOpBlock<>nil,'not found');
|
||||
|
||||
|
@ -220,16 +216,16 @@ begin
|
|||
end;
|
||||
|
||||
Assert(pOpLabel[0]<>nil);
|
||||
pOpLabel[1]:=NewLabelOp;
|
||||
pOpLabel[1]:=NewLabelOp(False);
|
||||
|
||||
UpBuildVol(pOpBlock);
|
||||
node^.Regs.FVolMark:=FVolMark; //mark end of
|
||||
|
||||
emit_OpCondMerge(line,pOpLabel[1]);
|
||||
OpCondMerge(line,pOpLabel[1]);
|
||||
|
||||
Case n of
|
||||
True :emit_OpBranchCond(line,pOpLabel[0],pOpLabel[1],src);
|
||||
False:emit_OpBranchCond(line,pOpLabel[1],pOpLabel[0],src);
|
||||
True :OpBranchCond(line,pOpLabel[0],pOpLabel[1],src);
|
||||
False:OpBranchCond(line,pOpLabel[1],pOpLabel[0],src);
|
||||
end;
|
||||
|
||||
AddSpirvOp(line,pOpLabel[1]);
|
||||
|
@ -240,7 +236,7 @@ var
|
|||
node:PsrCFGBlock;
|
||||
begin
|
||||
Result:=false;
|
||||
node:=FCursor.pBlock^.FindUpLoop;
|
||||
node:=Cursor.pBlock^.FindUpLoop;
|
||||
if (node<>nil) then
|
||||
begin
|
||||
Result:=node^.pBLabel^.Adr.get_pc=Adr.get_pc;
|
||||
|
@ -252,7 +248,7 @@ var
|
|||
node:PsrCFGBlock;
|
||||
begin
|
||||
Result:=false;
|
||||
node:=FCursor.pBlock^.FindUpLoop;
|
||||
node:=Cursor.pBlock^.FindUpLoop;
|
||||
if (node<>nil) then
|
||||
begin
|
||||
Result:=node^.pELabel^.Adr.get_pc=Adr.get_pc;
|
||||
|
@ -269,13 +265,12 @@ begin
|
|||
Result:=pLabel^.IsType(ltUnknow);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOPP._emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean);
|
||||
procedure TEmit_SOPP.emit_S_BRANCH_COND(pSlot:PsrRegSlot;n:Boolean);
|
||||
var
|
||||
c_adr,b_adr:TSrcAdr;
|
||||
pLabel:PsrLabel;
|
||||
|
||||
begin
|
||||
c_adr:=FCursor.Adr;
|
||||
c_adr:=Cursor.Adr;
|
||||
b_adr:=c_adr;
|
||||
b_adr.Offdw:=get_branch_offset(FSPI);
|
||||
|
||||
|
@ -293,7 +288,7 @@ begin
|
|||
emit_loop_cond(pSlot,n,b_adr);
|
||||
end else
|
||||
begin //down
|
||||
if FCursor.pBlock^.IsBigOf(b_adr) then
|
||||
if Cursor.pBlock^.IsBigOf(b_adr) then
|
||||
begin //break?
|
||||
if not IsEndLoop(b_adr) then Assert(false,'Unknow');
|
||||
emit_loop_cond(pSlot,n,b_adr);
|
||||
|
@ -314,9 +309,9 @@ var
|
|||
begin
|
||||
Info:=Default(TsrBlockInfo);
|
||||
|
||||
c_adr:=FCursor.Adr; //get current
|
||||
c_adr:=Cursor.Adr; //get current
|
||||
SetPtr(adr.get_pc,btAdrBranch); //set new
|
||||
e_adr:=FCursor.pCode^.FTop.pELabel^.Adr; //get end of code
|
||||
e_adr:=Cursor.pCode^.FTop.pELabel^.Adr; //get end of code
|
||||
SetPtr(c_adr.get_pc,btMain); //ret current
|
||||
|
||||
Info.b_adr:=adr;
|
||||
|
@ -331,12 +326,12 @@ begin
|
|||
SetPtr(adr.get_pc,btAdrBranch);
|
||||
end;
|
||||
|
||||
procedure TEmit_SOPP._emit_S_BRANCH;
|
||||
procedure TEmit_SOPP.emit_S_BRANCH;
|
||||
var
|
||||
c_adr,b_adr:TSrcAdr;
|
||||
|
||||
begin
|
||||
c_adr:=FCursor.Adr;
|
||||
c_adr:=Cursor.Adr;
|
||||
b_adr:=c_adr;
|
||||
b_adr.Offdw:=get_branch_offset(FSPI);
|
||||
|
||||
|
@ -356,7 +351,12 @@ begin
|
|||
|
||||
end;
|
||||
|
||||
procedure TEmit_SOPP._emit_SOPP;
|
||||
procedure TEmit_SOPP.mark_end_of;
|
||||
begin
|
||||
Main^.pBlock^.Regs.FVolMark:=vmEnd; //mark end of
|
||||
end;
|
||||
|
||||
procedure TEmit_SOPP.emit_SOPP;
|
||||
begin
|
||||
Case FSPI.SOPP.OP of
|
||||
S_NOP,
|
||||
|
@ -368,17 +368,17 @@ begin
|
|||
begin
|
||||
AddSpirvOp(Op.OpReturn);
|
||||
end;
|
||||
FMain^.pBlock^.Regs.FVolMark:=vmEnd; //mark end of
|
||||
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_CBRANCH_SCC0 :emit_S_BRANCH_COND(get_scc ,false);
|
||||
S_CBRANCH_SCC1 :emit_S_BRANCH_COND(get_scc ,true);
|
||||
S_CBRANCH_VCCZ :emit_S_BRANCH_COND(get_vcc0 ,false);
|
||||
S_CBRANCH_VCCNZ :emit_S_BRANCH_COND(get_vcc0 ,true);
|
||||
S_CBRANCH_EXECZ :emit_S_BRANCH_COND(get_exec0,false);
|
||||
S_CBRANCH_EXECNZ:emit_S_BRANCH_COND(get_exec0,true);
|
||||
|
||||
S_BRANCH :_emit_S_BRANCH;
|
||||
S_BRANCH :emit_S_BRANCH;
|
||||
|
||||
else
|
||||
Assert(false,'SOPP?'+IntToStr(FSPI.SOPP.OP));
|
||||
|
|
|
@ -8,12 +8,12 @@ uses
|
|||
sysutils,
|
||||
ps4_shader,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srType,
|
||||
srConst,
|
||||
srReg,
|
||||
srLayout,
|
||||
SprvEmit,
|
||||
emit_op,
|
||||
srConfig,
|
||||
emit_fetch,
|
||||
srVBufInfo;
|
||||
|
||||
type
|
||||
|
@ -30,11 +30,7 @@ type
|
|||
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;
|
||||
TEmit_vbuf_chain=class(TEmitFetch)
|
||||
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;
|
||||
|
@ -44,76 +40,6 @@ type
|
|||
|
||||
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;
|
||||
|
@ -123,7 +49,7 @@ begin
|
|||
adr.soffset:=get_soffset_const_int(FSPI.MUBUF.SOFFSET);
|
||||
end else
|
||||
begin
|
||||
ofs:=FRegsStory.get_ssrc8(FSPI.MUBUF.SOFFSET);
|
||||
ofs:=get_ssrc8(FSPI.MUBUF.SOFFSET);
|
||||
if (ofs<>nil) then
|
||||
begin
|
||||
adr.sof:=ofs^.current;
|
||||
|
@ -131,7 +57,7 @@ begin
|
|||
begin
|
||||
if (adr.sof^.is_const) then
|
||||
begin
|
||||
adr.soffset:=adr.sof^.AsConst^.AsInt;
|
||||
adr.soffset:=adr.sof^.AsConst^.AsInt32;
|
||||
adr.sof:=nil;
|
||||
end else
|
||||
begin
|
||||
|
@ -147,12 +73,12 @@ 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);
|
||||
ofs:=get_vsrc8(FSPI.MUBUF.VADDR+1);
|
||||
end;
|
||||
end else
|
||||
if (FSPI.MUBUF.OFFEN=1) then
|
||||
begin
|
||||
ofs:=FRegsStory.get_vsrc8(FSPI.MUBUF.VADDR+0);
|
||||
ofs:=get_vsrc8(FSPI.MUBUF.VADDR+0);
|
||||
end;
|
||||
|
||||
if (ofs<>nil) then
|
||||
|
@ -162,7 +88,7 @@ begin
|
|||
begin
|
||||
if (adr.ofs^.is_const) then
|
||||
begin
|
||||
adr.voffset:=adr.ofs^.AsConst^.AsInt;
|
||||
adr.voffset:=adr.ofs^.AsConst^.AsInt32;
|
||||
adr.ofs:=nil;
|
||||
end else
|
||||
begin
|
||||
|
@ -190,15 +116,13 @@ begin
|
|||
//(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
|
||||
ofs_d:=OpIDivTo(adr.ofs,adr.align); //ofs/Align
|
||||
sum_d:=OpIAddTo(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);
|
||||
idx_m:=OpIMulTo(adr.idx,adr.stride div adr.align); //idx*(stride/Align)
|
||||
sum_d:=OpIAddTo(sum_d,idx_m);
|
||||
end;
|
||||
|
||||
end else
|
||||
|
@ -206,17 +130,15 @@ begin
|
|||
|
||||
//result=(foffset+ofs+idx*stride)/Align in elem
|
||||
|
||||
adr.ofs^.mark_unread;
|
||||
sum_d:=OpAddTo(adr.ofs,foffset); //foffset+ofs
|
||||
sum_d:=OpIAddTo(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);
|
||||
idx_m:=OpIMulTo(adr.idx,adr.stride); //idx*stride
|
||||
sum_d:=OpIAddTo(sum_d,idx_m);
|
||||
end;
|
||||
|
||||
sum_d:=OpDivTo(sum_d,adr.align); // sum/Align
|
||||
sum_d:=OpIDivTo(sum_d,adr.align); // sum/Align
|
||||
end;
|
||||
|
||||
Result:=sum_d;
|
||||
|
@ -236,13 +158,11 @@ begin
|
|||
|
||||
if (adr.idx=nil) then
|
||||
begin
|
||||
sum_d:=FetchReg(FConsts.Fetchi(dtUint32,foffset));
|
||||
sum_d^.mark_unread;
|
||||
sum_d:=NewReg_q(dtUint32,foffset);
|
||||
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);
|
||||
idx_m:=OpIMulTo(adr.idx,adr.stride div adr.align); //idx*(stride/Align)
|
||||
sum_d:=OpIAddTo(idx_m,foffset);
|
||||
end;
|
||||
|
||||
Result:=sum_d;
|
||||
|
@ -262,13 +182,11 @@ begin
|
|||
|
||||
if (adr.idx=nil) then
|
||||
begin
|
||||
sum_d:=FetchReg(FConsts.Fetchi(dtUint32,foffset));
|
||||
sum_d^.mark_unread;
|
||||
sum_d:=NewReg_q(dtUint32,foffset);
|
||||
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);
|
||||
idx_m:=OpIMulTo(adr.idx,adr.stride div adr.fsize); //idx*(stride/size)
|
||||
sum_d:=OpIAddTo(idx_m,foffset);
|
||||
end;
|
||||
|
||||
Result:=sum_d;
|
||||
|
@ -288,7 +206,8 @@ var
|
|||
|
||||
sum_d:PsrRegNode;
|
||||
|
||||
ext:TsrChainExt;
|
||||
lvl_0:TsrChainLvl_0;
|
||||
lvl_1:TsrChainLvl_1;
|
||||
|
||||
img:TsrImageInfo;
|
||||
|
||||
|
@ -322,9 +241,11 @@ begin
|
|||
if (adr.ofs=nil) and (adr.idx=nil) then //simple
|
||||
begin
|
||||
|
||||
Result.vType :=vcChainVector;
|
||||
Result.data[0]:=info.grp^.Fetch(foffset,adr.csize,nil);
|
||||
lvl_0.offset:=foffset;
|
||||
lvl_0.size :=adr.csize;
|
||||
Result.data[0]:=info.grp^.Fetch(@lvl_0,nil);
|
||||
|
||||
Result.vType :=vcChainVector;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
|
@ -335,7 +256,7 @@ begin
|
|||
sum_d:=get_sum_ofs(adr);
|
||||
|
||||
//minTexelBufferOffsetAlignment
|
||||
if FUseTexelBuffer then
|
||||
if Config.UseTexelBuffer then
|
||||
if (info.IsComp) and
|
||||
(adr.stride div adr.align=0) then
|
||||
begin
|
||||
|
@ -350,21 +271,21 @@ begin
|
|||
Exit;
|
||||
end;
|
||||
|
||||
sum_d^.mark_read;
|
||||
ext:=Default(TsrChainExt);
|
||||
ext.pIndex:=sum_d;
|
||||
ext.stride:=adr.align;
|
||||
lvl_0.offset:=0;
|
||||
lvl_0.size :=adr.align;
|
||||
|
||||
lvl_1.pIndex:=sum_d;
|
||||
lvl_1.stride:=adr.align;
|
||||
|
||||
Result.data[0]:=info.grp^.Fetch(@lvl_0,@lvl_1);
|
||||
|
||||
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 Config.UseTexelBuffer then
|
||||
if (info.IsComp) and
|
||||
(adr.stride mod adr.fsize=0) and
|
||||
(foffset mod adr.fsize=0) then
|
||||
|
@ -383,7 +304,7 @@ begin
|
|||
end;
|
||||
|
||||
//minTexelBufferOffsetAlignment
|
||||
if FUseTexelBuffer then
|
||||
if Config.UseTexelBuffer then
|
||||
if (info.IsComp) and
|
||||
(adr.stride div adr.align=0) then
|
||||
begin
|
||||
|
@ -400,14 +321,15 @@ begin
|
|||
Exit;
|
||||
end;
|
||||
|
||||
//adr.idx^.mark_read;
|
||||
ext:=Default(TsrChainExt);
|
||||
ext.pIndex:=adr.idx;
|
||||
ext.stride:=adr.stride;
|
||||
lvl_0.offset:=foffset;
|
||||
lvl_0.size :=adr.csize;
|
||||
|
||||
lvl_1.pIndex:=adr.idx;
|
||||
lvl_1.stride:=adr.stride;
|
||||
|
||||
Result.data[0]:=info.grp^.Fetch(@lvl_0,@lvl_1);
|
||||
|
||||
Result.vType :=vcChainVector;
|
||||
Result.data[0]:=info.grp^.Fetch(foffset,adr.csize,@ext);
|
||||
|
||||
Exit;
|
||||
end;
|
||||
|
||||
|
|
|
@ -6,14 +6,11 @@ interface
|
|||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srConst,
|
||||
srType,
|
||||
srReg,
|
||||
srLayout,
|
||||
SprvEmit,
|
||||
emit_op,
|
||||
emit_fetch,
|
||||
srVBufInfo,
|
||||
emit_vbuf_chain;
|
||||
|
||||
|
@ -29,21 +26,15 @@ type
|
|||
elm:array[0..3] of PsrRegNode;
|
||||
end;
|
||||
|
||||
TEmit_vbuf_load=object(TEmitOp)
|
||||
TEmit_vbuf_load=class(TEmitFetch)
|
||||
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);
|
||||
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;
|
||||
|
||||
|
@ -53,7 +44,7 @@ procedure TEmit_vbuf_load.buf_load(info:TBuf_info);
|
|||
var
|
||||
v:TvarChain;
|
||||
begin
|
||||
v:=TEmit_vbuf_chain(Self).get_chain(info);
|
||||
v:=TEmit_vbuf_chain(TObject(Self)).get_chain(info);
|
||||
|
||||
if (v.vType=vcUniformVector) then
|
||||
begin
|
||||
|
@ -64,131 +55,77 @@ begin
|
|||
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;
|
||||
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));
|
||||
Result:=OpUToF(src,dtFloat32);
|
||||
Result:=OpFMulToS(Result,1/lc.elem_orig.High);
|
||||
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);
|
||||
Result:=OpSToF(src,dtFloat32);
|
||||
Result:=OpFMulToS(Result,1/(lc.elem_orig.High shr 1));
|
||||
Result:=OpFAddToS(Result,-1);
|
||||
end;
|
||||
|
||||
BUF_NUM_FORMAT_USCALED : //Unsigned integer to float [0.0 .. (1<<nbits)-1]
|
||||
begin
|
||||
Result:=OpUToF(src);
|
||||
Result:=OpUToF(src,dtFloat32);
|
||||
end;
|
||||
|
||||
BUF_NUM_FORMAT_SSCALED : //Signed integer to float [-(1<<(nbits-1)) ..(1<<(nbits-1))-1]
|
||||
begin
|
||||
Result:=OpSToF(src);
|
||||
Result:=OpSToF(src,dtFloat32);
|
||||
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));
|
||||
Result:=OpSToF(src,dtFloat32);
|
||||
Result:=OpFMulToS(Result,2);
|
||||
Result:=OpFAddToS(Result,1);
|
||||
Result:=OpFMulToS(Result,1/lc.elem_orig.High);
|
||||
end else
|
||||
begin
|
||||
Result:=OpShlI(src,1);
|
||||
Result:=OpAddI(Result,1);
|
||||
Result:=OpSToF(Result);
|
||||
Result:=OpMulF(Result,1/GetTypeHigh(lc.elem_orig));
|
||||
Result:=OpShlTo(src,1);
|
||||
Result:=OpIAddTo(Result,1);
|
||||
Result:=OpSToF(Result,dtFloat32);
|
||||
Result:=OpFMulToS(Result,1/lc.elem_orig.High);
|
||||
end;
|
||||
end;
|
||||
|
||||
BUF_NUM_FORMAT_UINT :
|
||||
begin
|
||||
Result:=NewReg(lc.elem_resl);
|
||||
src^.mark_read;
|
||||
_emit_Op1(line,Op.OpUConvert,Result,src);
|
||||
Result:=OpUToU(src,lc.elem_resl);
|
||||
end;
|
||||
|
||||
BUF_NUM_FORMAT_SINT :
|
||||
begin
|
||||
Result:=NewReg(lc.elem_resl);
|
||||
src^.mark_read;
|
||||
_emit_Op1(line,Op.OpSConvert,Result,src);
|
||||
Result:=OpSToS(src,lc.elem_resl);
|
||||
end;
|
||||
|
||||
BUF_NUM_FORMAT_FLOAT :
|
||||
begin
|
||||
Result:=NewReg(lc.elem_resl);
|
||||
src^.mark_read;
|
||||
_emit_Op1(line,Op.OpFConvert,Result,src);
|
||||
Result:=OpFToF(src,lc.elem_resl);
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_load._make_load_cv_id(var lc:Tload_cache;i:Byte);
|
||||
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));
|
||||
rsl:=FetchLoad(lc.v.data[0],lc.elem_orig.AsVector(lc.elem_count));
|
||||
lc.rsl:=rsl;
|
||||
end;
|
||||
|
||||
|
@ -197,17 +134,16 @@ begin
|
|||
|
||||
if (lc.elem_count=1) then
|
||||
begin
|
||||
rsl:=_convert_e(lc,rsl);
|
||||
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);
|
||||
OpExtract(line,lc.elm[i],rsl,i);
|
||||
|
||||
lc.elm[i]:=_convert_e(lc,lc.elm[i]);
|
||||
lc.elm[i]:=convert_e(lc,lc.elm[i]);
|
||||
end;
|
||||
|
||||
end;
|
||||
|
@ -215,37 +151,39 @@ begin
|
|||
MakeCopy(lc.dst,lc.elm[i]);
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_load._make_load_ce_id(var lc:Tload_cache;i:Byte);
|
||||
procedure TEmit_vbuf_load.make_load_ce_id(var lc:Tload_cache;i:Byte);
|
||||
var
|
||||
orig,elm:PsrChain;
|
||||
sum_d:PsrRegNode;
|
||||
ext:TsrChainExt;
|
||||
lvl_0:TsrChainLvl_0;
|
||||
lvl_1:TsrChainLvl_1;
|
||||
rsl:PsrRegNode;
|
||||
begin
|
||||
|
||||
if (lc.elm[i]=nil) then
|
||||
begin
|
||||
orig:=lc.v.data[0];
|
||||
sum_d:=orig^.key.ext.pIndex;
|
||||
sum_d:=orig^.pIndex;
|
||||
|
||||
if (i=0) then
|
||||
begin
|
||||
elm:=orig;
|
||||
end else
|
||||
begin
|
||||
sum_d:=TEmit_vbuf_chain(Self).OpAddTo(sum_d,i);
|
||||
sum_d:=OpIAddTo(sum_d,i);
|
||||
|
||||
sum_d^.mark_read;
|
||||
ext:=Default(TsrChainExt);
|
||||
ext.pIndex:=sum_d;
|
||||
ext.stride:=orig^.key.ext.stride;
|
||||
lvl_0.offset:=0;
|
||||
lvl_0.size :=orig^.size;
|
||||
|
||||
elm:=lc.info.grp^.Fetch(0,orig^.key.size,@ext);
|
||||
lvl_1.pIndex:=sum_d;
|
||||
lvl_1.stride:=orig^.stride;
|
||||
|
||||
elm:=lc.info.grp^.Fetch(@lvl_0,@lvl_1);
|
||||
end;
|
||||
|
||||
rsl:=FetchLoad(elm,lc.elem_orig);
|
||||
|
||||
rsl:=_convert_e(lc,rsl);
|
||||
rsl:=convert_e(lc,rsl);
|
||||
|
||||
lc.elm[i]:=rsl;
|
||||
end;
|
||||
|
@ -253,7 +191,7 @@ begin
|
|||
MakeCopy(lc.dst,lc.elm[i]);
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_load._make_load_uv_id(var lc:Tload_cache;i:Byte);
|
||||
procedure TEmit_vbuf_load.make_load_uv_id(var lc:Tload_cache;i:Byte);
|
||||
var
|
||||
rsl,idx:PsrRegNode;
|
||||
begin
|
||||
|
@ -261,20 +199,18 @@ begin
|
|||
rsl:=lc.rsl;
|
||||
if (rsl=nil) then
|
||||
begin
|
||||
rsl:=NewReg(GetVecType(lc.elem_resl,4));
|
||||
rsl:=NewReg(lc.elem_resl.AsVector(4));
|
||||
idx:=lc.v.data[1];
|
||||
|
||||
idx^.mark_read;
|
||||
emit_OpImageRead(line,lc.v.data[0],rsl,idx);
|
||||
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);
|
||||
OpExtract(line,lc.dst^.current,rsl,i);
|
||||
|
||||
lc.elm[i]:=lc.dst^.current;
|
||||
end else
|
||||
|
@ -283,7 +219,7 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_load._make_load_ue_id(var lc:Tload_cache;i:Byte);
|
||||
procedure TEmit_vbuf_load.make_load_ue_id(var lc:Tload_cache;i:Byte);
|
||||
var
|
||||
rsl,idx,sum_d:PsrRegNode;
|
||||
begin
|
||||
|
@ -297,13 +233,12 @@ begin
|
|||
sum_d:=idx;
|
||||
end else
|
||||
begin
|
||||
sum_d:=TEmit_vbuf_chain(Self).OpAddTo(idx,i);
|
||||
sum_d:=OpIAddTo(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);
|
||||
OpImageRead(line,lc.v.data[0],rsl,sum_d);
|
||||
|
||||
lc.elm[i]:=rsl;
|
||||
end else
|
||||
|
@ -312,19 +247,19 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_load._make_load_zero(var lc:Tload_cache);
|
||||
procedure TEmit_vbuf_load.make_load_zero(var lc:Tload_cache);
|
||||
begin
|
||||
SetConst(lc.dst,FConsts.Fetchi(lc.elem_resl,0));
|
||||
SetConst_i(lc.dst,lc.elem_resl,0);
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_load._make_load_one(var lc:Tload_cache);
|
||||
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));
|
||||
SetConst_s(lc.dst,lc.elem_resl,1);
|
||||
end else
|
||||
begin
|
||||
SetConst(lc.dst,FConsts.Fetchi(lc.elem_resl,1));
|
||||
SetConst_i(lc.dst,lc.elem_resl,1);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -348,16 +283,16 @@ begin
|
|||
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
lc.dst:=FRegsStory.get_vdst8(FSPI.MUBUF.VDATA+i);
|
||||
lc.dst:=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);
|
||||
make_load_zero(lc);
|
||||
end;
|
||||
1:begin //1
|
||||
_make_load_one(lc);
|
||||
make_load_one(lc);
|
||||
end;
|
||||
4..7:
|
||||
begin //RGBA
|
||||
|
@ -367,22 +302,22 @@ begin
|
|||
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);
|
||||
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);
|
||||
make_load_zero(lc);
|
||||
end;
|
||||
|
||||
end;
|
||||
else
|
||||
begin //as zero
|
||||
_make_load_zero(lc);
|
||||
make_load_zero(lc);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
|
@ -7,12 +7,10 @@ interface
|
|||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srConst,
|
||||
srType,
|
||||
srReg,
|
||||
srLayout,
|
||||
SprvEmit,
|
||||
emit_op,
|
||||
emit_fetch,
|
||||
srVBufInfo,
|
||||
emit_vbuf_chain;
|
||||
|
||||
|
@ -26,15 +24,15 @@ type
|
|||
elm:array[0..3] of PsrRegNode;
|
||||
end;
|
||||
|
||||
TEmit_vbuf_store=object(TEmitOp)
|
||||
TEmit_vbuf_store=class(TEmitFetch)
|
||||
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);
|
||||
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;
|
||||
|
||||
|
@ -44,7 +42,7 @@ procedure TEmit_vbuf_store.buf_store(info:TBuf_info);
|
|||
var
|
||||
v:TvarChain;
|
||||
begin
|
||||
v:=TEmit_vbuf_chain(Self).get_chain(info);
|
||||
v:=TEmit_vbuf_chain(TObject(Self)).get_chain(info);
|
||||
|
||||
if (v.vType=vcUniformVector) then
|
||||
begin
|
||||
|
@ -58,25 +56,25 @@ begin
|
|||
buf_store_cv(info,v);
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_store._fetch_id(var lc:Tstore_cache;i:Byte):PsrRegNode;
|
||||
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;
|
||||
function TEmit_vbuf_store.fetch_zero(var lc:Tstore_cache):PsrRegNode;
|
||||
begin
|
||||
Result:=FetchReg(FConsts.Fetchi(lc.elem_resl,0));
|
||||
Result:=NewReg_q(lc.elem_resl,0);
|
||||
end;
|
||||
|
||||
function TEmit_vbuf_store._fetch_one(var lc:Tstore_cache):PsrRegNode;
|
||||
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));
|
||||
Result:=NewReg_s(lc.elem_resl,1);
|
||||
end else
|
||||
begin
|
||||
Result:=FetchReg(FConsts.Fetchi(lc.elem_resl,1));
|
||||
Result:=NewReg_i(lc.elem_resl,1);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -85,23 +83,24 @@ begin
|
|||
if (a<b) then Result:=a else Result:=b;
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_store._make_store_cv(var lc:Tstore_cache);
|
||||
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;
|
||||
lvl_0:TsrChainLvl_0;
|
||||
lvl_1:TsrChainLvl_1;
|
||||
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);
|
||||
1:lc.elm[i]:=fetch_one(lc);
|
||||
else
|
||||
lc.elm[i]:=_fetch_zero(lc);
|
||||
lc.elm[i]:=fetch_zero(lc);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -109,8 +108,7 @@ begin
|
|||
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;
|
||||
rsl:=OpMakeVec(line,lc.elem_resl.AsVector(lc.elem_count),@lc.elm);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -119,19 +117,24 @@ begin
|
|||
csize:=Min(lc.info.GetElemSize*lc.elem_count,lc.info.GetSizeFormat);
|
||||
orig:=lc.v.data[0];
|
||||
|
||||
if (orig^.key.size<>csize) then //refetch
|
||||
if (orig^.size<>csize) then //refetch
|
||||
begin
|
||||
idx:=orig^.key.ext.pIndex;
|
||||
idx:=orig^.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);
|
||||
lvl_0.offset:=orig^.offset;
|
||||
lvl_0.size :=csize;
|
||||
|
||||
lvl_1.pIndex:=idx;
|
||||
lvl_1.stride:=orig^.stride;
|
||||
|
||||
new:=lc.info.grp^.Fetch(@lvl_0,@lvl_1);
|
||||
end else
|
||||
begin
|
||||
new:=lc.info.grp^.Fetch(orig^.key.offset,csize,nil);
|
||||
lvl_0.offset:=orig^.offset;
|
||||
lvl_0.size :=csize;
|
||||
|
||||
new:=lc.info.grp^.Fetch(@lvl_0,nil);
|
||||
end;
|
||||
orig:=new;
|
||||
end;
|
||||
|
@ -139,15 +142,16 @@ begin
|
|||
FetchStore(orig,rsl);
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_store._make_store_ce(var lc:Tstore_cache);
|
||||
procedure TEmit_vbuf_store.make_store_ce(var lc:Tstore_cache);
|
||||
var
|
||||
orig,elm:PsrChain;
|
||||
sum_d:PsrRegNode;
|
||||
ext:TsrChainExt;
|
||||
lvl_0:TsrChainLvl_0;
|
||||
lvl_1:TsrChainLvl_1;
|
||||
i:Byte;
|
||||
begin
|
||||
orig:=lc.v.data[0];
|
||||
sum_d:=orig^.key.ext.pIndex;
|
||||
sum_d:=orig^.pIndex;
|
||||
|
||||
For i:=0 to lc.elem_count-1 do
|
||||
if (lc.elm[i]<>nil) then
|
||||
|
@ -158,14 +162,15 @@ begin
|
|||
elm:=orig;
|
||||
end else
|
||||
begin
|
||||
sum_d:=TEmit_vbuf_chain(Self).OpAddTo(sum_d,i);
|
||||
sum_d:=OpIAddTo(sum_d,i);
|
||||
|
||||
sum_d^.mark_read;
|
||||
ext:=Default(TsrChainExt);
|
||||
ext.pIndex:=sum_d;
|
||||
ext.stride:=orig^.key.ext.stride;
|
||||
lvl_0.offset:=0;
|
||||
lvl_0.size :=orig^.size;
|
||||
|
||||
elm:=lc.info.grp^.Fetch(0,orig^.key.size,@ext);
|
||||
lvl_1.pIndex:=sum_d;
|
||||
lvl_1.stride:=orig^.stride;
|
||||
|
||||
elm:=lc.info.grp^.Fetch(@lvl_0,@lvl_1);
|
||||
end;
|
||||
|
||||
Assert(lc.elem_resl=lc.elem_orig,'TODO CONVERT');
|
||||
|
@ -176,7 +181,7 @@ begin
|
|||
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_store._make_store_uv(var lc:Tstore_cache);
|
||||
procedure TEmit_vbuf_store.make_store_uv(var lc:Tstore_cache);
|
||||
var
|
||||
rsl,idx:PsrRegNode;
|
||||
i:Byte;
|
||||
|
@ -186,9 +191,9 @@ begin
|
|||
if (lc.elm[i]=nil) then
|
||||
begin
|
||||
Case lc.info.dsel[i] of
|
||||
1:lc.elm[i]:=_fetch_one(lc);
|
||||
1:lc.elm[i]:=fetch_one(lc);
|
||||
else
|
||||
lc.elm[i]:=_fetch_zero(lc);
|
||||
lc.elm[i]:=fetch_zero(lc);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -196,18 +201,16 @@ begin
|
|||
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;
|
||||
rsl:=OpMakeVec(line,lc.elem_resl.AsVector(lc.elem_count),@lc.elm);
|
||||
end;
|
||||
end;
|
||||
|
||||
idx:=lc.v.data[1];
|
||||
idx^.mark_read;
|
||||
rsl^.mark_read;
|
||||
emit_OpImageWrite(line,lc.v.data[0],idx,rsl);
|
||||
|
||||
OpImageWrite(line,lc.v.data[0],idx,rsl);
|
||||
end;
|
||||
|
||||
procedure TEmit_vbuf_store._make_store_ue(var lc:Tstore_cache);
|
||||
procedure TEmit_vbuf_store.make_store_ue(var lc:Tstore_cache);
|
||||
var
|
||||
sum_d,idx,rsl:PsrRegNode;
|
||||
i:Byte;
|
||||
|
@ -224,12 +227,10 @@ begin
|
|||
sum_d:=idx;
|
||||
end else
|
||||
begin
|
||||
sum_d:=TEmit_vbuf_chain(Self).OpAddTo(idx,i);
|
||||
sum_d:=OpIAddTo(idx,i);
|
||||
end;
|
||||
|
||||
sum_d^.mark_read;
|
||||
rsl^.mark_read;
|
||||
emit_OpImageWrite(line,lc.v.data[0],sum_d,rsl);
|
||||
OpImageWrite(line,lc.v.data[0],sum_d,rsl);
|
||||
|
||||
end;
|
||||
end;
|
||||
|
@ -261,7 +262,7 @@ begin
|
|||
Case lc.info.dsel[i] of
|
||||
4..7:
|
||||
begin //RGBA
|
||||
lc.elm[i]:=_fetch_id(lc,lc.info.dsel[i]-4);
|
||||
lc.elm[i]:=fetch_id(lc,lc.info.dsel[i]-4);
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
|
@ -277,10 +278,10 @@ begin
|
|||
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)
|
||||
vcChainVector :make_store_cv(lc);
|
||||
vcChainElement :make_store_ce(lc);
|
||||
vcUniformVector :make_store_uv(lc);
|
||||
vcUniformElement:make_store_ue(lc)
|
||||
else;
|
||||
end;
|
||||
|
||||
|
|
|
@ -6,22 +6,21 @@ interface
|
|||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srType,
|
||||
srInput,
|
||||
srReg,
|
||||
spirv,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
emit_fetch;
|
||||
|
||||
type
|
||||
TEmit_VINTRP=object(TEmitOp)
|
||||
procedure _emit_VINTRP;
|
||||
TEmit_VINTRP=class(TEmitFetch)
|
||||
procedure emit_VINTRP;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_VINTRP._emit_VINTRP;
|
||||
procedure TEmit_VINTRP.emit_VINTRP;
|
||||
var
|
||||
inp_M0:PsrInput;
|
||||
|
||||
|
@ -35,23 +34,23 @@ var
|
|||
begin
|
||||
Assert(FExecutionModel=ExecutionModel.Fragment); //only pixel shader
|
||||
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VINTRP.VDST);
|
||||
dst:=get_vdst8(FSPI.VINTRP.VDST);
|
||||
|
||||
inp_M0:=GetInputRegNode(FRegsStory.M0.current);
|
||||
inp_M0:=GetInputRegNode(get_m0^.current);
|
||||
|
||||
Assert(inp_M0<>nil);
|
||||
Assert(inp_M0^.key.itype=itPsState);
|
||||
Assert(inp_M0^.itype=itPsState);
|
||||
|
||||
Case FSPI.VINTRP.OP of
|
||||
V_INTERP_P1_F32:
|
||||
begin
|
||||
src:=FRegsStory.get_vsrc8(FSPI.VINTRP.VSRC);
|
||||
src:=get_vsrc8(FSPI.VINTRP.VSRC);
|
||||
|
||||
inp_SRC:=GetInputRegNode(src^.current);
|
||||
|
||||
Assert(inp_SRC<>nil);
|
||||
|
||||
Case inp_SRC^.key.itype of
|
||||
Case inp_SRC^.itype of
|
||||
itPerspSample,
|
||||
itPerspCenter, //barycentrics with perspective interpolation
|
||||
itPerspCentroid,
|
||||
|
@ -62,24 +61,23 @@ begin
|
|||
Assert(false);
|
||||
end;
|
||||
|
||||
Assert(inp_SRC^.key.typeid=0); //I
|
||||
Assert(inp_SRC^.typeid=0); //I
|
||||
|
||||
rsl:=AddFragLayout(inp_SRC^.key.itype,dtVec4f,FSPI.VINTRP.ATTR);
|
||||
rsl^.mark_read;
|
||||
rsl:=AddFragLayout(inp_SRC^.itype,dtVec4f,FSPI.VINTRP.ATTR);
|
||||
|
||||
dst^.New(line,dtFloat32);
|
||||
emit_OpCompExtract(line,dst^.current,rsl,FSPI.VINTRP.ATTRCHAN);
|
||||
OpExtract(line,dst^.current,rsl,FSPI.VINTRP.ATTRCHAN);
|
||||
|
||||
end;
|
||||
V_INTERP_P2_F32:
|
||||
begin
|
||||
src:=FRegsStory.get_vsrc8(FSPI.VINTRP.VSRC);
|
||||
src:=get_vsrc8(FSPI.VINTRP.VSRC);
|
||||
|
||||
inp_SRC:=GetInputRegNode(src^.current);
|
||||
|
||||
Assert(inp_SRC<>nil);
|
||||
|
||||
Case inp_SRC^.key.itype of
|
||||
Case inp_SRC^.itype of
|
||||
itPerspSample,
|
||||
itPerspCenter, //barycentrics with perspective interpolation
|
||||
itPerspCentroid,
|
||||
|
@ -90,13 +88,12 @@ begin
|
|||
Assert(false);
|
||||
end;
|
||||
|
||||
Assert(inp_SRC^.key.typeid=1); //J
|
||||
Assert(inp_SRC^.typeid=1); //J
|
||||
|
||||
rsl:=AddFragLayout(inp_SRC^.key.itype,dtVec4f,FSPI.VINTRP.ATTR);
|
||||
rsl^.mark_read;
|
||||
rsl:=AddFragLayout(inp_SRC^.itype,dtVec4f,FSPI.VINTRP.ATTR);
|
||||
|
||||
dst^.New(line,dtFloat32);
|
||||
emit_OpCompExtract(line,dst^.current,rsl,FSPI.VINTRP.ATTRCHAN);
|
||||
OpExtract(line,dst^.current,rsl,FSPI.VINTRP.ATTRCHAN);
|
||||
|
||||
end;
|
||||
|
||||
|
|
|
@ -7,188 +7,153 @@ interface
|
|||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srReg,
|
||||
spirv,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
srType,
|
||||
srReg,
|
||||
emit_fetch;
|
||||
|
||||
type
|
||||
TEmit_VOP1=object(TEmitOp)
|
||||
procedure _emit_VOP1;
|
||||
procedure _emit_V_MOV_B32;
|
||||
procedure _emit_V_CVT(OpId:DWORD;dst_type,src_type:TsrDataType);
|
||||
procedure _emit_V_CVT_OFF_F32_I4;
|
||||
procedure _emit_V_CVT_F32_UBYTE0;
|
||||
procedure _emit_V_EXT_F32(OpId:DWORD);
|
||||
procedure _emit_V_RCP_F32;
|
||||
procedure _emit_V_FFBL_B32;
|
||||
TEmit_VOP1=class(TEmitFetch)
|
||||
procedure emit_VOP1;
|
||||
procedure emit_V_MOV_B32;
|
||||
procedure emit_V_CVT(OpId:DWORD;dst_type,src_type:TsrDataType);
|
||||
procedure emit_V_CVT_OFF_F32_I4;
|
||||
procedure emit_V_CVT_F32_UBYTE0;
|
||||
procedure emit_V_EXT_F32(OpId:DWORD);
|
||||
procedure emit_V_RCP_F32;
|
||||
procedure emit_V_FFBL_B32;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_VOP1._emit_V_MOV_B32;
|
||||
procedure TEmit_VOP1.emit_V_MOV_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
dst:=get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUnknow);
|
||||
_MakeCopy(dst,src);
|
||||
MakeCopy(dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_CVT(OpId:DWORD;dst_type,src_type:TsrDataType);
|
||||
procedure TEmit_VOP1.emit_V_CVT(OpId:DWORD;dst_type,src_type:TsrDataType);
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
dst:=get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,src_type);
|
||||
emit_Op1(OpId,dst_type,dst,src);
|
||||
Op1(OpId,dst_type,dst,src);
|
||||
end;
|
||||
|
||||
//V_CVT_OFF_F32_I4
|
||||
//([0..3]-8)/16
|
||||
procedure TEmit_VOP1._emit_V_CVT_OFF_F32_I4;
|
||||
procedure TEmit_VOP1.emit_V_CVT_OFF_F32_I4;
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
num_8:PsrRegNode;
|
||||
num_15:PsrRegNode;
|
||||
num_16:PsrRegNode;
|
||||
subi,subf:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
dst:=get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUInt32);
|
||||
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
num_15:=FetchReg(FConsts.Fetch(dtUInt32,15));
|
||||
src:=OpBitwiseAndTo(src,15);
|
||||
src^.PrepType(ord(dtInt32));
|
||||
|
||||
emit_OpBitwiseAnd(tmp,src,num_15);
|
||||
src:=MakeRead(tmp,dtUInt32);
|
||||
src:=OpISubTo(src,8);
|
||||
|
||||
num_8:=FetchReg(FConsts.Fetch(dtInt32,8));
|
||||
subi:=dst^.New(line,dtInt32);
|
||||
src:=OpSToF(src,dtFloat32);
|
||||
|
||||
_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);
|
||||
num_16:=NewReg_s(dtFloat32,16);
|
||||
Op2(Op.OpFDiv,dtFloat32,dst,src,num_16);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_CVT_F32_UBYTE0;
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
num_FF:PsrRegNode;
|
||||
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUInt32);
|
||||
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
num_FF:=FetchReg(FConsts.Fetch(dtUInt32,$FF));
|
||||
|
||||
emit_OpBitwiseAnd(tmp,src,num_FF);
|
||||
src:=MakeRead(tmp,dtUInt32);
|
||||
|
||||
emit_Op1(Op.OpConvertUToF,dtFloat32,dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_EXT_F32(OpId:DWORD);
|
||||
procedure TEmit_VOP1.emit_V_CVT_F32_UBYTE0;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32);
|
||||
emit_OpExt1(OpId,dtFloat32,dst,src);
|
||||
dst:=get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtUInt32);
|
||||
|
||||
src:=OpBitwiseAndTo(src,$FF);
|
||||
src^.PrepType(ord(dtUInt32));
|
||||
|
||||
Op1(Op.OpConvertUToF,dtFloat32,dst,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_RCP_F32;
|
||||
procedure TEmit_VOP1.emit_V_EXT_F32(OpId:DWORD);
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32);
|
||||
OpGlsl1(OpId,dtFloat32,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);
|
||||
dst:=get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtFloat32);
|
||||
|
||||
one:=FetchReg(FConsts.Fetchf(dtFloat32,1));
|
||||
one:=NewReg_s(dtFloat32,1);
|
||||
|
||||
emit_OpFDiv(dst,one,src);
|
||||
Op2(Op.OpFDiv,dtFloat32,dst,one,src);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP1._emit_V_FFBL_B32;
|
||||
procedure TEmit_VOP1.emit_V_FFBL_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP1.VDST);
|
||||
dst:=get_vdst8(FSPI.VOP1.VDST);
|
||||
src:=fetch_ssrc9(FSPI.VOP1.SRC0,dtInt32);
|
||||
|
||||
emit_OpExt1(GlslOp.FindILsb,dtInt32,dst,src);
|
||||
OpGlsl1(GlslOp.FindILsb,dtInt32,dst,src);
|
||||
end;
|
||||
|
||||
|
||||
procedure TEmit_VOP1._emit_VOP1;
|
||||
procedure TEmit_VOP1.emit_VOP1;
|
||||
begin
|
||||
|
||||
Case FSPI.VOP1.OP of
|
||||
|
||||
V_NOP:;
|
||||
|
||||
V_MOV_B32:
|
||||
begin
|
||||
_emit_V_MOV_B32;
|
||||
end;
|
||||
V_MOV_B32: emit_V_MOV_B32;
|
||||
|
||||
V_CVT_F32_I32: _emit_V_CVT(Op.OpConvertSToF,dtFloat32,dtInt32);
|
||||
V_CVT_F32_U32: _emit_V_CVT(Op.OpConvertUToF,dtFloat32,dtUInt32);
|
||||
V_CVT_U32_F32: _emit_V_CVT(Op.OpConvertFToU,dtUInt32 ,dtFloat32);
|
||||
V_CVT_I32_F32: _emit_V_CVT(Op.OpConvertFToS,dtInt32 ,dtFloat32);
|
||||
V_CVT_F32_I32: emit_V_CVT(Op.OpConvertSToF,dtFloat32,dtInt32);
|
||||
V_CVT_F32_U32: emit_V_CVT(Op.OpConvertUToF,dtFloat32,dtUInt32);
|
||||
V_CVT_U32_F32: emit_V_CVT(Op.OpConvertFToU,dtUInt32 ,dtFloat32);
|
||||
V_CVT_I32_F32: emit_V_CVT(Op.OpConvertFToS,dtInt32 ,dtFloat32);
|
||||
|
||||
V_CVT_OFF_F32_I4:
|
||||
begin
|
||||
_emit_V_CVT_OFF_F32_I4;
|
||||
end;
|
||||
V_CVT_OFF_F32_I4: emit_V_CVT_OFF_F32_I4;
|
||||
|
||||
V_CVT_F32_UBYTE0:
|
||||
begin
|
||||
_emit_V_CVT_F32_UBYTE0;
|
||||
end;
|
||||
V_CVT_F32_UBYTE0: emit_V_CVT_F32_UBYTE0;
|
||||
|
||||
V_FRACT_F32: _emit_V_EXT_F32(GlslOp.Fract);
|
||||
V_TRUNC_F32: _emit_V_EXT_F32(GlslOp.Trunc);
|
||||
V_CEIL_F32 : _emit_V_EXT_F32(GlslOp.Ceil);
|
||||
V_FRACT_F32: emit_V_EXT_F32(GlslOp.Fract);
|
||||
V_TRUNC_F32: emit_V_EXT_F32(GlslOp.Trunc);
|
||||
V_CEIL_F32 : emit_V_EXT_F32(GlslOp.Ceil);
|
||||
|
||||
V_FLOOR_F32: _emit_V_EXT_F32(GlslOp.Floor);
|
||||
V_EXP_F32 : _emit_V_EXT_F32(GlslOp.Exp2);
|
||||
V_LOG_F32 : _emit_V_EXT_F32(GlslOp.Log2);
|
||||
V_FLOOR_F32: emit_V_EXT_F32(GlslOp.Floor);
|
||||
V_EXP_F32 : emit_V_EXT_F32(GlslOp.Exp2);
|
||||
V_LOG_F32 : emit_V_EXT_F32(GlslOp.Log2);
|
||||
|
||||
V_RSQ_F32 : _emit_V_EXT_F32(GlslOp.InverseSqrt);
|
||||
V_RSQ_F32 : emit_V_EXT_F32(GlslOp.InverseSqrt);
|
||||
|
||||
V_SQRT_F32 : _emit_V_EXT_F32(GlslOp.Sqrt);
|
||||
V_SQRT_F32 : emit_V_EXT_F32(GlslOp.Sqrt);
|
||||
|
||||
V_SIN_F32 : _emit_V_EXT_F32(GlslOp.Sin);
|
||||
V_COS_F32 : _emit_V_EXT_F32(GlslOp.Cos);
|
||||
V_SIN_F32 : emit_V_EXT_F32(GlslOp.Sin);
|
||||
V_COS_F32 : emit_V_EXT_F32(GlslOp.Cos);
|
||||
|
||||
V_RCP_F32:
|
||||
begin
|
||||
_emit_V_RCP_F32;
|
||||
end;
|
||||
V_RCP_F32 : emit_V_RCP_F32;
|
||||
|
||||
V_FFBL_B32:
|
||||
begin
|
||||
_emit_V_FFBL_B32;
|
||||
end;
|
||||
V_FFBL_B32 : emit_V_FFBL_B32;
|
||||
|
||||
else
|
||||
Assert(false,'VOP1?'+IntToStr(FSPI.VOP1.OP));
|
||||
|
|
|
@ -8,506 +8,360 @@ uses
|
|||
sysutils,
|
||||
ps4_pssl,
|
||||
spirv,
|
||||
srTypes,
|
||||
srConst,
|
||||
srType,
|
||||
srReg,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
emit_fetch;
|
||||
|
||||
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_XOR_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_MAX(OpId:DWORD;rtype:TsrDataType);
|
||||
TEmit_VOP2=class(TEmitFetch)
|
||||
procedure emit_VOP2;
|
||||
procedure emit_V_CNDMASK_B32;
|
||||
procedure emit_V_AND_B32;
|
||||
procedure emit_V_OR_B32;
|
||||
procedure emit_V_XOR_B32;
|
||||
procedure emit_V_SH(OpId:DWORD;rtype:TsrDataType);
|
||||
procedure emit_V_SHREV(OpId:DWORD;rtype:TsrDataType);
|
||||
procedure emit_V_ADD_I32;
|
||||
procedure emit_V_SUB_I32;
|
||||
procedure emit_V_SUBREV_I32;
|
||||
procedure emit_V2_F32(OpId:DWORD);
|
||||
procedure emit_V_SUBREV_F32;
|
||||
procedure emit_V_CVT_PKRTZ_F16_F32;
|
||||
procedure emit_V_MUL_I32_I24;
|
||||
procedure emit_V_MUL_U32_U24;
|
||||
procedure emit_V_MAC_F32;
|
||||
procedure emit_V_MADAK_F32;
|
||||
procedure emit_V_MADMK_F32;
|
||||
procedure emit_V_MMX(OpId:DWORD;rtype:TsrDataType);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TEmit_VOP2._emit_V_CNDMASK_B32;
|
||||
procedure TEmit_VOP2.emit_V_CNDMASK_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
dst:=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);
|
||||
src[2]:=MakeRead(get_vcc0,dtBool);
|
||||
|
||||
emit_OpSelect(dst,src[0],src[1],src[2]);
|
||||
OpSelect(dst,src[0],src[1],src[2]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_AND_B32;
|
||||
procedure TEmit_VOP2.emit_V_AND_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
dst:=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]);
|
||||
OpBitwiseAnd(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_OR_B32;
|
||||
procedure TEmit_VOP2.emit_V_OR_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
dst:=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]);
|
||||
OpBitwiseOr(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_XOR_B32;
|
||||
procedure TEmit_VOP2.emit_V_XOR_B32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
dst:=get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,{dtUnknow}dtUInt32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,{dtUnknow}dtUInt32);
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUInt32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUInt32);
|
||||
|
||||
emit_OpBitwiseXor(dst,src[0],src[1]);
|
||||
OpBitwiseXor(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_LSHL_B32;
|
||||
procedure TEmit_VOP2.emit_V_SH(OpId:DWORD;rtype:TsrDataType);
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
dst:=get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,rtype);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32);
|
||||
|
||||
src[1]:=OpBitwiseAndTo(src[1],31);
|
||||
src[1]^.PrepType(ord(dtUInt32));
|
||||
|
||||
Op2(OpId,src[0]^.dtype,dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2.emit_V_SHREV(OpId:DWORD;rtype:TsrDataType);
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,rtype);
|
||||
|
||||
src[0]:=OpBitwiseAndTo(src[0],31);
|
||||
src[0]^.PrepType(ord(dtUInt32));
|
||||
|
||||
Op2(OpId,src[1]^.dtype,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:PsrRegNode;
|
||||
begin
|
||||
dst:=get_vdst8(FSPI.VOP2.VDST);
|
||||
car:=get_vcc0;
|
||||
|
||||
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);
|
||||
OpIAddExt(dst,car,src[0],src[1]);
|
||||
|
||||
emit_OpShl(dst,src[0],src[1]);
|
||||
exc:=MakeRead(get_exec0,dtUnknow);
|
||||
OpBitwiseAnd(car,car^.current,exc); //carry_out & EXEC
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_LSHLREV_B32;
|
||||
procedure TEmit_VOP2.emit_V_SUB_I32; //vdst = vsrc0.u - vsub.u; sdst[thread_id:] = borrow_out & EXEC
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
dst,bor:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
exc:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
dst:=get_vdst8(FSPI.VOP2.VDST);
|
||||
bor:=get_vcc0;
|
||||
|
||||
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);
|
||||
OpISubExt(dst,bor,src[0],src[1]);
|
||||
|
||||
emit_OpShl(dst,src[1],src[0]);
|
||||
exc:=MakeRead(get_exec0,dtUnknow);
|
||||
OpBitwiseAnd(bor,bor^.current,exc); //borrow_out & EXEC
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_LSHR_B32;
|
||||
procedure TEmit_VOP2.emit_V_SUBREV_I32; //vdst = vsrc1.u - vsub.u; sdst[thread_id:] = borrow_out & EXEC
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
dst,bor:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
exc:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
dst:=get_vdst8(FSPI.VOP2.VDST);
|
||||
bor:=get_vcc0;
|
||||
|
||||
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);
|
||||
OpISubExt(dst,bor,src[1],src[0]);
|
||||
|
||||
emit_OpShr(dst,src[0],src[1]);
|
||||
exc:=MakeRead(get_exec0,dtUnknow);
|
||||
OpBitwiseAnd(bor,bor^.current,exc); //borrow_out & EXEC
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_LSHRREV_B32;
|
||||
procedure TEmit_VOP2.emit_V2_F32(OpId:DWORD);
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
dst:=get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUint32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUint32);
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
|
||||
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]);
|
||||
Op2(OpId,dtFloat32,dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_ASHR_I32;
|
||||
procedure TEmit_VOP2.emit_V_SUBREV_F32;
|
||||
Var
|
||||
dst,tmp:PsrRegSlot;
|
||||
src:array[0..2] of PsrRegNode;
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
tmp:=@FRegsStory.FUnattach;
|
||||
dst:=get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
|
||||
Op2(Op.OpFSub,dtFloat32,dst,src[1],src[0]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2.emit_V_CVT_PKRTZ_F16_F32;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
|
||||
OpConvFloatToHalf2(dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2.emit_V_MUL_I32_I24;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
bit24:PsrRegNode;
|
||||
begin
|
||||
dst:=get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
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);
|
||||
bit24:=NewReg_q(dtUInt32,$FFFFFF);
|
||||
|
||||
emit_OpShrA(dst,src[1],src[0]);
|
||||
src[0]:=OpBitwiseAndTo(src[0],bit24);
|
||||
src[0]^.PrepType(ord(dtInt32));
|
||||
|
||||
src[1]:=OpBitwiseAndTo(src[1],bit24);
|
||||
src[1]^.PrepType(ord(dtInt32));
|
||||
|
||||
OpIMul(dst,src[0],src[1]);
|
||||
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;
|
||||
procedure TEmit_VOP2.emit_V_MUL_U32_U24;
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
bit24:PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
dst:=get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtUInt32);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtUInt32);
|
||||
|
||||
emit_OpFAdd(dst,src[0],src[1]);
|
||||
bit24:=NewReg_q(dtUInt32,$FFFFFF);
|
||||
|
||||
src[0]:=OpBitwiseAndTo(src[0],bit24);
|
||||
src[0]^.PrepType(ord(dtUInt32));
|
||||
|
||||
src[1]:=OpBitwiseAndTo(src[1],bit24);
|
||||
src[1]^.PrepType(ord(dtUInt32));
|
||||
|
||||
OpIMul(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
|
||||
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);
|
||||
dst:=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]);
|
||||
OpFmaF32(dst,src[0],src[1],src[2]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_MADAK_F32; //vdst = vsrc0.f * vsrc1.f + kadd.f
|
||||
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);
|
||||
dst:=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));
|
||||
src[2]:=NewReg_q(dtFloat32,FSPI.INLINE32);
|
||||
|
||||
emit_OpFmaF32(dst,src[0],src[1],src[2]);
|
||||
OpFmaF32(dst,src[0],src[1],src[2]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_MADMK_F32; //vdst = vsrc0.f * kmul.f + vadd.f
|
||||
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);
|
||||
dst:=get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,dtFloat32);
|
||||
src[1]:=FetchReg(FConsts.Fetch(dtFloat32,FSPI.INLINE32));
|
||||
src[1]:=NewReg_q(dtFloat32,FSPI.INLINE32);
|
||||
src[2]:=fetch_vsrc8(FSPI.VOP2.VSRC1,dtFloat32);
|
||||
|
||||
emit_OpFmaF32(dst,src[0],src[1],src[2]);
|
||||
OpFmaF32(dst,src[0],src[1],src[2]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_V_MIN_MAX(OpId:DWORD;rtype:TsrDataType);
|
||||
procedure TEmit_VOP2.emit_V_MMX(OpId:DWORD;rtype:TsrDataType);
|
||||
Var
|
||||
dst:PsrRegSlot;
|
||||
src:array[0..1] of PsrRegNode;
|
||||
begin
|
||||
dst:=FRegsStory.get_vdst8(FSPI.VOP2.VDST);
|
||||
dst:=get_vdst8(FSPI.VOP2.VDST);
|
||||
|
||||
src[0]:=fetch_ssrc9(FSPI.VOP2.SRC0 ,rtype);
|
||||
src[1]:=fetch_vsrc8(FSPI.VOP2.VSRC1,rtype);
|
||||
|
||||
emit_OpExt2(OpId,rtype,dst,src[0],src[1]);
|
||||
OpGlsl2(OpId,rtype,dst,src[0],src[1]);
|
||||
end;
|
||||
|
||||
procedure TEmit_VOP2._emit_VOP2;
|
||||
procedure TEmit_VOP2.emit_VOP2;
|
||||
begin
|
||||
|
||||
Case FSPI.VOP2.OP of
|
||||
|
||||
V_CNDMASK_B32:
|
||||
begin
|
||||
_emit_V_CNDMASK_B32;
|
||||
end;
|
||||
V_CNDMASK_B32: emit_V_CNDMASK_B32;
|
||||
|
||||
V_AND_B32:
|
||||
begin
|
||||
_emit_V_AND_B32;
|
||||
end;
|
||||
V_AND_B32 : emit_V_AND_B32;
|
||||
V_OR_B32 : emit_V_OR_B32;
|
||||
V_XOR_B32 : emit_V_XOR_B32;
|
||||
|
||||
V_OR_B32:
|
||||
begin
|
||||
_emit_V_OR_B32;
|
||||
end;
|
||||
V_LSHL_B32 : emit_V_SH(Op.OpShiftLeftLogical,dtUint32);
|
||||
V_LSHLREV_B32: emit_V_SHREV(Op.OpShiftLeftLogical,dtUint32);
|
||||
V_LSHR_B32 : emit_V_SH(Op.OpShiftRightLogical,dtUint32);
|
||||
V_LSHRREV_B32: emit_V_SHREV(Op.OpShiftRightLogical,dtUint32);
|
||||
V_ASHR_I32 : emit_V_SH(Op.OpShiftRightLogical,dtInt32);
|
||||
V_ASHRREV_I32: emit_V_SHREV(Op.OpShiftRightLogical,dtInt32);
|
||||
|
||||
V_XOR_B32:
|
||||
begin
|
||||
_emit_V_XOR_B32;
|
||||
end;
|
||||
V_ADD_I32 : emit_V_ADD_I32;
|
||||
V_SUB_I32 : emit_V_SUB_I32;
|
||||
V_SUBREV_I32 : emit_V_SUBREV_I32;
|
||||
|
||||
V_LSHL_B32:
|
||||
begin
|
||||
_emit_V_LSHL_B32;
|
||||
end;
|
||||
V_ADD_F32 : emit_V2_F32(Op.OpFAdd);
|
||||
V_SUB_F32 : emit_V2_F32(Op.OpFSub);
|
||||
V_SUBREV_F32 : emit_V_SUBREV_F32;
|
||||
|
||||
V_LSHLREV_B32:
|
||||
begin
|
||||
_emit_V_LSHLREV_B32;
|
||||
end;
|
||||
V_MUL_F32 :emit_V2_F32(Op.OpFMul);
|
||||
|
||||
V_LSHR_B32:
|
||||
begin
|
||||
_emit_V_LSHR_B32;
|
||||
end;
|
||||
V_CVT_PKRTZ_F16_F32: emit_V_CVT_PKRTZ_F16_F32;
|
||||
|
||||
V_LSHRREV_B32:
|
||||
begin
|
||||
_emit_V_LSHRREV_B32
|
||||
end;
|
||||
V_MUL_I32_I24: emit_V_MUL_I32_I24;
|
||||
V_MUL_U32_U24: emit_V_MUL_U32_U24;
|
||||
|
||||
V_ASHR_I32:
|
||||
begin
|
||||
_emit_V_ASHR_I32;
|
||||
end;
|
||||
V_MAC_F32 : emit_V_MAC_F32;
|
||||
V_MADAK_F32: emit_V_MADAK_F32;
|
||||
V_MADMK_F32: emit_V_MADMK_F32;
|
||||
|
||||
V_ASHRREV_I32:
|
||||
begin
|
||||
_emit_V_ASHRREV_I32
|
||||
end;
|
||||
V_MIN_LEGACY_F32: emit_V_MMX(GlslOp.NMin,dtFloat32);
|
||||
V_MAX_LEGACY_F32: emit_V_MMX(GlslOp.NMax,dtFloat32);
|
||||
|
||||
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_MIN_F32: emit_V_MMX(GlslOp.FMin,dtFloat32);
|
||||
V_MAX_F32: emit_V_MMX(GlslOp.FMax,dtFloat32);
|
||||
|
||||
V_SUB_I32:
|
||||
begin
|
||||
_emit_V_SUB_I32;
|
||||
end;
|
||||
V_MIN_I32: emit_V_MMX(GlslOp.SMin,dtInt32);
|
||||
V_MAX_I32: emit_V_MMX(GlslOp.SMax,dtInt32);
|
||||
|
||||
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_LEGACY_F32:_emit_V_MIN_MAX(GlslOp.NMin,dtFloat32);
|
||||
V_MAX_LEGACY_F32:_emit_V_MIN_MAX(GlslOp.NMax,dtFloat32);
|
||||
|
||||
V_MIN_F32:_emit_V_MIN_MAX(GlslOp.FMin,dtFloat32);
|
||||
V_MAX_F32:_emit_V_MIN_MAX(GlslOp.FMax,dtFloat32);
|
||||
|
||||
V_MIN_I32:_emit_V_MIN_MAX(GlslOp.SMin,dtInt32);
|
||||
V_MAX_I32:_emit_V_MIN_MAX(GlslOp.SMax,dtInt32);
|
||||
|
||||
V_MIN_U32:_emit_V_MIN_MAX(GlslOp.UMin,dtUint32);
|
||||
V_MAX_U32:_emit_V_MIN_MAX(GlslOp.UMax,dtUint32);
|
||||
V_MIN_U32: emit_V_MMX(GlslOp.UMin,dtUint32);
|
||||
V_MAX_U32: emit_V_MMX(GlslOp.UMax,dtUint32);
|
||||
|
||||
else
|
||||
Assert(false,'VOP2?'+IntToStr(FSPI.VOP2.OP));
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -7,60 +7,59 @@ interface
|
|||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srType,
|
||||
srReg,
|
||||
spirv,
|
||||
SprvEmit,
|
||||
emit_op;
|
||||
emit_fetch;
|
||||
|
||||
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);
|
||||
TEmit_VOPC=class(TEmitFetch)
|
||||
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);
|
||||
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];
|
||||
dst[0]:=get_vcc0;
|
||||
dst[1]:=get_vcc1;
|
||||
|
||||
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]);
|
||||
OpCmpV(OpId,dst[0],src[0],src[1]);
|
||||
|
||||
SetConst(dst[1],dtUnknow,0); //set zero
|
||||
SetConst_q(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
|
||||
MakeCopy(get_exec0,dst[0]^.current);
|
||||
SetConst_q(get_exec1,dtUnknow,0); //set zero
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_VOPC._emit_V_CMP_C(r,x:Boolean);
|
||||
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];
|
||||
dst[0]:=get_vcc0;
|
||||
dst[1]:=get_vcc1;
|
||||
|
||||
SetConst(dst[0],dtBool,QWORD(r));
|
||||
SetConst(dst[1],dtUnknow,0); //set zero
|
||||
SetConst_b(dst[0],r);
|
||||
SetConst_q(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
|
||||
MakeCopy(get_exec0,dst[0]^.current);
|
||||
SetConst_q(get_exec1,dtUnknow,0); //set zero
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TEmit_VOPC._emit_VOPC;
|
||||
procedure TEmit_VOPC.emit_VOPC;
|
||||
begin
|
||||
|
||||
Case FSPI.VOPC.OP of
|
||||
|
@ -72,7 +71,7 @@ begin
|
|||
V_CMP_F_U32,
|
||||
V_CMP_F_U64,
|
||||
V_CMPS_F_F32,
|
||||
V_CMPS_F_F64:_emit_V_CMP_C(false,false);
|
||||
V_CMPS_F_F64:emit_V_CMP_C(false,false);
|
||||
|
||||
V_CMP_T_F32,
|
||||
V_CMP_T_F64,
|
||||
|
@ -81,7 +80,7 @@ begin
|
|||
V_CMP_T_U32,
|
||||
V_CMP_T_U64,
|
||||
V_CMPS_T_F32,
|
||||
V_CMPS_T_F64:_emit_V_CMP_C(true,false);
|
||||
V_CMPS_T_F64:emit_V_CMP_C(true,false);
|
||||
|
||||
V_CMPX_F_F32,
|
||||
V_CMPX_F_F64,
|
||||
|
@ -90,7 +89,7 @@ begin
|
|||
V_CMPX_F_U32,
|
||||
V_CMPX_F_U64,
|
||||
V_CMPSX_F_F32,
|
||||
V_CMPSX_F_F64:_emit_V_CMP_C(false,true);
|
||||
V_CMPSX_F_F64:emit_V_CMP_C(false,true);
|
||||
|
||||
V_CMPX_T_F32,
|
||||
V_CMPX_T_F64,
|
||||
|
@ -99,101 +98,101 @@ begin
|
|||
V_CMPX_T_U32,
|
||||
V_CMPX_T_U64,
|
||||
V_CMPSX_T_F32,
|
||||
V_CMPSX_T_F64:_emit_V_CMP_C(true,true);
|
||||
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_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_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_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_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_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_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_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);
|
||||
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?');
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
unit srNodes;
|
||||
unit ginodes;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
|
@ -45,45 +45,7 @@ type
|
|||
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 ComparePChar(buf1,buf2:PChar):Integer;
|
||||
function ComparePtruint(buf1,buf2:PPtruint;count:PtrUint):Integer;
|
||||
|
||||
implementation
|
||||
|
@ -169,10 +131,7 @@ 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;
|
||||
_Splay(node);
|
||||
node:=node^.pRight;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
|
@ -185,10 +144,7 @@ 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;
|
||||
_Splay(node);
|
||||
node:=node^.pLeft;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
|
@ -483,74 +439,32 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure TOpParamSingle.SetParam(_ntype:TsrNodeType;_Data:Pointer);
|
||||
begin
|
||||
ntype:=_ntype;
|
||||
pData:=_Data;
|
||||
end;
|
||||
//
|
||||
|
||||
function TOpParamSingle.AsConst:Pointer;
|
||||
function ComparePChar(buf1,buf2:PChar):Integer;
|
||||
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;
|
||||
Result:=0;
|
||||
if (buf1=nil) and (buf2=nil) then
|
||||
begin
|
||||
Exit;
|
||||
end else
|
||||
if (buf1=nil) then
|
||||
begin
|
||||
Result:=-Integer(buf2^);
|
||||
end else
|
||||
if (buf2=nil) then
|
||||
begin
|
||||
Result:=Integer(buf1^);
|
||||
end else
|
||||
begin
|
||||
While true do
|
||||
begin
|
||||
Result:=Integer(buf1^)-Integer(buf2^);
|
||||
if (Result<>0) or (buf1^=#0) or (buf2^=#0) then Exit;
|
||||
Inc(buf1);
|
||||
Inc(buf2);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
function ComparePtruint(buf1,buf2:PPtruint;count:PtrUint):Integer;
|
|
@ -25,7 +25,7 @@
|
|||
<RunParams>
|
||||
<FormatVersion Value="2"/>
|
||||
</RunParams>
|
||||
<Units Count="49">
|
||||
<Units Count="50">
|
||||
<Unit0>
|
||||
<Filename Value="pssl-spirv.lpr"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
|
@ -239,6 +239,10 @@
|
|||
<Filename Value="emit_bin.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit48>
|
||||
<Unit49>
|
||||
<Filename Value="srConfig.pas"/>
|
||||
<IsPartOfProject Value="True"/>
|
||||
</Unit49>
|
||||
</Units>
|
||||
</ProjectOptions>
|
||||
<CompilerOptions>
|
||||
|
@ -263,7 +267,7 @@
|
|||
</CodeGeneration>
|
||||
<Linking>
|
||||
<Debugging>
|
||||
<DebugInfoType Value="dsDwarf2Set"/>
|
||||
<DebugInfoType Value="dsDwarf2"/>
|
||||
<UseLineInfoUnit Value="False"/>
|
||||
</Debugging>
|
||||
<LinkSmart Value="True"/>
|
||||
|
|
|
@ -7,8 +7,8 @@ Uses
|
|||
si_ci_vi_merged_registers,
|
||||
ps4_pssl,
|
||||
ps4_shader,
|
||||
//spirv,
|
||||
srBuffer,
|
||||
|
||||
srConfig,
|
||||
SprvEmit,
|
||||
|
||||
emit_post,
|
||||
|
@ -21,13 +21,9 @@ var
|
|||
FName:RawByteString;
|
||||
FSave:RawByteString;
|
||||
FPrintInfo:Boolean;
|
||||
FPrintAsm:Boolean;
|
||||
FPrintSpv:Boolean;
|
||||
FUseVertexInput:Boolean;
|
||||
FUseTexelBuffer:Boolean;
|
||||
FUseOutput16:Boolean;
|
||||
|
||||
BufferCfg:TsrBufferCfg;
|
||||
//
|
||||
cfg:TsrConfig;
|
||||
end;
|
||||
|
||||
type
|
||||
|
@ -35,67 +31,12 @@ type
|
|||
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);
|
||||
procedure SaveToFile_Spv(const FName:RawByteString;var SprvEmit:TSprvEmit);
|
||||
var
|
||||
F:TFileStream;
|
||||
begin
|
||||
F:=TFileStream.Create(FName,fmCreate);
|
||||
SaveToStream_SprvEmit(F,SprvEmit);
|
||||
SprvEmit.SaveToStream(F);
|
||||
F.Free;
|
||||
end;
|
||||
|
||||
|
@ -325,9 +266,6 @@ var
|
|||
|
||||
SprvEmit:TSprvEmit;
|
||||
|
||||
//LParser:TsrLParser;
|
||||
//FCode:TsrCodeBlock;
|
||||
|
||||
i:Byte;
|
||||
|
||||
begin
|
||||
|
@ -410,6 +348,8 @@ begin
|
|||
|
||||
Assert(info<>nil);
|
||||
|
||||
SprvEmit:=TSprvEmit.Create;
|
||||
|
||||
case info^.m_type of
|
||||
kShaderTypePs :
|
||||
begin
|
||||
|
@ -444,39 +384,34 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
SprvEmit.FPrintAsm :=cfg.FPrintAsm;
|
||||
SprvEmit.FUseVertexInput:=cfg.FUseVertexInput;
|
||||
SprvEmit.FUseTexelBuffer:=cfg.FUseTexelBuffer;
|
||||
SprvEmit.FUseOutput16 :=cfg.FUseOutput16;
|
||||
SprvEmit.Config:=cfg.cfg;
|
||||
|
||||
SprvEmit.FBuffers.cfg:=cfg.BufferCfg;
|
||||
|
||||
if (SprvEmit.Parse(base)>1) then
|
||||
if (SprvEmit.ParseStage(base)>1) then
|
||||
begin
|
||||
Writeln(StdErr,'Shader Parse Err');
|
||||
end;
|
||||
|
||||
if cfg.FPrintAsm or cfg.FPrintSpv or (cfg.FSave<>'') then
|
||||
if cfg.cfg.PrintAsm or cfg.FPrintSpv or (cfg.FSave<>'') then
|
||||
begin
|
||||
post_SprvEmit(SprvEmit);
|
||||
alloc_SprvEmit(SprvEmit);
|
||||
SprvEmit.PostStage;
|
||||
SprvEmit.AllocStage;
|
||||
end;
|
||||
|
||||
if cfg.FPrintSpv then
|
||||
begin
|
||||
print_SprvEmit(SprvEmit);
|
||||
SprvEmit.Print;
|
||||
Writeln;
|
||||
end;
|
||||
|
||||
if (cfg.FSave<>'') then
|
||||
begin
|
||||
SaveToFile_SprvEmit(cfg.FSave,SprvEmit);
|
||||
SaveToFile_Spv(cfg.FSave,SprvEmit);
|
||||
end;
|
||||
|
||||
if cfg.FPrintInfo then
|
||||
Writeln('used_size=',SprvEmit.FAllocator.used_size);
|
||||
Writeln('used_size=',SprvEmit.Allocator.used_size);
|
||||
|
||||
SprvEmit.FAllocator.Free;
|
||||
SprvEmit.Free;
|
||||
end;
|
||||
|
||||
function ParseCmd:Boolean;
|
||||
|
@ -492,25 +427,28 @@ begin
|
|||
Exit(False);
|
||||
end;
|
||||
|
||||
cfg.FUseVertexInput:=True;
|
||||
cfg.BufferCfg.Init;
|
||||
cfg.FName:='';
|
||||
cfg.FSave:='';
|
||||
cfg.FPrintInfo:=False;
|
||||
cfg.FPrintSpv :=False;
|
||||
cfg.cfg.Init;
|
||||
|
||||
n:=-1;
|
||||
For i:=1 to ParamCount do
|
||||
begin
|
||||
case LowerCase(ParamStr(i)) of
|
||||
'-i':cfg.FPrintInfo:=True;
|
||||
'-a':cfg.FPrintAsm:=True;
|
||||
'-a':cfg.cfg.PrintAsm:=True;
|
||||
'-p':cfg.FPrintSpv:=True;
|
||||
|
||||
'-eva':cfg.FUseVertexInput:=True;
|
||||
'-dva':cfg.FUseVertexInput:=False;
|
||||
'-eva':cfg.cfg.UseVertexInput:=True;
|
||||
'-dva':cfg.cfg.UseVertexInput:=False;
|
||||
|
||||
'-etb':cfg.FUseTexelBuffer:=True;
|
||||
'-dtb':cfg.FUseTexelBuffer:=False;
|
||||
'-etb':cfg.cfg.UseTexelBuffer:=True;
|
||||
'-dtb':cfg.cfg.UseTexelBuffer:=False;
|
||||
|
||||
'-eoh':cfg.FUseOutput16:=True;
|
||||
'-doh':cfg.FUseOutput16:=False;
|
||||
'-eoh':cfg.cfg.UseOutput16:=True;
|
||||
'-doh':cfg.cfg.UseOutput16:=False;
|
||||
|
||||
'-b':n:=0;
|
||||
|
||||
|
@ -525,11 +463,11 @@ 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);
|
||||
1:cfg.cfg.maxUniformBufferRange :=StrToInt64Def(ParamStr(i),0);
|
||||
2:cfg.cfg.PushConstantsOffset :=StrToInt64Def(ParamStr(i),0);
|
||||
3:cfg.cfg.maxPushConstantsSize :=StrToInt64Def(ParamStr(i),0);
|
||||
4:cfg.cfg.minStorageBufferOffsetAlignment:=StrToInt64Def(ParamStr(i),0);
|
||||
5:cfg.cfg.minUniformBufferOffsetAlignment:=StrToInt64Def(ParamStr(i),0);
|
||||
end;
|
||||
n:=-1;
|
||||
end;
|
||||
|
@ -552,81 +490,47 @@ begin
|
|||
|
||||
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-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\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\WeAreDoomed\WeAreDoomed_ps4_cs_FEA061C5.dump');
|
||||
//load_dump('shader_dump\WeAreDoomed\WeAreDoomed_ps4_ps_B9680888.dump');
|
||||
//load_dump('shader_dump\WeAreDoomed\WeAreDoomed_ps4_ps_BA60EAD7.dump');
|
||||
//load_dump('shader_dump\WeAreDoomed\WeAreDoomed_ps4_vs_0C420DE0.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-sample\basic-sample_debug_ps_E125C5F7.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\basic_quad_debug\basic_quad_debug_cs_3685EFC7.dump');
|
||||
|
||||
//load_dump('shader_dump\SonicMania\SonicMania_ps_11DF2A32.dump');
|
||||
//load_dump('shader_dump\SonicMania\SonicMania_ps_3CC22A00.dump');
|
||||
|
||||
//load_dump('shader_dump\SonicMania\SonicMania_ps_3CC22A00.dump'); //cfg
|
||||
//load_dump('shader_dump\MomodoraRUtM\MomodoraRUtM_ps_595F5E5D.dump');
|
||||
load_dump('shader_dump\MomodoraRUtM\MomodoraRUtM_ps_B42E92C3.dump');
|
||||
//load_dump('shader_dump\MomodoraRUtM\MomodoraRUtM_vs_B9E80F51.dump');
|
||||
|
||||
//load_dump('shader_dump\basic-sample\basic-sample_debug_cs_4303E70D.dump');
|
||||
//load_dump('shader_dump\basic-sample\basic-sample_debug_cs_C4EA2D91.dump');
|
||||
|
||||
//load_dump('shader_dump\Cladun_Returns\ClassicDungeon3ORBIS_ps_B2ED8D0C.dump');
|
||||
//load_dump('shader_dump\Cladun_Returns\ClassicDungeon3ORBIS_ps_B39D802A.dump');
|
||||
|
||||
//load_dump('shader_dump\depth-mode-sample\depth-mode-sample_debug_ps_E125C5F7.dump');
|
||||
|
||||
//load_dump('shader_dump\tutorial_anti-aliasing_debug\tutorial_anti-aliasing_debug_ps_E820FFDE.dump');
|
||||
|
||||
//load_dump('shader_dump\JETPACKJOYRIDE\mgjp_cs_2D246406.dump');
|
||||
end;
|
||||
|
||||
|
||||
if (cfg.FName<>'') then
|
||||
begin
|
||||
load_dump(cfg.FName);
|
||||
end;
|
||||
|
||||
load_pssl(GPU_REGS.CS.Addr);
|
||||
|
||||
|
@ -634,7 +538,9 @@ begin
|
|||
load_pssl(GPU_REGS.PS.Addr);
|
||||
|
||||
if cfg.FPrintInfo then
|
||||
begin
|
||||
readln;
|
||||
end;
|
||||
end.
|
||||
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@ unit srAllocator;
|
|||
interface
|
||||
|
||||
uses
|
||||
srNodes;
|
||||
ginodes;
|
||||
|
||||
type
|
||||
PsrAllocNode=^TsrAllocNode;
|
||||
|
|
|
@ -5,11 +5,11 @@ unit srBitcast;
|
|||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg;
|
||||
ginodes,
|
||||
srNode,
|
||||
srType,
|
||||
srConst,
|
||||
srReg;
|
||||
|
||||
type
|
||||
PsrBitcast=^TsrBitcast;
|
||||
|
@ -24,27 +24,34 @@ type
|
|||
function c(n1,n2:PsrBitcast):Integer; static;
|
||||
end;
|
||||
|
||||
PsrBitcastList=^TsrBitcastList;
|
||||
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;
|
||||
rSlot:TsrRegSlot;
|
||||
procedure Init(Emit:TCustomEmit); inline;
|
||||
function Find(dtype:TsrDataType;src:PsrRegNode):PsrBitcast;
|
||||
function FetchRead(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
||||
function FetchDstr(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));
|
||||
//first dtype
|
||||
Result:=Integer(n1^.key.dtype>n2^.key.dtype)-Integer(n1^.key.dtype<n2^.key.dtype);
|
||||
if (Result<>0) then Exit;
|
||||
//second src
|
||||
Result:=Integer(n1^.key.src>n2^.key.src)-Integer(n1^.key.src<n2^.key.src);
|
||||
end;
|
||||
|
||||
procedure TsrBitcastList.Init(Emit:TCustomEmit); inline;
|
||||
begin
|
||||
rSlot.Init(Emit,'BCAST');
|
||||
end;
|
||||
|
||||
function TsrBitcastList.Find(dtype:TsrDataType;src:PsrRegNode):PsrBitcast;
|
||||
|
@ -63,37 +70,33 @@ var
|
|||
begin
|
||||
Result:=src;
|
||||
if (src=nil) then Exit;
|
||||
if (dtype=dtUnknow) or (dtype=src^.dtype) then
|
||||
begin
|
||||
src^.mark_read;
|
||||
Exit;
|
||||
end;
|
||||
if (dtype=dtUnknow) or (dtype=src^.dtype) then Exit;
|
||||
|
||||
src^.mark_read;
|
||||
dst:=PSprvEmit(pRoot)^.NewReg(dtype);
|
||||
dst^.pLine:=src^.pLine;
|
||||
dst^.SetReg(src);
|
||||
dst:=rSlot.New(src^.pLine,dtype);
|
||||
dst^.pWriter:=src;
|
||||
|
||||
dst^.mark_read;
|
||||
Result:=dst;
|
||||
end;
|
||||
|
||||
function TsrBitcastList.FetchDst(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
||||
function TsrBitcastList.FetchDstr(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
||||
var
|
||||
dst: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;
|
||||
dst:=rSlot.New(src^.pLine,dtype);
|
||||
dst^.pWriter:=src^.pWriter;
|
||||
|
||||
Result^.pWriter:=src^.pWriter;
|
||||
src^.SetReg(Result);
|
||||
src^.pWriter:=dst;
|
||||
|
||||
Result:=dst;
|
||||
end;
|
||||
|
||||
function TsrBitcastList.FetchCast(dtype:TsrDataType;src:PsrRegNode):PsrRegNode;
|
||||
var
|
||||
pConstList:PsrConstList;
|
||||
node:PsrBitcast;
|
||||
dst:PsrRegNode;
|
||||
pConst:PsrConst;
|
||||
|
@ -101,52 +104,46 @@ var
|
|||
begin
|
||||
Result:=src;
|
||||
if (src=nil) then Exit;
|
||||
if (dtype=dtUnknow) or (dtype=src^.dtype) then
|
||||
begin
|
||||
src^.mark_read;
|
||||
Exit;
|
||||
end;
|
||||
if (dtype=dtUnknow) or (dtype=src^.dtype) then Exit;
|
||||
|
||||
dst:=nil;
|
||||
|
||||
node:=Find(dtype,src);
|
||||
if (node<>nil) then
|
||||
begin
|
||||
dst:=node^.dst;
|
||||
dst^.mark_read;
|
||||
Result:=dst;
|
||||
Result:=node^.dst;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if src^.is_const then
|
||||
begin
|
||||
pConst:=src^.AsConst;
|
||||
pConst^.mark_unread;
|
||||
dst:=PSprvEmit(pRoot)^.NewReg(dtype);
|
||||
dst^.pLine:=src^.pLine;
|
||||
dst^.SetConst(PSprvEmit(pRoot)^.FConsts.Bitcast(dtype,pConst))
|
||||
|
||||
pConstList:=rSlot.FEmit.GetConstList;
|
||||
pConst:=pConstList^.Bitcast(dtype,pConst);
|
||||
|
||||
dst:=rSlot.New(src^.pLine,dtype);
|
||||
dst^.pWriter:=pConst;
|
||||
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);
|
||||
dst:=rSlot.New(src^.pLine,dtype);
|
||||
|
||||
rSlot.FEmit.OpCast(src^.pLine,dst,src)
|
||||
end else
|
||||
begin
|
||||
Assert(false,'bitcast');
|
||||
end;
|
||||
end;
|
||||
|
||||
node:=PSprvEmit(pRoot)^.Alloc(SizeOf(TsrBitcast));
|
||||
node:=rSlot.FEmit.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;
|
||||
|
||||
|
|
|
@ -5,14 +5,23 @@ unit srBuffer;
|
|||
interface
|
||||
|
||||
uses
|
||||
spirv,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srVariable,
|
||||
srLayout,
|
||||
srDecorate;
|
||||
sysutils,
|
||||
spirv,
|
||||
ginodes,
|
||||
srNode,
|
||||
srType,
|
||||
srTypes,
|
||||
srVariable,
|
||||
srLayout,
|
||||
srDecorate,
|
||||
srConfig;
|
||||
|
||||
type
|
||||
ntBuffer=class(ntDescriptor)
|
||||
class Function pwrite_count (node:PsrNode):PDWORD; override;
|
||||
class function GetStorageName(node:PsrNode):RawByteString; override;
|
||||
end;
|
||||
|
||||
PsrBuffer=^TsrBuffer;
|
||||
|
||||
PsrField=^TsrField;
|
||||
|
@ -33,7 +42,7 @@ type
|
|||
//----
|
||||
|
||||
pBuffer:PsrBuffer;
|
||||
parent:PsrField;
|
||||
pParent:PsrField;
|
||||
offset:PtrUint;
|
||||
size:PtrUint;
|
||||
stride:PtrUint;
|
||||
|
@ -45,7 +54,6 @@ type
|
|||
|
||||
//
|
||||
|
||||
Alloc:TfnAlloc;
|
||||
FList:TFieldFetch;
|
||||
|
||||
function c(n1,n2:PsrField):Integer; static;
|
||||
|
@ -60,80 +68,90 @@ type
|
|||
function FetchValue(_offset,_size:PtrUint;_dtype:TsrDataType):TFieldFetchValue;
|
||||
function FetchRuntimeArray(_offset,_stride:PtrUint):TFieldFetchValue;
|
||||
function IsStructUsedRuntimeArray:Boolean;
|
||||
function IsStructNotUsed:Boolean;
|
||||
function IsStructNotUsed:Boolean; inline;
|
||||
function IsTop:Boolean; inline;
|
||||
function GetStructDecorate:DWORD;
|
||||
procedure UpdateSize;
|
||||
function GetSize:PtrUint;
|
||||
procedure FillNode(o,s:PtrUint);
|
||||
function FillSpace:Integer;
|
||||
procedure AllocID;
|
||||
procedure AllocBinding(aType:PsrType;Decorates:PsrDecorateList);
|
||||
end;
|
||||
|
||||
TsrBufferType=(btStorageBuffer,btUniformBuffer,btPushConstant);
|
||||
|
||||
TsrBuffer=object(TsrDescriptor)
|
||||
TsrBuffer=packed object(TsrDescriptor)
|
||||
pLeft,pRight:PsrBuffer;
|
||||
//----
|
||||
fwrite_count:DWORD;
|
||||
fchain_read :DWORD;
|
||||
fchain_write:DWORD;
|
||||
//
|
||||
align_offset:DWORD;
|
||||
|
||||
key:packed record
|
||||
pLayout:PsrDataLayout;
|
||||
CastNum:PtrInt;
|
||||
end;
|
||||
FEmit:TCustomEmit;
|
||||
|
||||
bType:TsrBufferType;
|
||||
|
||||
write_count:DWORD;
|
||||
align_offset:DWORD;
|
||||
key:packed record
|
||||
pLayout:PsrDataLayout;
|
||||
AliasId:PtrInt;
|
||||
end;
|
||||
|
||||
FTop:TsrField;
|
||||
|
||||
function c(n1,n2:PsrBuffer):Integer; static;
|
||||
Procedure Init(Emit:TCustomEmit); inline;
|
||||
function GetStorageName:RawByteString;
|
||||
function GetTypeChar:Char;
|
||||
function GetString:RawByteString;
|
||||
function GetStructName:RawByteString;
|
||||
procedure UpdateSize;
|
||||
function GetSize:PtrUint;
|
||||
procedure TakeChain(node:PsrChain);
|
||||
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;
|
||||
|
||||
PsrBufferList=^TsrBufferList;
|
||||
TsrBufferList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrBuffer,TsrBuffer>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
cfg:TsrBufferCfg;
|
||||
FEmit:TCustomEmit;
|
||||
FNTree:TNodeFetch;
|
||||
FPushConstant:PsrBuffer;
|
||||
procedure Init(cb:TfnAlloc);
|
||||
procedure Init(Emit:TCustomEmit); inline;
|
||||
function Fetch(s:PsrDataLayout;n:PtrInt):PsrBuffer;
|
||||
function NextCast(buf:PsrBuffer):PsrBuffer;
|
||||
function NextAlias(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 OnAllocID(pField:PsrField);
|
||||
procedure AllocID;
|
||||
procedure AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList);
|
||||
procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
procedure UpdateStorage(node:PsrChain;pBuffer:PsrBuffer);
|
||||
procedure AllocBinding(Var FBinding:Integer);
|
||||
procedure AllocSourceExtension;
|
||||
function FindUserDataBuf:PsrBuffer;
|
||||
procedure ApplyBufferType;
|
||||
procedure AlignOffset(node:PsrBuffer;offset:PtrUint);
|
||||
procedure AlignOffset;
|
||||
procedure OnAllocTypeBinding(pField:PsrField);
|
||||
procedure AllocTypeBinding;
|
||||
procedure AllocName;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
class Function ntBuffer.pwrite_count(node:PsrNode):PDWORD;
|
||||
begin
|
||||
Result:=@PsrBuffer(node)^.fwrite_count;
|
||||
end;
|
||||
|
||||
class function ntBuffer.GetStorageName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrBuffer(node)^.GetStorageName;
|
||||
end;
|
||||
|
||||
//---
|
||||
|
||||
function TsrField.c(n1,n2:PsrField):Integer;
|
||||
|
@ -194,12 +212,12 @@ begin
|
|||
Result:=FList.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrField));
|
||||
Result^.Alloc:=Alloc;
|
||||
Assert(pBuffer^.FEmit<>nil);
|
||||
Result:=pBuffer^.FEmit.Alloc(SizeOf(TsrField));
|
||||
Result^.pBuffer:=pBuffer;
|
||||
Result^.parent:=@Self;
|
||||
Result^.offset:=o;
|
||||
Result^.FID:=-1;
|
||||
Result^.pParent:=@Self;
|
||||
Result^.offset :=o;
|
||||
Result^.FID :=-1;
|
||||
FList.Insert(Result);
|
||||
Inc(FCount);
|
||||
end;
|
||||
|
@ -213,9 +231,9 @@ begin
|
|||
Result:=Default(TFieldFetchValue);
|
||||
|
||||
_stride:=0;
|
||||
if isVector(_dtype) then
|
||||
if _dtype.isVector then
|
||||
begin
|
||||
_stride:=BitSizeType(GetVecChild(_dtype)) div 8;
|
||||
_stride:=_dtype.Child.BitSize div 8;
|
||||
end;
|
||||
|
||||
node:=Find_le(_offset);
|
||||
|
@ -262,9 +280,9 @@ begin
|
|||
end;
|
||||
else
|
||||
begin
|
||||
if isVector(node^.dtype) then
|
||||
if node^.dtype.isVector then
|
||||
begin //ftVector
|
||||
if isVector(_dtype) then
|
||||
if _dtype.isVector then
|
||||
begin
|
||||
if (node^.offset=_offset) and
|
||||
(node^.size =_size) and
|
||||
|
@ -287,7 +305,7 @@ begin
|
|||
end;
|
||||
end else
|
||||
begin //ftValue
|
||||
if isVector(_dtype) then
|
||||
if _dtype.isVector then
|
||||
begin
|
||||
if (node^.offset=_offset) and
|
||||
(node^.size =_size) then
|
||||
|
@ -350,15 +368,20 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
function TsrField.IsStructNotUsed:Boolean;
|
||||
function TsrField.IsStructNotUsed:Boolean; inline;
|
||||
begin
|
||||
Result:=(FCount<=1) and (parent<>nil);
|
||||
Result:=(FCount<=1) and (pParent<>nil);
|
||||
end;
|
||||
|
||||
function TsrField.IsTop:Boolean; inline;
|
||||
begin
|
||||
Result:=(pParent=nil);
|
||||
end;
|
||||
|
||||
function TsrField.GetStructDecorate:DWORD;
|
||||
begin
|
||||
Result:=DWORD(-1); //dont use
|
||||
if (parent=nil) then //is top
|
||||
if IsTop then
|
||||
if (dtype=dtTypeStruct) then //is struct
|
||||
begin
|
||||
|
||||
|
@ -374,6 +397,23 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure TsrField.UpdateSize;
|
||||
var
|
||||
node:PsrField;
|
||||
begin
|
||||
node:=FList.Max;
|
||||
if (node<>nil) then
|
||||
begin
|
||||
size:=node^.offset+node^.size;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrField.GetSize:PtrUint;
|
||||
begin
|
||||
UpdateSize;
|
||||
Result:=size;
|
||||
end;
|
||||
|
||||
procedure TsrField.FillNode(o,s:PtrUint);
|
||||
|
||||
procedure _Pad(p,v:PtrUint;_dtype:TsrDataType); //inline;
|
||||
|
@ -477,43 +517,6 @@ begin
|
|||
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;
|
||||
|
@ -522,7 +525,30 @@ begin
|
|||
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);
|
||||
Result:=Integer(n1^.key.AliasId>n2^.key.AliasId)-Integer(n1^.key.AliasId<n2^.key.AliasId);
|
||||
end;
|
||||
|
||||
Procedure TsrBuffer.Init(Emit:TCustomEmit); inline;
|
||||
begin
|
||||
FEmit:=Emit;
|
||||
|
||||
fntype :=ntBuffer;
|
||||
bType :=btStorageBuffer;
|
||||
FStorage:=StorageClass.Uniform;
|
||||
FBinding:=-1;
|
||||
|
||||
FTop.FID:=-1;
|
||||
FTop.dtype:=dtTypeStruct;
|
||||
end;
|
||||
|
||||
function TsrBuffer.GetStorageName:RawByteString;
|
||||
begin
|
||||
Result:='';
|
||||
Case bType of
|
||||
btStorageBuffer:Result:='sBuf'+IntToStr(FBinding);
|
||||
btUniformBuffer:Result:='uBuf'+IntToStr(FBinding);
|
||||
btPushConstant :Result:='cBuf';
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrBuffer.GetTypeChar:Char;
|
||||
|
@ -556,21 +582,19 @@ 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;
|
||||
Result:=FTop.GetSize;
|
||||
end;
|
||||
|
||||
procedure TsrBuffer.TakeChain(node:PsrChain);
|
||||
begin
|
||||
if (@Self=nil) or (node=nil) then Exit;
|
||||
|
||||
mark_read(node);
|
||||
|
||||
fchain_read :=fchain_read +node^.read_count;
|
||||
fchain_write:=fchain_write+node^.write_count;
|
||||
end;
|
||||
|
||||
procedure TsrBuffer.EnumAllField(cb:TFieldEnumCb);
|
||||
|
@ -583,9 +607,8 @@ begin
|
|||
repeat
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.FList.pRoot<>nil) then //child exist
|
||||
if (node^.First<>nil) then //child exist
|
||||
begin
|
||||
curr^.FList._Splay(node); //Move to root
|
||||
curr:=node;
|
||||
node:=curr^.First; //down
|
||||
end else
|
||||
|
@ -595,9 +618,9 @@ begin
|
|||
end;
|
||||
end;
|
||||
cb(curr);
|
||||
curr:=curr^.parent; //up
|
||||
node:=curr;
|
||||
curr:=curr^.pParent; //up
|
||||
if (curr=nil) then Break;
|
||||
node:=curr^.FList.pRoot; //last find
|
||||
node:=curr^.Next(node);
|
||||
until false;
|
||||
end;
|
||||
|
@ -619,24 +642,9 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrBufferCfg.Init;
|
||||
procedure TsrBufferList.Init(Emit:TCustomEmit); inline;
|
||||
begin
|
||||
SpvVersion:=$10100;
|
||||
maxUniformBufferRange:=$FFFF;
|
||||
maxPushConstantsSize:=128;
|
||||
minStorageBufferOffsetAlignment:=0;
|
||||
minUniformBufferOffsetAlignment:=0;
|
||||
end;
|
||||
|
||||
Function TsrBufferCfg.CanUseStorageBufferClass:Boolean;
|
||||
begin
|
||||
Result:=(SpvVersion>=$10300);
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.Init(cb:TfnAlloc);
|
||||
begin
|
||||
Alloc:=cb;
|
||||
cfg.Init;
|
||||
FEmit:=Emit;
|
||||
end;
|
||||
|
||||
function TsrBufferList.Fetch(s:PsrDataLayout;n:PtrInt):PsrBuffer;
|
||||
|
@ -644,30 +652,27 @@ var
|
|||
node:TsrBuffer;
|
||||
begin
|
||||
node:=Default(TsrBuffer);
|
||||
node.Init(FEmit);
|
||||
node.key.pLayout:=s;
|
||||
node.key.CastNum:=n;
|
||||
node.key.AliasId:=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:=FEmit.Alloc(SizeOf(TsrBuffer));
|
||||
Move(node,Result^,SizeOf(TsrBuffer));
|
||||
Result^.FTop.pBuffer:=Result;
|
||||
Result^.FTop.FID:=-1;
|
||||
Result^.FTop.dtype:=dtTypeStruct;
|
||||
//
|
||||
Result^.InitVar(FEmit);
|
||||
//
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrBufferList.NextCast(buf:PsrBuffer):PsrBuffer;
|
||||
function TsrBufferList.NextAlias(buf:PsrBuffer):PsrBuffer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (buf=nil) then Exit;
|
||||
Result:=Fetch(buf^.key.pLayout,buf^.key.CastNum+1);
|
||||
Result:=Fetch(buf^.key.pLayout,buf^.key.AliasId+1);
|
||||
end;
|
||||
|
||||
Function TsrBufferList.First:PsrBuffer;
|
||||
|
@ -688,7 +693,10 @@ begin
|
|||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
node^.EnumAllField(cb);
|
||||
if node^.IsUsed then
|
||||
begin
|
||||
node^.EnumAllField(cb);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
@ -703,9 +711,26 @@ begin
|
|||
EnumAllField(@OnFillSpace);
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.OnAllocID(node:PsrField);
|
||||
procedure TsrBufferList.OnAllocID(pField:PsrField);
|
||||
var
|
||||
node:PsrField;
|
||||
ID:Integer;
|
||||
begin
|
||||
node^.AllocID;
|
||||
ID:=0;
|
||||
node:=pField^.First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if pField^.dtype.IsVector then
|
||||
begin
|
||||
ID:=node^.offset div pField^.stride;
|
||||
node^.FID:=ID;
|
||||
end else
|
||||
begin
|
||||
node^.FID:=ID;
|
||||
Inc(ID);
|
||||
end;
|
||||
node:=pField^.Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.AllocID;
|
||||
|
@ -713,80 +738,108 @@ begin
|
|||
EnumAllField(@OnAllocID);
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList);
|
||||
procedure TsrBufferList.AllocBinding(Var FBinding:Integer);
|
||||
var
|
||||
pConfig:PsrConfig;
|
||||
pDecorateList:PsrDecorateList;
|
||||
node:PsrBuffer;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (Decorates=nil) then Exit;
|
||||
pConfig:=FEmit.GetConfig;
|
||||
pDecorateList:=FEmit.GetDecorateList;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
if (pVar<>nil) and node^.IsUsed then
|
||||
if (node^.bType<>btPushConstant) then
|
||||
if (node^.FBinding=-1) then //alloc
|
||||
begin
|
||||
if (node^.bType<>btPushConstant) then
|
||||
if (node^.FBinding=-1) then //alloc
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.Binding,FBinding);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.DescriptorSet,pConfig^.DescriptorSet);
|
||||
node^.FBinding:=FBinding;
|
||||
Inc(FBinding);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.AllocSourceExtension;
|
||||
var
|
||||
pDebugInfoList:PsrDebugInfoList;
|
||||
node:PsrBuffer;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
pDebugInfoList:=FEmit.GetDebugInfoList;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) and node^.IsUsed then
|
||||
begin
|
||||
pDebugInfoList^.OpSourceExtension(node^.GetString);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrBufferList.FindUserDataBuf:PsrBuffer;
|
||||
var
|
||||
node:PsrBuffer;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if node^.IsUsed then
|
||||
begin
|
||||
if node^.key.pLayout^.IsUserData then
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Binding,FBinding);
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.DescriptorSet,Decorates^.FDescriptorSet);
|
||||
node^.FBinding:=FBinding;
|
||||
Inc(FBinding);
|
||||
Exit(node);
|
||||
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
|
||||
pConfig:PsrConfig;
|
||||
node:PsrBuffer;
|
||||
begin
|
||||
pConfig:=FEmit.GetConfig;
|
||||
|
||||
node:=FindUserDataBuf;
|
||||
if (node<>nil) and (FPushConstant=nil) then
|
||||
if (node^.write_count=0) and
|
||||
(node^.GetSize<=pConfig^.maxPushConstantsSize) then
|
||||
begin
|
||||
node^.bType :=btPushConstant;
|
||||
node^.FStorage:=StorageClass.PushConstant;
|
||||
FPushConstant :=node;
|
||||
end;
|
||||
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.bType=btStorageBuffer) then
|
||||
if node^.IsUsed and (node^.bType=btStorageBuffer) then
|
||||
begin
|
||||
|
||||
if (FPushConstant=nil) and
|
||||
(node^.write_count=0) and
|
||||
(node^.GetSize<=cfg.maxPushConstantsSize) then
|
||||
(node^.fchain_write=0) and
|
||||
(node^.GetSize<=pConfig^.maxPushConstantsSize) then
|
||||
begin
|
||||
node^.bType :=btPushConstant;
|
||||
node^.FStorage:=StorageClass.PushConstant;
|
||||
FPushConstant:=node;
|
||||
FPushConstant :=node;
|
||||
end else
|
||||
if (node^.write_count=0) and
|
||||
(node^.GetSize<=cfg.maxUniformBufferRange) then
|
||||
if (node^.fchain_write=0) and
|
||||
(node^.GetSize<=pConfig^.maxUniformBufferRange) then
|
||||
begin
|
||||
node^.bType :=btUniformBuffer;
|
||||
node^.FStorage:=StorageClass.Uniform;
|
||||
end else
|
||||
if cfg.CanUseStorageBufferClass then
|
||||
if pConfig^.CanUseStorageBufferClass then
|
||||
begin
|
||||
node^.FStorage:=StorageClass.StorageBuffer;
|
||||
end else
|
||||
|
@ -822,25 +875,97 @@ end;
|
|||
|
||||
procedure TsrBufferList.AlignOffset;
|
||||
var
|
||||
pConfig:PsrConfig;
|
||||
node:PsrBuffer;
|
||||
begin
|
||||
pConfig:=FEmit.GetConfig;
|
||||
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;
|
||||
if node^.IsUsed then
|
||||
begin
|
||||
Case node^.bType of
|
||||
btStorageBuffer:
|
||||
begin
|
||||
AlignOffset(node,pConfig^.minStorageBufferOffsetAlignment);
|
||||
end;
|
||||
btUniformBuffer:
|
||||
begin
|
||||
AlignOffset(node,pConfig^.minUniformBufferOffsetAlignment);
|
||||
end;
|
||||
btPushConstant:
|
||||
begin
|
||||
node^.align_offset:=pConfig^.PushConstantsOffset;
|
||||
node^.ShiftOffset(pConfig^.PushConstantsOffset);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.OnAllocTypeBinding(pField:PsrField);
|
||||
var
|
||||
pDecorateList:PsrDecorateList;
|
||||
node:PsrField;
|
||||
SD:DWORD;
|
||||
begin
|
||||
if (pField^.dtype<>dtTypeStruct) then Exit;
|
||||
if (pField^.pType=nil) then Exit;
|
||||
pDecorateList:=FEmit.GetDecorateList;
|
||||
SD:=pField^.GetStructDecorate;
|
||||
if (SD<>DWORD(-1)) then
|
||||
begin
|
||||
pDecorateList^.OpDecorate(pField^.pType,SD,0);
|
||||
end;
|
||||
node:=pField^.First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pDecorateList^.OpMemberDecorate(pField^.pType,node^.FID,node^.offset);
|
||||
node:=pField^.Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.AllocTypeBinding;
|
||||
var
|
||||
pDecorateList:PsrDecorateList;
|
||||
node:PsrBuffer;
|
||||
begin
|
||||
EnumAllField(@OnAllocTypeBinding);
|
||||
//
|
||||
pDecorateList:=FEmit.GetDecorateList;
|
||||
//
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if node^.IsUsed and (node^.pVar<>nil) then
|
||||
if (node^.bType=btStorageBuffer) then
|
||||
begin
|
||||
if (node^.fchain_read=0) then
|
||||
begin
|
||||
pDecorateList^.OpDecorate(node^.pVar,Decoration.NonReadable,0);
|
||||
end;
|
||||
if (node^.fchain_write=0) then
|
||||
begin
|
||||
pDecorateList^.OpDecorate(node^.pVar,Decoration.NonWritable,0);
|
||||
end;
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrBufferList.AllocName;
|
||||
var
|
||||
FDebugInfo:PsrDebugInfoList;
|
||||
node:PsrBuffer;
|
||||
begin
|
||||
FDebugInfo:=FEmit.GetDebugInfoList;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if node^.IsUsed and (node^.FTop.pType<>nil) then
|
||||
begin
|
||||
FDebugInfo^.OpName(node^.FTop.pType,node^.GetStructName);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
unit srParser;
|
||||
unit srCFGCursor;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
srLabel,
|
||||
srCFG,
|
||||
srNodes;
|
||||
srCFGLabel,
|
||||
srCFGParser,
|
||||
ginodes,
|
||||
srNode;
|
||||
|
||||
type
|
||||
PsrCursor=^TsrCursor;
|
||||
TsrCursor=object(TsrLCursor)
|
||||
pCode:PsrCodeBlock;
|
||||
pBlock:PsrCFGBlock;
|
||||
|
@ -18,8 +19,11 @@ type
|
|||
end;
|
||||
|
||||
TsrCodeList=specialize TNodeQueue<PsrCodeBlock>;
|
||||
|
||||
PsrCodeHeap=^TsrCodeHeap;
|
||||
TsrCodeHeap=object(TsrCodeList)
|
||||
Alloc:TfnAlloc;
|
||||
FEmit:TCustomEmit;
|
||||
Procedure Init(Emit:TCustomEmit);
|
||||
function FindByPtr(base:Pointer):PsrCodeBlock;
|
||||
function FetchByPtr(base:Pointer;bType:TsrBlockType):TsrCursor;
|
||||
end;
|
||||
|
@ -28,6 +32,11 @@ implementation
|
|||
|
||||
//
|
||||
|
||||
Procedure TsrCodeHeap.Init(Emit:TCustomEmit);
|
||||
begin
|
||||
FEmit:=Emit;
|
||||
end;
|
||||
|
||||
function TsrCodeHeap.FindByPtr(base:Pointer):PsrCodeBlock;
|
||||
var
|
||||
node:PsrCodeBlock;
|
||||
|
@ -52,8 +61,8 @@ begin
|
|||
node:=FindByPtr(base);
|
||||
if (node=nil) then
|
||||
begin
|
||||
node:=Alloc(SizeOf(TsrCodeBlock));
|
||||
node^.Alloc:=Alloc;
|
||||
node:=FEmit.Alloc(SizeOf(TsrCodeBlock));
|
||||
node^.FEmit:=FEmit;
|
||||
if parse_code_cfg(bType,base,node)>1 then Assert(False);
|
||||
Push_tail(node);
|
||||
end;
|
|
@ -1,13 +1,12 @@
|
|||
unit srLabel;
|
||||
unit srCFGLabel;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srNodes;
|
||||
ginodes;
|
||||
|
||||
type
|
||||
TSrcAdr=object
|
|
@ -1,14 +1,14 @@
|
|||
unit srCFG;
|
||||
unit srCFGParser;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srNodes,
|
||||
srLabel;
|
||||
ginodes,
|
||||
srNode,
|
||||
srCFGLabel;
|
||||
|
||||
type
|
||||
PsrCFGBlock=^TsrCFGBlock;
|
||||
|
@ -42,7 +42,7 @@ type
|
|||
TsrCodeBlock=object
|
||||
pNext:PsrCodeBlock;
|
||||
//----
|
||||
Alloc:TfnAlloc;
|
||||
FEmit:TCustomEmit;
|
||||
Body:Pointer;
|
||||
Size:ptruint;
|
||||
FLabels:TsrLabels;
|
||||
|
@ -475,10 +475,9 @@ begin
|
|||
Result:=FLabels.FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrLabel));
|
||||
Result:=FEmit.Alloc(SizeOf(TsrLabel));
|
||||
Result^.Adr:=Adr;
|
||||
FLabels.FNTree.Insert(Result);
|
||||
//FLabels.FList.Push_tail(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -489,7 +488,7 @@ end;
|
|||
|
||||
Function TsrCFGParser.NewBlock:PsrCFGBlock;
|
||||
begin
|
||||
Result:=pCode^.Alloc(SizeOf(TsrCFGBlock));
|
||||
Result:=pCode^.FEmit.Alloc(SizeOf(TsrCFGBlock));
|
||||
end;
|
||||
|
||||
Procedure TsrCFGParser.PushBlock(New:PsrCFGBlock);
|
|
@ -0,0 +1,114 @@
|
|||
unit srCacheOp;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ginodes,
|
||||
srNode,
|
||||
srCFGLabel,
|
||||
srType,
|
||||
srReg,
|
||||
srOp;
|
||||
|
||||
type
|
||||
PsrCacheOp=^TsrCacheOp;
|
||||
TsrCacheOp=object
|
||||
private
|
||||
pLeft,pRight:PsrCacheOp;
|
||||
//----
|
||||
key:packed record
|
||||
place:PsrOpBlock;
|
||||
OpId:DWORD;
|
||||
dtype:TsrDataType;
|
||||
count:DWORD;
|
||||
end;
|
||||
pData:PPsrRegNode;
|
||||
function c(n1,n2:PsrCacheOp):Integer; static;
|
||||
public
|
||||
pDst:PsrNode;
|
||||
end;
|
||||
|
||||
PsrCacheOpList=^TsrCacheOpList;
|
||||
TsrCacheOpList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrCacheOp,TsrCacheOp>;
|
||||
var
|
||||
FEmit:TCustomEmit;
|
||||
FNTree:TNodeFetch;
|
||||
Procedure Init(Emit:TCustomEmit); inline;
|
||||
function Fetch(place:PsrOpBlock;OpId:DWORD;rtype:TsrDataType;count:Byte;src:PPsrRegNode):PsrCacheOp;
|
||||
end;
|
||||
|
||||
function _up_to_real(t:PsrOpBlock):PsrOpBlock;
|
||||
|
||||
implementation
|
||||
|
||||
function _up_to_real(t:PsrOpBlock):PsrOpBlock;
|
||||
begin
|
||||
repeat
|
||||
if not t^.IsType(ntOpBlock) then Break;
|
||||
Case t^.Block.bType of
|
||||
btMain,
|
||||
btCond,
|
||||
btLoop:Break;
|
||||
else;
|
||||
end;
|
||||
t:=t^.Parent;
|
||||
until false;
|
||||
Result:=t;
|
||||
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^.pData^,n2^.pData^,count*SizeOf(Pointer));
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrCacheOpList.Init(Emit:TCustomEmit); inline;
|
||||
begin
|
||||
FEmit:=Emit;
|
||||
end;
|
||||
|
||||
function TsrCacheOpList.Fetch(place:PsrOpBlock;OpId:DWORD;rtype:TsrDataType;count:Byte;src:PPsrRegNode):PsrCacheOp;
|
||||
var
|
||||
size:ptruint;
|
||||
node:TsrCacheOp;
|
||||
begin
|
||||
Assert(place<>nil);
|
||||
place:=_up_to_real(place);
|
||||
Result:=nil;
|
||||
node:=Default(TsrCacheOp);
|
||||
node.key.place:=place;
|
||||
node.key.OpId :=OpId;
|
||||
node.key.dtype:=rtype;
|
||||
node.key.count:=count;
|
||||
node.pData:=src;
|
||||
Result:=FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=FEmit.Alloc(SizeOf(TsrCacheOp));
|
||||
Move(node,Result^,SizeOf(TsrCacheOp));
|
||||
|
||||
size:=count*SizeOf(Pointer);
|
||||
Result^.pData:=FEmit.Alloc(size);
|
||||
Move(src^,Result^.pData^,size);
|
||||
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -1,62 +0,0 @@
|
|||
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;
|
||||
|
||||
PsrCapList=^TsrCapList;
|
||||
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.
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
unit srCapability;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ginodes,
|
||||
srNode;
|
||||
|
||||
type
|
||||
PsrCapability=^TsrCapability;
|
||||
TsrCapability=object
|
||||
pLeft,pRight:PsrCapability;
|
||||
//----
|
||||
ID:DWORD;
|
||||
function c(n1,n2:PsrCapability):Integer; static;
|
||||
end;
|
||||
|
||||
PsrCapabilityList=^TsrCapabilityList;
|
||||
TsrCapabilityList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrCapability,TsrCapability>;
|
||||
var
|
||||
FEmit:TCustomEmit;
|
||||
FNTree:TNodeFetch;
|
||||
Procedure Init(Emit:TCustomEmit);
|
||||
procedure Add(ID:DWORD);
|
||||
Function First:PsrCapability;
|
||||
Function Next(node:PsrCapability):PsrCapability;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TsrCapability.c(n1,n2:PsrCapability):Integer;
|
||||
begin
|
||||
Result:=Integer(n1^.ID>n2^.ID)-Integer(n1^.ID<n2^.ID);
|
||||
end;
|
||||
|
||||
Procedure TsrCapabilityList.Init(Emit:TCustomEmit);
|
||||
begin
|
||||
FEmit:=Emit;
|
||||
end;
|
||||
|
||||
procedure TsrCapabilityList.Add(ID:DWORD);
|
||||
var
|
||||
fnode:TsrCapability;
|
||||
pnode:PsrCapability;
|
||||
begin
|
||||
fnode:=Default(TsrCapability);
|
||||
fnode.ID:=ID;
|
||||
if (FNTree.Find(@fnode)<>nil) then Exit;
|
||||
pnode:=FEmit.Alloc(SizeOf(TsrCapability));
|
||||
Move(fnode,pnode^,SizeOf(TsrCapability));
|
||||
FNTree.Insert(pnode);
|
||||
end;
|
||||
|
||||
Function TsrCapabilityList.First:PsrCapability;
|
||||
begin
|
||||
Result:=FNTree.Min;
|
||||
end;
|
||||
|
||||
Function TsrCapabilityList.Next(node:PsrCapability):PsrCapability;
|
||||
begin
|
||||
Result:=FNTree.Next(node);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
unit srConfig;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
PsrConfig=^TsrConfig;
|
||||
TsrConfig=packed object
|
||||
PrintAsm:Boolean;
|
||||
UseVertexInput:Boolean; //True
|
||||
UseTexelBuffer:Boolean;
|
||||
UseOutput16:Boolean;
|
||||
//
|
||||
DescriptorSet:DWORD; //0
|
||||
//
|
||||
SpvVersion:PtrUint; // $10100
|
||||
maxUniformBufferRange:PtrUint; // $FFFF
|
||||
PushConstantsOffset:PtrUint; // 0
|
||||
maxPushConstantsSize:PtrUint; // 128
|
||||
minStorageBufferOffsetAlignment:PtrUint; // $10
|
||||
minUniformBufferOffsetAlignment:PtrUint; // $100
|
||||
//
|
||||
Procedure Init;
|
||||
Function CanUseStorageBufferClass:Boolean;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
Procedure TsrConfig.Init;
|
||||
begin
|
||||
UseVertexInput:=True;
|
||||
//
|
||||
SpvVersion:=$10100;
|
||||
maxUniformBufferRange:=$FFFF;
|
||||
maxPushConstantsSize:=128;
|
||||
minStorageBufferOffsetAlignment:=0;
|
||||
minUniformBufferOffsetAlignment:=0;
|
||||
end;
|
||||
|
||||
Function TsrConfig.CanUseStorageBufferClass:Boolean;
|
||||
begin
|
||||
Result:=(SpvVersion>=$10300);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -6,31 +6,48 @@ interface
|
|||
|
||||
uses
|
||||
spirv,
|
||||
srNodes,
|
||||
srNode,
|
||||
srOp;
|
||||
|
||||
type
|
||||
PsrHeaderList=^TsrHeaderList;
|
||||
TsrHeaderList=object(TsrOpBlockCustom)
|
||||
FGLSL_std_450:PSpirvOp;
|
||||
function emit_glsl_ext:PSpirvOp;
|
||||
end;
|
||||
|
||||
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);
|
||||
TsrDecorateList=object(TsrOpBlockCustom)
|
||||
procedure OpDecorate(Data:PsrNode;dec_id,param:DWORD);
|
||||
procedure OpMemberDecorate(Data:PsrNode;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);
|
||||
TsrDebugInfoList=object(TsrOpBlockCustom)
|
||||
procedure OpSourceExtension(const n:RawByteString);
|
||||
procedure OpName(Data:PsrNode;const n:RawByteString);
|
||||
function OpString(const n:RawByteString):PsrNode;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
procedure TsrDecorateList.emit_decorate(ntype:TsrNodeType;Data:Pointer;dec_id,param:DWORD);
|
||||
function TsrHeaderList.emit_glsl_ext:PSpirvOp;
|
||||
begin
|
||||
if (FGLSL_std_450=nil) then
|
||||
begin
|
||||
FGLSL_std_450:=AddSpirvOp(Op.OpExtInstImport);
|
||||
FGLSL_std_450^.pDst:=Emit.NewRefNode;
|
||||
FGLSL_std_450^.AddString('GLSL.std.450');
|
||||
end;
|
||||
Result:=FGLSL_std_450;
|
||||
end;
|
||||
|
||||
procedure TsrDecorateList.OpDecorate(Data:PsrNode;dec_id,param:DWORD);
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
node:=AddSpirvOp(Op.OpDecorate);
|
||||
node^.AddParam(ntype,Data);
|
||||
node^.AddParam(Data);
|
||||
node^.AddLiteral(dec_id,Decoration.GetStr(dec_id));
|
||||
Case dec_id of
|
||||
Decoration.BuiltIn:
|
||||
|
@ -48,18 +65,18 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure TsrDecorateList.emit_member_decorate(ntype:TsrNodeType;Data:Pointer;index,offset:DWORD);
|
||||
procedure TsrDecorateList.OpMemberDecorate(Data:PsrNode;index,offset:DWORD);
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
node:=AddSpirvOp(Op.OpMemberDecorate);
|
||||
node^.AddParam(ntype,Data);
|
||||
node^.AddParam(Data);
|
||||
node^.AddLiteral(index);
|
||||
node^.AddLiteral(Decoration.Offset,Decoration.GetStr(Decoration.Offset));
|
||||
node^.AddLiteral(offset);
|
||||
end;
|
||||
|
||||
procedure TsrDebugInfoList.emit_source_extension(const n:RawByteString);
|
||||
procedure TsrDebugInfoList.OpSourceExtension(const n:RawByteString);
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
|
@ -67,14 +84,24 @@ begin
|
|||
node^.AddString(n);
|
||||
end;
|
||||
|
||||
procedure TsrDebugInfoList.emit_name(ntype:TsrNodeType;Data:Pointer;const n:RawByteString);
|
||||
procedure TsrDebugInfoList.OpName(Data:PsrNode;const n:RawByteString);
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
node:=AddSpirvOp(Op.OpName);
|
||||
node^.AddParam(ntype,Data);
|
||||
node^.AddParam(Data);
|
||||
node^.AddString(n);
|
||||
end;
|
||||
|
||||
function TsrDebugInfoList.OpString(const n:RawByteString):PsrNode;
|
||||
var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
node:=AddSpirvOp(Op.OpString);
|
||||
node^.pDst:=Emit.NewRefNode;
|
||||
node^.AddString(n);
|
||||
Result:=node^.pDst;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
|
|
@ -0,0 +1,418 @@
|
|||
unit srFlow;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
spirv,
|
||||
srNode,
|
||||
srCFGLabel,
|
||||
srCFGParser,
|
||||
srCFGCursor,
|
||||
srReg,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
srConfig,
|
||||
emit_op;
|
||||
|
||||
type
|
||||
TEmitFlow=class(TEmitOp)
|
||||
//
|
||||
Procedure InitFlow;
|
||||
Procedure PushBlockOp(pLine:PspirvOp;pChild:PsrOpBlock;pLBlock:PsrCFGBlock);
|
||||
function PopBlockOp:Boolean;
|
||||
function CheckBlockBeg:Boolean;
|
||||
function CheckBlockEnd:Boolean;
|
||||
//
|
||||
function GetPtr:Pointer;
|
||||
procedure SetPtr(base:Pointer;bType:TsrBlockType);
|
||||
function IsFinalize:Boolean;
|
||||
function FindLabel(Adr:TSrcAdr):PsrLabel;
|
||||
//
|
||||
procedure Finalize;
|
||||
//
|
||||
function NextParse:Byte;
|
||||
function ParseStage(base:Pointer):Byte;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
Procedure TEmitFlow.InitFlow;
|
||||
begin
|
||||
CodeHeap.Init(Self);
|
||||
//
|
||||
InitBlock:=AllocBlockOp;
|
||||
InitBlock^.SetInfo(btOther,Cursor.Adr,Cursor.Adr);
|
||||
PushBlockOp(line,InitBlock,nil);
|
||||
Main^.PopBlock;
|
||||
end;
|
||||
|
||||
Procedure TEmitFlow.PushBlockOp(pLine:PspirvOp;pChild:PsrOpBlock;pLBlock:PsrCFGBlock);
|
||||
begin
|
||||
pChild^.FCursor:=Cursor; //prev
|
||||
|
||||
InsSpirvOp(pLine,PspirvOp(pChild));
|
||||
|
||||
Main^.PushBlock(pChild);
|
||||
|
||||
if (pLBlock<>nil) then
|
||||
begin
|
||||
Cursor.pBlock:=pLBlock; //push
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure UpdateVolMark(pBlock:PsrOpBlock);
|
||||
var
|
||||
pChild:PsrOpBlock;
|
||||
begin
|
||||
if (not pBlock^.IsType(ntOpBlock)) then Exit;
|
||||
if (pBlock^.Regs.FVolMark<>vmNone) then Exit;
|
||||
|
||||
pChild:=pBlock^.line; //last
|
||||
if (not pChild^.IsType(ntOpBlock)) then Exit;
|
||||
|
||||
Case pChild^.Block.bType of
|
||||
btAdr,
|
||||
btAdrBranch,
|
||||
btOther:;
|
||||
else
|
||||
Exit;
|
||||
end;
|
||||
|
||||
pBlock^.Regs.FVolMark:=pChild^.Regs.FVolMark;
|
||||
end;
|
||||
|
||||
function TEmitFlow.PopBlockOp:Boolean;
|
||||
var
|
||||
pOpBlock:PsrOpBlock;
|
||||
pOpChild:PsrOpBlock;
|
||||
pOpLabel:array[0..2] of PspirvOp;
|
||||
|
||||
branch_up:Boolean;
|
||||
|
||||
procedure pop_cond;
|
||||
begin
|
||||
Assert(pOpLabel[1]<>nil);
|
||||
|
||||
Case pOpBlock^.Regs.FVolMark of
|
||||
vmNone:PrivateList.build_volatile_cur(pOpBlock^.Regs.pSnap);
|
||||
vmEnd :PrivateList.build_volatile_dis(pOpBlock^.Regs.pSnap);
|
||||
else;
|
||||
end;
|
||||
|
||||
if not is_term_op(line) then
|
||||
begin
|
||||
OpBranch(line,pOpLabel[1]);
|
||||
end;
|
||||
|
||||
AddSpirvOp(line,pOpLabel[1]); //end
|
||||
end;
|
||||
|
||||
procedure pop_loop;
|
||||
begin
|
||||
//add OpLoopMerge continue
|
||||
|
||||
Assert(pOpLabel[0]<>nil);
|
||||
Assert(pOpLabel[1]<>nil);
|
||||
Assert(pOpLabel[2]<>nil);
|
||||
|
||||
Case pOpBlock^.Regs.FVolMark of
|
||||
vmNone:PrivateList.build_volatile_old(pOpBlock^.Regs.pSnap);
|
||||
else;
|
||||
end;
|
||||
|
||||
if pOpBlock^.Cond.FUseCont then //use continue
|
||||
begin
|
||||
|
||||
if not is_term_op(line) then
|
||||
begin
|
||||
OpBranch(line,pOpLabel[1]); //break
|
||||
end;
|
||||
|
||||
AddSpirvOp(line,pOpLabel[2]); //OpLoopMerge end
|
||||
|
||||
pOpChild:=AllocBlockOp;
|
||||
pOpChild^.SetInfo(btOther,Cursor.Adr,Cursor.Adr);
|
||||
PushBlockOp(line,pOpChild,nil);
|
||||
OpBranch(line,pOpLabel[0]); //continue
|
||||
Main^.PopBlock;
|
||||
|
||||
AddSpirvOp(line,pOpLabel[1]); //end
|
||||
|
||||
end else //dont used continue
|
||||
begin
|
||||
|
||||
if not is_term_op(line) then
|
||||
begin
|
||||
AddSpirvOp(line,NewLabelOp(True)); //devide
|
||||
end;
|
||||
|
||||
AddSpirvOp(line,pOpLabel[2]); //OpLoopMerge end
|
||||
|
||||
pOpChild:=AllocBlockOp;
|
||||
pOpChild^.SetInfo(btOther,Cursor.Adr,Cursor.Adr);
|
||||
PushBlockOp(line,pOpChild,nil);
|
||||
OpBranch(line,pOpLabel[1]); //break
|
||||
Main^.PopBlock;
|
||||
|
||||
AddSpirvOp(line,pOpLabel[1]); //end
|
||||
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
procedure pop_else;
|
||||
begin
|
||||
if (pOpLabel[1]<>nil) then
|
||||
begin
|
||||
if not is_term_op(line) then
|
||||
begin
|
||||
OpBranch(line,pOpLabel[1]);
|
||||
end;
|
||||
AddSpirvOp(line,pOpLabel[1]);
|
||||
end;
|
||||
end;
|
||||
|
||||
begin
|
||||
Result:=False;
|
||||
if (Main=nil) then Exit;
|
||||
|
||||
branch_up:=False;
|
||||
|
||||
repeat
|
||||
|
||||
pOpBlock:=Main^.pBlock;
|
||||
if (pOpBlock=nil) then Exit;
|
||||
|
||||
UpdateVolMark(pOpBlock);
|
||||
|
||||
pOpLabel[0]:=pOpBlock^.Labels.pBegOp;
|
||||
pOpLabel[1]:=pOpBlock^.Labels.pEndOp;
|
||||
pOpLabel[2]:=pOpBlock^.Labels.pMrgOp;
|
||||
|
||||
Case pOpBlock^.Block.bType of
|
||||
btCond:
|
||||
begin
|
||||
pop_cond;
|
||||
branch_up:=False;
|
||||
end;
|
||||
btLoop:
|
||||
begin
|
||||
pop_loop;
|
||||
branch_up:=False;
|
||||
end;
|
||||
else
|
||||
pop_else;
|
||||
end;
|
||||
|
||||
Case pOpBlock^.Block.bType of
|
||||
btAdr:
|
||||
begin
|
||||
Cursor:=pOpBlock^.FCursor;
|
||||
end;
|
||||
btAdrBranch:
|
||||
begin
|
||||
Cursor:=pOpBlock^.FCursor;
|
||||
branch_up:=True;
|
||||
end;
|
||||
btOther:; //nop
|
||||
else
|
||||
begin
|
||||
Cursor.PopBlock;
|
||||
end;
|
||||
end;
|
||||
|
||||
Result:=Main^.PopBlock;
|
||||
|
||||
until (not branch_up) or (not Result);
|
||||
|
||||
end;
|
||||
|
||||
function TEmitFlow.CheckBlockBeg:Boolean;
|
||||
var
|
||||
pLBlock:PsrCFGBlock;
|
||||
pOpLabel:array[0..3] of PspirvOp;
|
||||
pOpBlock:PsrOpBlock;
|
||||
pOpChild:PsrOpBlock;
|
||||
adr:TSrcAdr;
|
||||
Info:TsrBlockInfo;
|
||||
begin
|
||||
Result:=False;
|
||||
adr:=Cursor.Adr;
|
||||
if (FindLabel(adr)=nil) then Exit;
|
||||
|
||||
pLBlock:=Cursor.pBlock^.FindBlock(adr);
|
||||
if (pLBlock<>nil) then
|
||||
Case pLBlock^.bType of
|
||||
btLoop:
|
||||
begin
|
||||
PrivateList.make_copy_all;
|
||||
|
||||
Info:=Default(TsrBlockInfo);
|
||||
Info.b_adr:=pLBlock^.pBLabel^.Adr;
|
||||
Info.e_adr:=pLBlock^.pELabel^.Adr;
|
||||
Info.bType:=btLoop;
|
||||
|
||||
pOpLabel[0]:=NewLabelOp(False); //continue
|
||||
pOpLabel[1]:=NewLabelOp(False); //end
|
||||
pOpLabel[2]:=NewLabelOp(False); //cond
|
||||
pOpLabel[3]:=NewLabelOp(False); //start
|
||||
|
||||
pOpLabel[0]^.Adr:=Info.b_adr;
|
||||
pOpLabel[1]^.Adr:=Info.e_adr;
|
||||
pOpLabel[2]^.Adr:=Info.e_adr;
|
||||
pOpLabel[3]^.Adr:=Info.b_adr;
|
||||
|
||||
pOpBlock:=NewBlockOp(RegsStory.get_snapshot);
|
||||
pOpBlock^.SetLabels(pOpLabel[0],pOpLabel[1],pOpLabel[2]);
|
||||
pOpBlock^.SetInfo(Info);
|
||||
|
||||
PushBlockOp(line,pOpBlock,pLBlock);
|
||||
|
||||
OpBranch(line,pOpLabel[0]);
|
||||
AddSpirvOp(line,pOpLabel[0]); //continue loop
|
||||
|
||||
OpLoopMerge(line,pOpLabel[1],pOpLabel[2]);
|
||||
OpBranch(line,pOpLabel[3]);
|
||||
AddSpirvOp(line,pOpLabel[3]);
|
||||
|
||||
//down group
|
||||
Info.bType:=btOther;
|
||||
pOpChild:=AllocBlockOp;
|
||||
pOpChild^.SetInfo(Info);
|
||||
PushBlockOp(line,pOpChild,nil);
|
||||
end;
|
||||
btAdr,
|
||||
btAdrBranch: //skip
|
||||
begin
|
||||
adr:=pLBlock^.pELabel^.Adr;
|
||||
Cursor.Adr:=adr;
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
function TEmitFlow.CheckBlockEnd:Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
if (Main=nil) then Exit;
|
||||
if (Main^.pBlock=nil) then Exit;
|
||||
|
||||
if (Main^.pBlock^.Parent<>nil) and
|
||||
Main^.pBlock^.IsEndOf(Cursor.Adr) then
|
||||
begin
|
||||
Result:=PopBlockOp;
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TEmitFlow.GetPtr:Pointer;
|
||||
begin
|
||||
Result:=Cursor.Adr.get_pc;
|
||||
end;
|
||||
|
||||
procedure TEmitFlow.SetPtr(base:Pointer;bType:TsrBlockType);
|
||||
begin
|
||||
if (Cursor.Adr.get_pc=base) then Exit;
|
||||
Cursor:=CodeHeap.FetchByPtr(base,bType);
|
||||
end;
|
||||
|
||||
function TEmitFlow.IsFinalize:Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
if (Main^.pBlock^.Parent=nil) then
|
||||
if Cursor.pBlock^.IsEndOf(Cursor.Adr) then
|
||||
begin
|
||||
Result:=True;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TEmitFlow.FindLabel(Adr:TSrcAdr):PsrLabel;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (Cursor.pCode=nil) then Exit;
|
||||
Result:=Cursor.pCode^.FindLabel(Adr);
|
||||
end;
|
||||
|
||||
procedure TEmitFlow.Finalize;
|
||||
begin
|
||||
if (Main=nil) then Exit;
|
||||
|
||||
if (Main^.pBlock<>nil) then
|
||||
While (Main^.pBlock^.Parent<>nil) do
|
||||
begin
|
||||
PopBlockOp;
|
||||
end;
|
||||
|
||||
AddSpirvOp(Op.OpFunctionEnd);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TEmitFlow.NextParse:Byte;
|
||||
var
|
||||
FLevel:DWORD;
|
||||
begin
|
||||
if (Cursor.pCode=nil) then Exit(2);
|
||||
if (Cursor.pBlock=nil) then Exit(3);
|
||||
if (Main=nil) then Exit(4);
|
||||
if (Main^.pBlock=nil) then Exit(5);
|
||||
|
||||
if Config.PrintAsm then
|
||||
begin
|
||||
Write(HexStr(Cursor.OFFSET_DW*4,4));
|
||||
FLevel:=0;
|
||||
if (Main<>nil) then
|
||||
if (Main^.pBlock<>nil) then
|
||||
begin
|
||||
FLevel:=Main^.pBlock^.Level;
|
||||
end;
|
||||
Write(Space(FLevel+1));
|
||||
end;
|
||||
|
||||
Result:=Cursor.Next(FSPI);
|
||||
if (Result>1) then Exit;
|
||||
|
||||
if Config.PrintAsm then
|
||||
begin
|
||||
print_spi(FSPI);
|
||||
end;
|
||||
|
||||
emit_spi;
|
||||
|
||||
While (CheckBlockBeg) do;
|
||||
While (CheckBlockEnd) do;
|
||||
|
||||
Result:=0;
|
||||
if IsFinalize then
|
||||
begin
|
||||
Finalize;
|
||||
Result:=1;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
function TEmitFlow.ParseStage(base:Pointer):Byte;
|
||||
begin
|
||||
Result:=0;
|
||||
SetPtr(base,btMain);
|
||||
Main^.pTop^.SetCFGBlock(Cursor.pBlock);
|
||||
While (CheckBlockBeg) do;
|
||||
repeat
|
||||
Result:=NextParse;
|
||||
Case Result of
|
||||
0:;
|
||||
1:Break;
|
||||
else
|
||||
Break;
|
||||
end;
|
||||
until false;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -5,16 +5,18 @@ unit srFragLayout;
|
|||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
srNodes,
|
||||
srReg,
|
||||
srOp,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srInput,
|
||||
srCap,
|
||||
srDecorate;
|
||||
sysutils,
|
||||
spirv,
|
||||
ginodes,
|
||||
srNode,
|
||||
srType,
|
||||
srReg,
|
||||
srOp,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srInput,
|
||||
srCapability,
|
||||
srDecorate;
|
||||
|
||||
type
|
||||
//itPerspSample, //Sample
|
||||
|
@ -24,44 +26,63 @@ type
|
|||
//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;
|
||||
ntFragLayout=class(ntDescriptor)
|
||||
class function GetStorageName(node:PsrNode):RawByteString; override;
|
||||
end;
|
||||
|
||||
PsrFragLayout=^TsrFragLayout;
|
||||
TsrFragLayout=object(TsrDescriptor)
|
||||
private
|
||||
pLeft,pRight:PsrFragLayout;
|
||||
//----
|
||||
itype:TpsslInputType;
|
||||
function c(n1,n2:PsrFragLayout):Integer; static;
|
||||
public
|
||||
pReg:PsrRegNode;
|
||||
Procedure Init; inline;
|
||||
function GetStorageName:RawByteString;
|
||||
end;
|
||||
|
||||
PsrFragLayoutList=^TsrFragLayoutList;
|
||||
TsrFragLayoutList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrFragLayout,TsrFragLayout>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
FEmit:TCustomEmit;
|
||||
FNTree:TNodeFetch;
|
||||
procedure Init(cb:TfnAlloc);
|
||||
function Fetch(itype:TpsslInputType;location:DWORD):PsrFragLayout;
|
||||
procedure Init(Emit:TCustomEmit); inline;
|
||||
function Fetch(itype:TpsslInputType;location:DWORD;rtype:TsrDataType):PsrFragLayout;
|
||||
Function First:PsrFragLayout;
|
||||
Function Next(node:PsrFragLayout):PsrFragLayout;
|
||||
procedure AllocBinding(Decorates:PsrDecorateList;Cap:PsrCapList);
|
||||
procedure AllocBinding;
|
||||
procedure AllocEntryPoint(EntryPoint:PSpirvOp);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
class function ntFragLayout.GetStorageName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrFragLayout(node)^.GetStorageName;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TsrFragLayout.c(n1,n2:PsrFragLayout):Integer;
|
||||
begin
|
||||
//first itype
|
||||
Result:=Integer(n1^.itype>n2^.itype)-Integer(n1^.itype<n2^.itype);
|
||||
if (Result<>0) then Exit;
|
||||
//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;
|
||||
Procedure TsrFragLayout.Init; inline;
|
||||
begin
|
||||
fntype :=ntFragLayout;
|
||||
FStorage:=StorageClass.Input;
|
||||
end;
|
||||
|
||||
function TsrFragLayout.GetStorageName:RawByteString;
|
||||
begin
|
||||
Case itype of
|
||||
itPerspSample:
|
||||
|
@ -81,24 +102,28 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure TsrFragLayoutList.Init(cb:TfnAlloc);
|
||||
procedure TsrFragLayoutList.Init(Emit:TCustomEmit); inline;
|
||||
begin
|
||||
Alloc:=cb;
|
||||
FEmit:=Emit;
|
||||
end;
|
||||
|
||||
function TsrFragLayoutList.Fetch(itype:TpsslInputType;location:DWORD):PsrFragLayout;
|
||||
function TsrFragLayoutList.Fetch(itype:TpsslInputType;location:DWORD;rtype:TsrDataType):PsrFragLayout;
|
||||
var
|
||||
node:TsrFragLayout;
|
||||
begin
|
||||
node:=Default(TsrFragLayout);
|
||||
node.Init;
|
||||
node.itype:=itype;
|
||||
node.FStorage:=StorageClass.Input;
|
||||
node.FBinding:=location;
|
||||
Result:=FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrFragLayout));
|
||||
Result:=FEmit.Alloc(SizeOf(TsrFragLayout));
|
||||
Move(node,Result^,SizeOf(TsrFragLayout));
|
||||
//
|
||||
Result^.InitType(rtype,FEmit);
|
||||
Result^.InitVar(FEmit);
|
||||
//
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
@ -113,45 +138,48 @@ begin
|
|||
Result:=FNTree.Next(node);
|
||||
end;
|
||||
|
||||
procedure TsrFragLayoutList.AllocBinding(Decorates:PsrDecorateList;Cap:PsrCapList);
|
||||
procedure TsrFragLayoutList.AllocBinding;
|
||||
var
|
||||
pDecorateList:PsrDecorateList;
|
||||
pCapabilityList:PsrCapabilityList;
|
||||
node:PsrFragLayout;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (Decorates=nil) then Exit;
|
||||
pDecorateList:=FEmit.GetDecorateList;
|
||||
pCapabilityList:=FEmit.GetCapabilityList;
|
||||
//interpolate param
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
if (pVar<>nil) and node^.IsUsed then
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,node^.FBinding);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.Location,node^.FBinding);
|
||||
|
||||
case node^.itype of
|
||||
itPerspSample: //Sample
|
||||
begin
|
||||
Cap^.Add(Capability.SampleRateShading);
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Sample,0);
|
||||
pCapabilityList^.Add(Capability.SampleRateShading);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.Sample,0);
|
||||
end;
|
||||
itPerspCenter:; //default
|
||||
itPerspCentroid: //Centroid
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Centroid,0);
|
||||
pDecorateList^.OpDecorate(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);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.NoPerspective,0);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.Sample,0);
|
||||
end;
|
||||
itLinearCenter: //NoPerspective
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.NoPerspective,0);
|
||||
pDecorateList^.OpDecorate(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);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.NoPerspective,0);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.Centroid,0);
|
||||
end;
|
||||
else
|
||||
Assert(false,'AllocBinding');
|
||||
|
@ -172,9 +200,9 @@ begin
|
|||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
if (pVar<>nil) and node^.IsUsed then
|
||||
begin
|
||||
EntryPoint^.AddParam(ntVar,pVar);
|
||||
EntryPoint^.AddParam(pVar);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
|
|
|
@ -5,15 +5,18 @@ unit srInput;
|
|||
interface
|
||||
|
||||
uses
|
||||
typinfo,
|
||||
sysutils,
|
||||
spirv,
|
||||
srNodes,
|
||||
srReg,
|
||||
srOp,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srDecorate;
|
||||
typinfo,
|
||||
sysutils,
|
||||
spirv,
|
||||
ginodes,
|
||||
srNode,
|
||||
srType,
|
||||
srReg,
|
||||
srOp,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srCapability,
|
||||
srDecorate;
|
||||
|
||||
type
|
||||
TpsslInputType=(
|
||||
|
@ -42,90 +45,123 @@ type
|
|||
|
||||
itFloatPos,
|
||||
itFrontFace,
|
||||
itAncillary,
|
||||
itSampleCoverage,
|
||||
itPosFixed,
|
||||
|
||||
itTgid,
|
||||
itTgSize,
|
||||
|
||||
itThreadId
|
||||
itThreadId,
|
||||
|
||||
//
|
||||
itSampleId,
|
||||
itLayer,
|
||||
|
||||
itSubgroupLocalInvocationId
|
||||
);
|
||||
|
||||
ntInput=class(ntDescriptor)
|
||||
class function GetStorageName(node:PsrNode):RawByteString; override;
|
||||
end;
|
||||
|
||||
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;
|
||||
private
|
||||
pLeft,pRight:PsrInput;
|
||||
//----
|
||||
key:packed record
|
||||
itype:TpsslInputType;
|
||||
typeid:Byte;
|
||||
end;
|
||||
function c(n1,n2:PsrInput):Integer; static;
|
||||
public
|
||||
pReg:PsrRegNode;
|
||||
property itype:TpsslInputType read key.itype;
|
||||
property typeid:Byte read key.typeid;
|
||||
Procedure Init; inline;
|
||||
function GetStorageName:RawByteString;
|
||||
end;
|
||||
|
||||
PsrInputList=^TsrInputList;
|
||||
TsrInputList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrInput,TsrInput>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
FEmit:TCustomEmit;
|
||||
FNTree:TNodeFetch;
|
||||
procedure Init(cb:TfnAlloc);
|
||||
function Search(itype:TpsslInputType;id:Byte=0):PsrInput;
|
||||
function Fetch(itype:TpsslInputType;id:Byte=0):PsrInput;
|
||||
Procedure Init(Emit:TCustomEmit); inline;
|
||||
function Search(itype:TpsslInputType;id:Byte):PsrInput;
|
||||
function Fetch(rtype:TsrDataType;itype:TpsslInputType;id:Byte):PsrInput;
|
||||
Function First:PsrInput;
|
||||
Function Next(node:PsrInput):PsrInput;
|
||||
procedure AllocBinding(Decorates:PsrDecorateList);
|
||||
procedure AllocBinding;
|
||||
procedure AllocEntryPoint(EntryPoint:PSpirvOp);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TsrInput.c(n1,n2:PsrInput):Integer;
|
||||
class function ntInput.GetStorageName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=CompareByte(n1^.key,n2^.key,SizeOf(TsrInput.key));
|
||||
Result:=PsrInput(node)^.GetStorageName;
|
||||
end;
|
||||
|
||||
function TsrInput.GetName:RawByteString;
|
||||
//
|
||||
|
||||
function TsrInput.c(n1,n2:PsrInput):Integer;
|
||||
begin
|
||||
//first itype
|
||||
Result:=Integer(n1^.key.itype>n2^.key.itype)-Integer(n1^.key.itype<n2^.key.itype);
|
||||
if (Result<>0) then Exit;
|
||||
//second typeid
|
||||
Result:=Integer(n1^.key.typeid>n2^.key.typeid)-Integer(n1^.key.typeid<n2^.key.typeid);
|
||||
end;
|
||||
|
||||
Procedure TsrInput.Init; inline;
|
||||
begin
|
||||
fntype :=ntInput;
|
||||
FStorage:=StorageClass.Input;
|
||||
FBinding:=-1;
|
||||
end;
|
||||
|
||||
function TsrInput.GetStorageName:RawByteString;
|
||||
begin
|
||||
Result:=GetEnumName(TypeInfo(TpsslInputType),ord(key.itype))+IntToStr(key.typeid);
|
||||
end;
|
||||
|
||||
procedure TsrInputList.Init(cb:TfnAlloc);
|
||||
Procedure TsrInputList.Init(Emit:TCustomEmit); inline;
|
||||
begin
|
||||
Alloc:=cb;
|
||||
FEmit:=Emit;
|
||||
end;
|
||||
|
||||
function TsrInputList.Search(itype:TpsslInputType;id:Byte=0):PsrInput;
|
||||
function TsrInputList.Search(itype:TpsslInputType;id:Byte):PsrInput;
|
||||
var
|
||||
node:TsrInput;
|
||||
begin
|
||||
node:=Default(TsrInput);
|
||||
node.Init;
|
||||
node.key.itype:=itype;
|
||||
node.key.typeid:=id;
|
||||
Result:=FNTree.Find(@node);
|
||||
end;
|
||||
|
||||
function TsrInputList.Fetch(itype:TpsslInputType;id:Byte=0):PsrInput;
|
||||
function TsrInputList.Fetch(rtype:TsrDataType;itype:TpsslInputType;id:Byte):PsrInput;
|
||||
var
|
||||
node:TsrInput;
|
||||
begin
|
||||
node:=Default(TsrInput);
|
||||
node.Init;
|
||||
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));
|
||||
Result:=FEmit.Alloc(SizeOf(TsrInput));
|
||||
Move(node,Result^,SizeOf(TsrInput));
|
||||
//
|
||||
Result^.InitType(rtype,FEmit);
|
||||
Result^.InitVar(FEmit);
|
||||
//
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
@ -140,40 +176,54 @@ begin
|
|||
Result:=FNTree.Next(node);
|
||||
end;
|
||||
|
||||
procedure TsrInputList.AllocBinding(Decorates:PsrDecorateList);
|
||||
procedure TsrInputList.AllocBinding;
|
||||
var
|
||||
pDecorateList:PsrDecorateList;
|
||||
pCapabilityList:PsrCapabilityList;
|
||||
node:PsrInput;
|
||||
pVar:PsrVariable;
|
||||
|
||||
begin
|
||||
if (Decorates=nil) then Exit;
|
||||
pDecorateList :=FEmit.GetDecorateList;
|
||||
pCapabilityList:=FEmit.GetCapabilityList;
|
||||
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
if (pVar<>nil) and node^.IsUsed then
|
||||
begin
|
||||
Case node^.key.itype of
|
||||
itFloatPos:
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.FragCoord);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.FragCoord);
|
||||
end;
|
||||
itTgid:
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.WorkgroupId);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.WorkgroupId);
|
||||
end;
|
||||
itThreadId:
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.LocalInvocationID);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.LocalInvocationID);
|
||||
end;
|
||||
itVIndex:
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.VertexIndex);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.VertexIndex);
|
||||
end;
|
||||
itFrontFace:
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.FrontFacing);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.FrontFacing);
|
||||
end;
|
||||
|
||||
itLayer:
|
||||
begin
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.Layer);
|
||||
pCapabilityList^.Add(Capability.Geometry);
|
||||
end;
|
||||
itSampleId:
|
||||
begin
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.SampleId);
|
||||
end;
|
||||
|
||||
else
|
||||
{Assert(false,'AllocBinding')};
|
||||
end;
|
||||
|
@ -192,9 +242,9 @@ begin
|
|||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
if (pVar<>nil) and node^.IsUsed then
|
||||
begin
|
||||
EntryPoint^.AddParam(ntVar,pVar);
|
||||
EntryPoint^.AddParam(pVar);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
|
|
|
@ -0,0 +1,518 @@
|
|||
unit srInterface;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
ps4_pssl,
|
||||
spirv,
|
||||
srNode,
|
||||
srConfig,
|
||||
srAllocator,
|
||||
srCFGCursor,
|
||||
srRefId,
|
||||
srLiteral,
|
||||
srCapability,
|
||||
srDecorate,
|
||||
srType,
|
||||
srTypes,
|
||||
srConst,
|
||||
srReg,
|
||||
srVariable,
|
||||
srInput,
|
||||
srOutput,
|
||||
srLayout,
|
||||
srVertLayout,
|
||||
srFragLayout,
|
||||
srBuffer,
|
||||
srUniform,
|
||||
srPrivate,
|
||||
srBitcast,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
srCacheOp;
|
||||
|
||||
type
|
||||
TLocalSize=packed record
|
||||
x,y,z:DWORD;
|
||||
end;
|
||||
|
||||
TEmitInterface=class(TCustomEmit)
|
||||
FExecutionModel:Word;
|
||||
FLocalSize:TLocalSize;
|
||||
Config:TsrConfig;
|
||||
//
|
||||
FSPI:TSPI;
|
||||
//
|
||||
Allocator:TsrAllocator;
|
||||
//
|
||||
LiteralList :TsrLiteralList;
|
||||
TypeList :TsrTypeList;
|
||||
ConstList :TsrConstList;
|
||||
RegsStory :TsrRegsStory;
|
||||
CapabilityList:TsrCapabilityList;
|
||||
HeaderList :TsrHeaderList;
|
||||
DecorateList :TsrDecorateList;
|
||||
DebugInfoList :TsrDebugInfoList;
|
||||
VariableList :TsrVariableList;
|
||||
//
|
||||
InputList :TsrInputList;
|
||||
OutputList :TsrOutputList;
|
||||
//
|
||||
DataLayoutList:TsrDataLayoutList;
|
||||
VertLayoutList:TsrVertLayoutList;
|
||||
FragLayoutList:TsrFragLayoutList;
|
||||
//
|
||||
BufferList :TsrBufferList;
|
||||
UniformList :TsrUniformList;
|
||||
PrivateList :TsrPrivateList;
|
||||
//
|
||||
BitcastList :TsrBitcastList;
|
||||
CacheOpList :TsrCacheOpList;
|
||||
//
|
||||
FuncList :TsrFuncList;
|
||||
//
|
||||
CodeHeap :TsrCodeHeap;
|
||||
Cursor :TsrCursor;
|
||||
Main :PSpirvFunc;
|
||||
InitBlock:PsrOpBlock;
|
||||
//
|
||||
RefIdAlloc:TsrRefIdAlloc;
|
||||
//
|
||||
function Alloc(Size:ptruint):Pointer; override;
|
||||
Function GetConfig :Pointer; override;
|
||||
Function GetCodeHeap :Pointer; override;
|
||||
|
||||
Function GetLiteralList :Pointer; override;
|
||||
Function GetTypeList :Pointer; override;
|
||||
Function GetConstList :Pointer; override;
|
||||
Function GetRegsStory :Pointer; override;
|
||||
Function GetCapabilityList :Pointer; override;
|
||||
Function GetHeaderList :Pointer; override;
|
||||
Function GetDecorateList :Pointer; override;
|
||||
Function GetDebugInfoList :Pointer; override;
|
||||
Function GetVariableList :Pointer; override;
|
||||
Function GetInputList :Pointer; override;
|
||||
Function GetOutputList :Pointer; override;
|
||||
Function GetDataLayoutList :Pointer; override;
|
||||
Function GetVertLayoutList :Pointer; override;
|
||||
Function GetFragLayoutList :Pointer; override;
|
||||
Function GetBufferList :Pointer; override;
|
||||
Function GetUniformList :Pointer; override;
|
||||
Function GetBitcastList :Pointer; override;
|
||||
Function GetCacheOpList :Pointer; override;
|
||||
Function GetFuncList :Pointer; override;
|
||||
|
||||
Function GetCursor :Pointer; override;
|
||||
|
||||
function NewRefNode :PsrNode; override;
|
||||
//
|
||||
Function line :PspirvOp;
|
||||
Function curr_line :Pointer; override;
|
||||
function init_line :Pointer; override;
|
||||
//
|
||||
Procedure InitLists;
|
||||
//
|
||||
function NewVariable:Pointer;
|
||||
//
|
||||
function _get_line(ppLine:PPspirvOp):PspirvOp;
|
||||
//
|
||||
Function NewRegPair:PsrRegPair;
|
||||
Function NewReg(rtype:TsrDataType):PsrRegNode;
|
||||
Function NewReg(pConst:PsrConst;ppLine:PPspirvOp=nil):PsrRegNode;
|
||||
//
|
||||
Function NewReg_q(dtype:TsrDataType;value:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
||||
Function NewReg_b(value:Boolean;ppLine:PPspirvOp=nil):PsrRegNode;
|
||||
Function NewReg_i(dtype:TsrDataType;value:Integer;ppLine:PPspirvOp=nil):PsrRegNode;
|
||||
Function NewReg_s(dtype:TsrDataType;value:Single;ppLine:PPspirvOp=nil):PsrRegNode;
|
||||
//
|
||||
function NewSpirvOp(OpId:DWORD):PSpirvOp;
|
||||
function NewLabelOp(sdep:Boolean):PSpirvOp;
|
||||
function AddSpirvOp(OpId:DWORD):PSpirvOp;
|
||||
function AddSpirvOp(pLine:PspirvOp;OpId:DWORD):PSpirvOp;
|
||||
function AddSpirvOp(pLine,pNew:PspirvOp):PSpirvOp;
|
||||
function AddSGlslOp(pLine:PspirvOp;OpId:DWORD):PSpirvOp;
|
||||
//
|
||||
procedure PostLink(pLine,dst:PsrNode); override;
|
||||
procedure MakeCopy(dst:PsrRegSlot;src:PsrRegNode);
|
||||
//
|
||||
Procedure SetConst(pSlot:PsrRegSlot;pConst:PsrConst);
|
||||
Procedure SetConst_q(pSlot:PsrRegSlot;dtype:TsrDataType;value:QWORD);
|
||||
Procedure SetConst_b(pSlot:PsrRegSlot;value:Boolean);
|
||||
Procedure SetConst_i(pSlot:PsrRegSlot;dtype:TsrDataType;value:Integer);
|
||||
Procedure SetConst_s(pSlot:PsrRegSlot;dtype:TsrDataType;value:Single);
|
||||
//
|
||||
function AllocBlockOp:PsrOpBlock;
|
||||
function NewBlockOp(Snap:TsrRegsSnapshot):PsrOpBlock;
|
||||
function InsertBlockOp(pLine:PspirvOp;pChild:PsrOpBlock):PspirvOp;
|
||||
//
|
||||
procedure AddCapability(ID:DWORD);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TEmitInterface.Alloc(Size:ptruint):Pointer;
|
||||
begin
|
||||
Result:=Allocator.Alloc(Size);
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetConfig:Pointer;
|
||||
begin
|
||||
Result:=@Config;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetCodeHeap:Pointer;
|
||||
begin
|
||||
Result:=@CodeHeap;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetLiteralList:Pointer;
|
||||
begin
|
||||
Result:=@LiteralList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetTypeList:Pointer;
|
||||
begin
|
||||
Result:=@TypeList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetConstList:Pointer;
|
||||
begin
|
||||
Result:=@ConstList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetRegsStory:Pointer;
|
||||
begin
|
||||
Result:=@RegsStory;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetCapabilityList:Pointer;
|
||||
begin
|
||||
Result:=@CapabilityList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetHeaderList:Pointer;
|
||||
begin
|
||||
Result:=@HeaderList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetDecorateList:Pointer;
|
||||
begin
|
||||
Result:=@DecorateList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetDebugInfoList:Pointer;
|
||||
begin
|
||||
Result:=@DebugInfoList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetVariableList:Pointer;
|
||||
begin
|
||||
Result:=@VariableList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetInputList:Pointer;
|
||||
begin
|
||||
Result:=@InputList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetOutputList:Pointer;
|
||||
begin
|
||||
Result:=@OutputList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetDataLayoutList:Pointer;
|
||||
begin
|
||||
Result:=@DataLayoutList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetVertLayoutList:Pointer;
|
||||
begin
|
||||
Result:=@VertLayoutList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetFragLayoutList:Pointer;
|
||||
begin
|
||||
Result:=@FragLayoutList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetBufferList:Pointer;
|
||||
begin
|
||||
Result:=@BufferList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetUniformList:Pointer;
|
||||
begin
|
||||
Result:=@UniformList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetBitcastList:Pointer;
|
||||
begin
|
||||
Result:=@BitcastList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetCacheOpList:Pointer;
|
||||
begin
|
||||
Result:=@CacheOpList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetFuncList:Pointer;
|
||||
begin
|
||||
Result:=@FuncList;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.GetCursor:Pointer;
|
||||
begin
|
||||
Result:=@Cursor;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TEmitInterface.NewRefNode:PsrNode;
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrRefNode));
|
||||
PsrRefNode(Result)^.Init;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.line:PspirvOp;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (Main<>nil) then
|
||||
begin
|
||||
Result:=Main^.line;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TEmitInterface.curr_line:Pointer;
|
||||
begin
|
||||
Result:=line;
|
||||
end;
|
||||
|
||||
function TEmitInterface.init_line:Pointer;
|
||||
begin
|
||||
Assert(InitBlock<>nil);
|
||||
if (InitBlock^.dummy.Parent=nil) then //is not init?
|
||||
begin
|
||||
InitBlock^.Init(Self);
|
||||
end;
|
||||
Result:=InitBlock^.line;
|
||||
Assert(Result<>nil);
|
||||
end;
|
||||
|
||||
Procedure TEmitInterface.InitLists;
|
||||
begin
|
||||
Config.Init;
|
||||
|
||||
LiteralList .Init(Self);
|
||||
TypeList .Init(Self);
|
||||
ConstList .Init(Self);
|
||||
RegsStory .Init(Self);
|
||||
CapabilityList.Init(Self);
|
||||
HeaderList .Init(Self);
|
||||
DecorateList .Init(Self);
|
||||
DebugInfoList .Init(Self);
|
||||
VariableList .Init(Self);
|
||||
InputList .Init(Self);
|
||||
OutputList .Init(Self);
|
||||
DataLayoutList.Init(Self);
|
||||
VertLayoutList.Init(Self);
|
||||
FragLayoutList.Init(Self);
|
||||
BufferList .Init(Self);
|
||||
UniformList .Init(Self);
|
||||
PrivateList .Init(Self);
|
||||
BitcastList .Init(Self);
|
||||
CacheOpList .Init(Self);
|
||||
end;
|
||||
|
||||
function TEmitInterface.NewVariable:Pointer;
|
||||
begin
|
||||
Result:=VariableList.Fetch;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TEmitInterface._get_line(ppLine:PPspirvOp):PspirvOp;
|
||||
begin
|
||||
if (ppLine=nil) then Exit(line);
|
||||
if (ppLine^=nil) then Exit(line);
|
||||
Result:=ppLine^;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
Function TEmitInterface.NewRegPair:PsrRegPair;
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrRegPair));
|
||||
Result^.Init;
|
||||
end;
|
||||
|
||||
Function TEmitInterface.NewReg(rtype:TsrDataType):PsrRegNode;
|
||||
begin
|
||||
Result:=RegsStory.FUnattach.New(line,rtype);
|
||||
end;
|
||||
|
||||
Function TEmitInterface.NewReg(pConst:PsrConst;ppLine:PPspirvOp=nil):PsrRegNode;
|
||||
begin
|
||||
if (pConst=nil) then Exit(nil);
|
||||
Result:=NewReg(pConst^.dtype);
|
||||
Result^.pWriter:=pConst;
|
||||
Result^.pLine:=_get_line(ppLine);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
Function TEmitInterface.NewReg_q(dtype:TsrDataType;value:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
||||
begin
|
||||
Result:=NewReg(ConstList.Fetch(dtype,value),ppLine);
|
||||
end;
|
||||
|
||||
Function TEmitInterface.NewReg_b(value:Boolean;ppLine:PPspirvOp=nil):PsrRegNode;
|
||||
begin
|
||||
Result:=NewReg(ConstList.Fetch_b(value),ppLine);
|
||||
end;
|
||||
|
||||
Function TEmitInterface.NewReg_i(dtype:TsrDataType;value:Integer;ppLine:PPspirvOp=nil):PsrRegNode;
|
||||
begin
|
||||
Result:=NewReg(ConstList.Fetch_i(dtype,value),ppLine);
|
||||
end;
|
||||
|
||||
Function TEmitInterface.NewReg_s(dtype:TsrDataType;value:Single;ppLine:PPspirvOp=nil):PsrRegNode;
|
||||
begin
|
||||
Result:=NewReg(ConstList.Fetch_s(dtype,value),ppLine);
|
||||
end;
|
||||
|
||||
function TEmitInterface.NewSpirvOp(OpId:DWORD):PSpirvOp;
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TSpirvOp));
|
||||
Result^.Init(OpId);
|
||||
Result^.adr:=Cursor.Adr;
|
||||
end;
|
||||
|
||||
function TEmitInterface.NewLabelOp(sdep:Boolean):PSpirvOp;
|
||||
Var
|
||||
node:PSpirvOp;
|
||||
begin
|
||||
node:=NewSpirvOp(Op.OpLabel);
|
||||
node^.pDst:=NewRefNode;
|
||||
Result:=node;
|
||||
if sdep then node^.pDst^.mark_read(nil);
|
||||
end;
|
||||
|
||||
function TEmitInterface.AddSpirvOp(OpId:DWORD):PSpirvOp;
|
||||
begin
|
||||
Result:=AddSpirvOp(line,OpId);
|
||||
end;
|
||||
|
||||
function TEmitInterface.AddSpirvOp(pLine:PspirvOp;OpId:DWORD):PSpirvOp;
|
||||
begin
|
||||
Result:=InsSpirvOp(pLine,NewSpirvOp(OpId));
|
||||
end;
|
||||
|
||||
function TEmitInterface.AddSpirvOp(pLine,pNew:PspirvOp):PSpirvOp;
|
||||
begin
|
||||
Result:=InsSpirvOp(pLine,pNew);
|
||||
end;
|
||||
|
||||
function TEmitInterface.AddSGlslOp(pLine:PspirvOp;OpId:DWORD):PSpirvOp;
|
||||
var
|
||||
ext,node:PSpirvOp;
|
||||
begin
|
||||
ext:=HeaderList.emit_glsl_ext;
|
||||
node:=AddSpirvOp(pLine,Op.OpExtInst);
|
||||
node^.AddParam(ext^.pDst);
|
||||
node^.AddLiteral(OpId,GlslOp.GetStr(OpId));
|
||||
Result:=node;
|
||||
end;
|
||||
|
||||
procedure TEmitInterface.PostLink(pLine,dst:PsrNode);
|
||||
var
|
||||
node:PspirvOp;
|
||||
begin
|
||||
node:=pLine^.AsType(ntOpCustom);
|
||||
Assert(node<>nil);
|
||||
|
||||
if node^.IsType(ntOp) then
|
||||
if (node^.OpId=Op.OpNop) then
|
||||
begin
|
||||
node^.AddParam(dst);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
node:=AddSpirvOp(node,Op.OpNop);
|
||||
node^.AddParam(dst);
|
||||
node^.mark_not_used;
|
||||
end;
|
||||
|
||||
procedure TEmitInterface.MakeCopy(dst:PsrRegSlot;src:PsrRegNode);
|
||||
var
|
||||
node:PsrRegNode;
|
||||
begin
|
||||
node:=dst^.New(line,src^.dtype);
|
||||
node^.pWriter:=src;
|
||||
|
||||
PostLink(line,node); //post processing
|
||||
end;
|
||||
|
||||
Procedure TEmitInterface.SetConst(pSlot:PsrRegSlot;pConst:PsrConst);
|
||||
var
|
||||
dst:PsrRegNode;
|
||||
begin
|
||||
dst:=pSlot^.New(line,pConst^.dtype);
|
||||
dst^.pWriter:=pConst;
|
||||
|
||||
PostLink(line,dst); //post processing
|
||||
end;
|
||||
|
||||
Procedure TEmitInterface.SetConst_q(pSlot:PsrRegSlot;dtype:TsrDataType;value:QWORD);
|
||||
begin
|
||||
SetConst(pSlot,ConstList.Fetch(dtype,value));
|
||||
end;
|
||||
|
||||
Procedure TEmitInterface.SetConst_b(pSlot:PsrRegSlot;value:Boolean);
|
||||
begin
|
||||
SetConst(pSlot,ConstList.Fetch_b(value));
|
||||
end;
|
||||
|
||||
Procedure TEmitInterface.SetConst_i(pSlot:PsrRegSlot;dtype:TsrDataType;value:Integer);
|
||||
begin
|
||||
SetConst(pSlot,ConstList.Fetch_i(dtype,value));
|
||||
end;
|
||||
|
||||
Procedure TEmitInterface.SetConst_s(pSlot:PsrRegSlot;dtype:TsrDataType;value:Single);
|
||||
begin
|
||||
SetConst(pSlot,ConstList.Fetch_s(dtype,value));
|
||||
end;
|
||||
|
||||
function TEmitInterface.AllocBlockOp:PsrOpBlock;
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrOpBlock));
|
||||
Result^.Init(Self);
|
||||
end;
|
||||
|
||||
function TEmitInterface.NewBlockOp(Snap:TsrRegsSnapshot):PsrOpBlock;
|
||||
begin
|
||||
Result:=AllocBlockOp;
|
||||
Result^.Regs.pSnap :=Alloc(SizeOf(TsrRegsSnapshot));
|
||||
Result^.Regs.pSnap^:=Snap;
|
||||
Result^.Regs.FVolMark:=vmNone;
|
||||
Result^.Cond.FUseCont:=false;
|
||||
end;
|
||||
|
||||
function TEmitInterface.InsertBlockOp(pLine:PspirvOp;pChild:PsrOpBlock):PspirvOp;
|
||||
begin
|
||||
pLine:=InsSpirvOp(pLine,PspirvOp(pChild));
|
||||
pChild^.UpdateLevel;
|
||||
Result:=pLine;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
procedure TEmitInterface.AddCapability(ID:DWORD);
|
||||
begin
|
||||
CapabilityList.Add(ID);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
|
@ -5,18 +5,25 @@ unit srLayout;
|
|||
interface
|
||||
|
||||
uses
|
||||
ps4_shader,
|
||||
srNodes,
|
||||
srParser,
|
||||
srCFG,
|
||||
srTypes,
|
||||
srReg,
|
||||
srVariable,
|
||||
srRefId,
|
||||
srDecorate;
|
||||
sysutils,
|
||||
ps4_shader,
|
||||
spirv,
|
||||
ginodes,
|
||||
srNode,
|
||||
srCFGParser,
|
||||
srCFGCursor,
|
||||
srType,
|
||||
srTypes,
|
||||
srReg,
|
||||
srOp,
|
||||
srVariable,
|
||||
srBitcast,
|
||||
srRefId,
|
||||
srDecorate;
|
||||
|
||||
type
|
||||
TsrResourceType=(
|
||||
rtRoot,
|
||||
rtBufPtr2,
|
||||
rtFunPtr2,
|
||||
rtVSharp4,
|
||||
|
@ -26,41 +33,82 @@ type
|
|||
);
|
||||
|
||||
type
|
||||
ntChain=class(TsrNodeVmt)
|
||||
class Procedure zero_read (node:PsrNode); override;
|
||||
class Procedure zero_unread (node:PsrNode); override;
|
||||
class Function pwrite_count(node:PsrNode):PDWORD; override;
|
||||
class function Next (node:PsrNode):Pointer; override;
|
||||
class function Prev (node:PsrNode):Pointer; override;
|
||||
class function Parent (node:PsrNode):Pointer; override;
|
||||
class Procedure PrepType (node:PPrepTypeNode); override;
|
||||
class function GetPrintName(node:PsrNode):RawByteString; override;
|
||||
class function GetRef (node:PsrNode):Pointer; override;
|
||||
end;
|
||||
|
||||
PsrDataLayout=^TsrDataLayout;
|
||||
|
||||
PsrChainExt=^TsrChainExt;
|
||||
TsrChainExt=object
|
||||
PsrChainLvl_1=^TsrChainLvl_1;
|
||||
TsrChainLvl_1=object
|
||||
pIndex:PsrRegNode;
|
||||
stride:PtrUint;
|
||||
function c(n1,n2:PsrChainExt):Integer; static;
|
||||
function c(n1,n2:PsrChainLvl_1):Integer; static;
|
||||
end;
|
||||
|
||||
PsrChainLvl_0=^TsrChainLvl_0;
|
||||
TsrChainLvl_0=object
|
||||
size :PtrUint;
|
||||
offset:PtrUint;
|
||||
function c(n1,n2:PsrChainLvl_0):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;
|
||||
TsrChain=object(TsrNode)
|
||||
type
|
||||
PVNode=^TVNode;
|
||||
TVNode=record
|
||||
pPrev,pNext:PVNode;
|
||||
pLine:PspirvOp;
|
||||
end;
|
||||
TNodeList=specialize TNodeList<PVNode>;
|
||||
private
|
||||
pLeft,pRight:PsrChain;
|
||||
//--
|
||||
fwrite_count:DWORD;
|
||||
//--
|
||||
ID:TsrRefId; //post id
|
||||
FParent:PsrDataLayout;
|
||||
key:packed record
|
||||
lvl_1:TsrChainLvl_1;
|
||||
lvl_0:TsrChainLvl_0;
|
||||
end;
|
||||
Fdtype:TsrDataType;
|
||||
FList:TNodeList;
|
||||
function c(n1,n2:PsrChain):Integer; static;
|
||||
Procedure SetRegType(rtype:TsrDataType);
|
||||
public
|
||||
pField:Pointer;
|
||||
//pLine:Pointer;
|
||||
property Parent:PsrDataLayout read FParent;
|
||||
property pIndex:PsrRegNode read key.lvl_1.pIndex;
|
||||
property stride:PtrUint read key.lvl_1.stride;
|
||||
property size :PtrUint read key.lvl_0.size;
|
||||
property offset:PtrUint read key.lvl_0.offset;
|
||||
property dtype:TsrDataType read Fdtype write SetRegType;
|
||||
Procedure Init(L:PsrDataLayout);
|
||||
function Emit:TCustomEmit;
|
||||
Procedure UpdateRegType;
|
||||
Procedure PrepType(new:TsrDataType);
|
||||
procedure AddLine(pLine:PspirvOp);
|
||||
function FirstLine:PspirvOp;
|
||||
procedure FetchLoad(pLine:PspirvOp;dst:PsrRegNode);
|
||||
Procedure FetchStore(pLine:PspirvOp;src:PsrRegNode);
|
||||
function GetPrintName:RawByteString;
|
||||
end;
|
||||
|
||||
TsrChains=array[0..7] of PsrChain;
|
||||
|
||||
TChainCb=function(node:PsrChain):Integer of object;
|
||||
|
||||
//----
|
||||
|
||||
TsrDataLayout=object
|
||||
|
@ -76,45 +124,65 @@ type
|
|||
end;
|
||||
pData:Pointer;
|
||||
FID:Integer;
|
||||
Alloc:TfnAlloc;
|
||||
FEmit:TCustomEmit;
|
||||
FList:TChainFetch;
|
||||
function c(n1,n2:PsrDataLayout):Integer; static;
|
||||
function Fetch(o,s:PtrUint;ext:PsrChainExt):PsrChain;
|
||||
function Fetch(lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrChain;
|
||||
Function First:PsrChain;
|
||||
Function Last:PsrChain;
|
||||
Function Next(node:PsrChain):PsrChain;
|
||||
Function Prev(node:PsrChain):PsrChain;
|
||||
Function NextChain(node:PsrChain):PsrChain;
|
||||
Function PrevChain(node:PsrChain):PsrChain;
|
||||
function EnumChain(cb:TChainCb):Integer;
|
||||
function GetData:Pointer;
|
||||
function IsUserData:Boolean; inline;
|
||||
function GetStride:PtrUint;
|
||||
function GetTypeChar:Char;
|
||||
function GetString:RawByteString;
|
||||
function GetFuncString(LEN:DWORD):RawByteString;
|
||||
end;
|
||||
|
||||
PsrDataLayoutList=^TsrDataLayoutList;
|
||||
TsrDataLayoutList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrDataLayout,TsrDataLayout>;
|
||||
var
|
||||
FTop:TsrDataLayout;
|
||||
FNTree:TNodeFetch;
|
||||
procedure Init(cb:TfnAlloc);
|
||||
procedure Init(Emit:TCustomEmit);
|
||||
procedure SetUserData(pData:Pointer);
|
||||
function pRoot:PsrDataLayout;
|
||||
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;
|
||||
function EnumChain(cb:TChainCb):Integer;
|
||||
Procedure AllocID;
|
||||
procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
procedure AllocFuncExt(FDebugInfo:PsrDebugInfoList;var Heap:TsrCodeHeap);
|
||||
procedure AllocSourceExtension;
|
||||
procedure AllocFuncExt;
|
||||
end;
|
||||
|
||||
//----
|
||||
|
||||
ntDescriptor=class(TsrNodeVmt)
|
||||
class Procedure zero_read (node:PsrNode); override;
|
||||
class Procedure zero_unread (node:PsrNode); override;
|
||||
class Function GetPtype (node:PsrNode):PsrNode; override;
|
||||
class Function GetStorageClass(node:PsrNode):DWORD; override;
|
||||
end;
|
||||
|
||||
PsrDescriptor=^TsrDescriptor;
|
||||
TsrDescriptor=object
|
||||
pVar:PsrVariable;
|
||||
FStorage:DWORD;
|
||||
FBinding:Integer;
|
||||
TsrDescriptor=packed object(TsrNode)
|
||||
protected
|
||||
FVar:PsrVariable;
|
||||
FType:PsrType;
|
||||
FStorage:DWORD;
|
||||
FBinding:Integer;
|
||||
procedure InitVar(Emit:TCustomEmit);
|
||||
procedure InitType(rtype:TsrDataType;Emit:TCustomEmit);
|
||||
procedure SetType(t:PsrType);
|
||||
public
|
||||
property pVar:PsrVariable read FVar;
|
||||
property pType:PsrType read FType write SetType;
|
||||
end;
|
||||
|
||||
function is_consistents(const chains:TsrChains;count:Byte):Boolean;
|
||||
|
@ -124,6 +192,88 @@ function GetResourceSizeDw(r:TsrResourceType):Byte;
|
|||
|
||||
implementation
|
||||
|
||||
class Procedure ntChain.zero_read(node:PsrNode);
|
||||
begin
|
||||
With PsrChain(node)^ do
|
||||
begin
|
||||
key.lvl_1.pIndex^.mark_read(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
class Procedure ntChain.zero_unread(node:PsrNode);
|
||||
begin
|
||||
With PsrChain(node)^ do
|
||||
begin
|
||||
key.lvl_1.pIndex^.mark_unread(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
class Function ntChain.pwrite_count(node:PsrNode):PDWORD;
|
||||
begin
|
||||
Result:=@PsrChain(node)^.fwrite_count;
|
||||
end;
|
||||
|
||||
class function ntChain.Next(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=PsrChain(node)^.FParent^.NextChain(PsrChain(node));
|
||||
end;
|
||||
|
||||
class function ntChain.Prev(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=PsrChain(node)^.FParent^.PrevChain(PsrChain(node));
|
||||
end;
|
||||
|
||||
class function ntChain.Parent(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=PsrChain(node)^.FParent;
|
||||
end;
|
||||
|
||||
class Procedure ntChain.PrepType(node:PPrepTypeNode);
|
||||
begin
|
||||
PsrChain(node^.dnode)^.PrepType(TsrDataType(node^.rtype));
|
||||
node^.dnode:=nil;
|
||||
end;
|
||||
|
||||
class function ntChain.GetPrintName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrChain(node)^.GetPrintName;
|
||||
end;
|
||||
|
||||
class function ntChain.GetRef(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=@PsrChain(node)^.ID;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
class Procedure ntDescriptor.zero_read(node:PsrNode);
|
||||
begin
|
||||
With PsrDescriptor(node)^ do
|
||||
begin
|
||||
pType^.mark_read(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
class Procedure ntDescriptor.zero_unread(node:PsrNode);
|
||||
begin
|
||||
With PsrDescriptor(node)^ do
|
||||
begin
|
||||
pType^.mark_unread(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
class Function ntDescriptor.GetPtype(node:PsrNode):PsrNode;
|
||||
begin
|
||||
Result:=PsrDescriptor(node)^.FType;
|
||||
end;
|
||||
|
||||
class Function ntDescriptor.GetStorageClass(node:PsrNode):DWORD;
|
||||
begin
|
||||
Result:=PsrDescriptor(node)^.FStorage;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TsrDataLayout.c(n1,n2:PsrDataLayout):Integer;
|
||||
begin
|
||||
//first parent
|
||||
|
@ -136,37 +286,29 @@ begin
|
|||
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;
|
||||
function TsrDataLayout.Fetch(lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrChain;
|
||||
var
|
||||
node:TsrChain;
|
||||
begin
|
||||
node:=Default(TsrChain);
|
||||
node.key.offset:=o;
|
||||
node.key.size :=s;
|
||||
if (ext<>nil) then
|
||||
if (lvl_0<>nil) then
|
||||
begin
|
||||
node.key.ext:=ext^;
|
||||
node.key.lvl_0:=lvl_0^;
|
||||
end;
|
||||
if (lvl_1<>nil) then
|
||||
begin
|
||||
node.key.lvl_1:=lvl_1^;
|
||||
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');
|
||||
Result:=FEmit.Alloc(SizeOf(TsrChain));
|
||||
Move(node,Result^,SizeOf(TsrChain));
|
||||
|
||||
Result^.Init(@Self);
|
||||
|
||||
FList.Insert(Result);
|
||||
end else
|
||||
begin
|
||||
if (ext<>nil) then
|
||||
if (ext^.pIndex<>nil) then
|
||||
begin
|
||||
ext^.pIndex^.mark_unread;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -180,21 +322,38 @@ begin
|
|||
Result:=FList.Max;
|
||||
end;
|
||||
|
||||
Function TsrDataLayout.Next(node:PsrChain):PsrChain;
|
||||
Function TsrDataLayout.NextChain(node:PsrChain):PsrChain;
|
||||
begin
|
||||
Result:=FList.Next(node);
|
||||
end;
|
||||
|
||||
Function TsrDataLayout.Prev(node:PsrChain):PsrChain;
|
||||
Function TsrDataLayout.PrevChain(node:PsrChain):PsrChain;
|
||||
begin
|
||||
Result:=FList.Prev(node);
|
||||
end;
|
||||
|
||||
function TsrDataLayout.EnumChain(cb:TChainCb):Integer;
|
||||
var
|
||||
node:PsrChain;
|
||||
begin
|
||||
Result:=0;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if node^.IsUsed then
|
||||
begin
|
||||
Result:=Result+cb(node);
|
||||
end;
|
||||
node:=node^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataLayout.GetData:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (pData<>nil) then
|
||||
Case key.rtype of
|
||||
rtRoot,
|
||||
rtBufPtr2,
|
||||
rtFunPtr2:Result:=pData;
|
||||
rtVSharp4:Result:={%H-}Pointer(PVSharpResource4(pData)^.base);
|
||||
|
@ -209,16 +368,23 @@ begin
|
|||
Result:=0;
|
||||
if (pData<>nil) then
|
||||
Case key.rtype of
|
||||
rtRoot,
|
||||
rtBufPtr2:Result:=4;
|
||||
rtVSharp4:Result:=PVSharpResource4(pData)^.stride;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataLayout.IsUserData:Boolean; inline;
|
||||
begin
|
||||
Result:=(key.rtype=rtRoot);
|
||||
end;
|
||||
|
||||
function TsrDataLayout.GetTypeChar:Char;
|
||||
begin
|
||||
Result:=#0;
|
||||
case key.rtype of
|
||||
rtRoot :Result:='R';
|
||||
rtBufPtr2:Result:='B';
|
||||
rtFunPtr2:Result:='F';
|
||||
rtVSharp4:Result:='V';
|
||||
|
@ -249,9 +415,9 @@ begin
|
|||
';LEN='+HexStr(LEN,8);
|
||||
end;
|
||||
|
||||
procedure TsrDataLayoutList.Init(cb:TfnAlloc);
|
||||
procedure TsrDataLayoutList.Init(Emit:TCustomEmit);
|
||||
begin
|
||||
FTop.Alloc:=cb;
|
||||
FTop.FEmit:=Emit;
|
||||
FNTree.Insert(@FTop);
|
||||
end;
|
||||
|
||||
|
@ -260,38 +426,42 @@ begin
|
|||
FTop.pData:=pData;
|
||||
end;
|
||||
|
||||
function TsrDataLayoutList.pRoot:PsrDataLayout;
|
||||
begin
|
||||
Result:=@FTop;
|
||||
end;
|
||||
|
||||
function TsrDataLayoutList.Fetch(p:PsrDataLayout;o:PtrUint;t:TsrResourceType):PsrDataLayout;
|
||||
var
|
||||
node:TsrDataLayout;
|
||||
pData:Pointer;
|
||||
begin
|
||||
Assert(p<>nil);
|
||||
node:=Default(TsrDataLayout);
|
||||
node.Alloc:=FTop.Alloc;
|
||||
node.FEmit:=FTop.FEmit;
|
||||
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));
|
||||
Result:=FTop.FEmit.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;
|
||||
pData:=p^.GetData;
|
||||
if (pData<>nil) then
|
||||
case t of
|
||||
rtRoot,
|
||||
rtBufPtr2,
|
||||
rtFunPtr2:Result^.pData:={%H-}Pointer(PPtrUint(pData+o)^ and (not 3));
|
||||
rtVSharp4,
|
||||
rtSSharp4,
|
||||
rtTSharp4,
|
||||
rtTSharp8:Result^.pData:=pData+o;
|
||||
end;
|
||||
|
||||
end;
|
||||
end;
|
||||
|
@ -310,6 +480,7 @@ function GetResourceSizeDw(r:TsrResourceType):Byte;
|
|||
begin
|
||||
Result:=0;
|
||||
Case r of
|
||||
rtRoot :Result:=2;
|
||||
rtBufPtr2:Result:=2;
|
||||
rtFunPtr2:Result:=2;
|
||||
rtVSharp4:Result:=4;
|
||||
|
@ -333,7 +504,21 @@ begin
|
|||
Assert(False,'indexed chain not support');
|
||||
end;
|
||||
|
||||
Result:=Fetch(chain[0]^.parent,chain[0]^.key.offset,rtype);
|
||||
Result:=Fetch(chain[0]^.Parent,chain[0]^.offset,rtype);
|
||||
end;
|
||||
|
||||
function TsrDataLayoutList.EnumChain(cb:TChainCb):Integer;
|
||||
var
|
||||
node:PsrDataLayout;
|
||||
begin
|
||||
Result:=0;
|
||||
if (cb=nil) then Exit;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
Result:=Result+node^.EnumChain(cb);
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrDataLayoutList.AllocID;
|
||||
|
@ -354,40 +539,53 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
procedure TsrDataLayoutList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
procedure TsrDataLayoutList.AllocSourceExtension;
|
||||
var
|
||||
pDebugInfoList:PsrDebugInfoList;
|
||||
node:PsrDataLayout;
|
||||
begin
|
||||
if (FDebugInfo=nil) then Exit;
|
||||
pDebugInfoList:=FTop.FEmit.GetDebugInfoList;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
FDebugInfo^.emit_source_extension(node^.GetString);
|
||||
pDebugInfoList^.OpSourceExtension(node^.GetString);
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrDataLayoutList.AllocFuncExt(FDebugInfo:PsrDebugInfoList;var Heap:TsrCodeHeap);
|
||||
procedure TsrDataLayoutList.AllocFuncExt;
|
||||
var
|
||||
pDebugInfoList:PsrDebugInfoList;
|
||||
pHeap:PsrCodeHeap;
|
||||
node:PsrDataLayout;
|
||||
block:PsrCodeBlock;
|
||||
begin
|
||||
pDebugInfoList:=FTop.FEmit.GetDebugInfoList;
|
||||
pHeap:=FTop.FEmit.GetCodeHeap;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.key.rtype=rtFunPtr2) then
|
||||
begin
|
||||
block:=Heap.FindByPtr(node^.pData);
|
||||
block:=pHeap^.FindByPtr(node^.pData);
|
||||
if (block<>nil) then
|
||||
begin
|
||||
FDebugInfo^.emit_source_extension(node^.GetFuncString(block^.Size));
|
||||
pDebugInfoList^.OpSourceExtension(node^.GetFuncString(block^.Size));
|
||||
end;
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrChainExt.c(n1,n2:PsrChainExt):Integer;
|
||||
//
|
||||
|
||||
Procedure TsrChain.Init(L:PsrDataLayout);
|
||||
begin
|
||||
fntype:=ntChain;
|
||||
FParent:=L;
|
||||
end;
|
||||
|
||||
function TsrChainLvl_1.c(n1,n2:PsrChainLvl_1):Integer;
|
||||
begin
|
||||
//first pIndex forward
|
||||
Result:=Integer(n1^.pIndex>n2^.pIndex)-Integer(n1^.pIndex<n2^.pIndex);
|
||||
|
@ -397,62 +595,237 @@ begin
|
|||
Result:=Integer(n1^.stride>n2^.stride)-Integer(n1^.stride<n2^.stride);
|
||||
end;
|
||||
|
||||
function TsrChainLvl_0.c(n1,n2:PsrChainLvl_0):Integer;
|
||||
begin
|
||||
//first size backward
|
||||
Result:=Integer(n1^.size<n2^.size)-Integer(n1^.size>n2^.size);
|
||||
if (Result<>0) then Exit;
|
||||
|
||||
//second offset forward
|
||||
Result:=Integer(n1^.offset>n2^.offset)-Integer(n1^.offset<n2^.offset);
|
||||
end;
|
||||
|
||||
function TsrChain.c(n1,n2:PsrChain):Integer;
|
||||
begin
|
||||
//first ext
|
||||
Result:=TsrChainExt.c(@n1^.key.ext,@n2^.key.ext);
|
||||
//first lvl_1
|
||||
Result:=TsrChainLvl_1.c(@n1^.key.lvl_1,@n2^.key.lvl_1);
|
||||
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);
|
||||
//second lvl_0
|
||||
Result:=TsrChainLvl_0.c(@n1^.key.lvl_0,@n2^.key.lvl_0);
|
||||
end;
|
||||
|
||||
Procedure TsrChain.mark_read;
|
||||
function TsrChain.Emit:TCustomEmit;
|
||||
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);
|
||||
Result:=FParent^.FEmit;
|
||||
end;
|
||||
|
||||
Procedure TsrChain.SetRegType(rtype:TsrDataType);
|
||||
var
|
||||
node:PsrRegNode;
|
||||
pTypeList:PsrTypeList;
|
||||
FType:PsrType;
|
||||
node:PVNode;
|
||||
pLine:PspirvOp;
|
||||
begin
|
||||
node:=rSlot.pStory.pHead;
|
||||
Fdtype:=rtype;
|
||||
|
||||
pTypeList:=Emit.GetTypeList;
|
||||
FType:=pTypeList^.Fetch(rtype);
|
||||
|
||||
node:=FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
node^.dtype:=rtype;
|
||||
pLine:=node^.pLine;
|
||||
|
||||
Case pLine^.OpId of
|
||||
|
||||
Op.OpLoad:
|
||||
begin
|
||||
pLine^.pDst^.PrepType(ord(rtype));
|
||||
pLine^.pType:=Ftype;
|
||||
end;
|
||||
|
||||
Op.OpStore:
|
||||
begin
|
||||
pLine^.ParamFirst^.Value^.PrepType(ord(rtype));
|
||||
end;
|
||||
|
||||
else;
|
||||
end;
|
||||
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrChain.GetRegType:TsrDataType;
|
||||
Procedure TsrChain.UpdateRegType;
|
||||
var
|
||||
pReg:PsrRegNode;
|
||||
pTypeList:PsrTypeList;
|
||||
pBitcastList:PsrBitcastList;
|
||||
FType:PsrType;
|
||||
node:PVNode;
|
||||
pLine:PspirvOp;
|
||||
dst:PsrRegNode;
|
||||
old,rtype:TsrDataType;
|
||||
begin
|
||||
Result:=dtUnknow;
|
||||
pReg:=rSlot.current;
|
||||
if (pReg=nil) then Exit;
|
||||
Result:=pReg^.dtype;
|
||||
rtype:=Fdtype;
|
||||
|
||||
pTypeList:=Emit.GetTypeList;
|
||||
FType:=pTypeList^.Fetch(rtype);
|
||||
|
||||
pBitcastList:=Emit.GetBitcastList;
|
||||
|
||||
node:=FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pLine:=node^.pLine;
|
||||
|
||||
Case pLine^.OpId of
|
||||
|
||||
Op.OpLoad:
|
||||
begin
|
||||
pLine^.pDst^.PrepType(ord(rtype));
|
||||
pLine^.pType:=Ftype;
|
||||
|
||||
dst:=pLine^.pDst^.AsType(ntReg);
|
||||
if (dst<>nil) then
|
||||
begin
|
||||
old:=dst^.dtype;
|
||||
if (old<>dtUnknow) and (not CompareType(rtype,old)) then
|
||||
begin
|
||||
//OpLoad -> new -> dst
|
||||
pBitcastList:=Emit.GetBitcastList;
|
||||
dst:=pBitcastList^.FetchDstr(rtype,dst);
|
||||
pLine^.pDst:=dst;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Op.OpStore:
|
||||
begin
|
||||
pLine^.ParamFirst^.Value^.PrepType(ord(rtype));
|
||||
|
||||
dst:=pLine^.ParamFirst^.Value^.AsType(ntReg);
|
||||
if (dst<>nil) then
|
||||
begin
|
||||
old:=dst^.dtype;
|
||||
if (old<>dtUnknow) and (rtype<>old) then
|
||||
begin
|
||||
//OpStore <- new <- dst
|
||||
pBitcastList:=Emit.GetBitcastList;
|
||||
dst:=pBitcastList^.FetchRead(rtype,dst);
|
||||
pLine^.ParamFirst^.Value:=dst;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
else;
|
||||
end;
|
||||
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrChain.IsUsed:Boolean;
|
||||
Procedure TsrChain.PrepType(new:TsrDataType);
|
||||
var
|
||||
old:TsrDataType;
|
||||
begin
|
||||
Result:=((read_count<>0) or
|
||||
(write_count<>0)) and
|
||||
(rSlot.current<>nil);
|
||||
if (new=dtUnknow) then Exit;
|
||||
old:=Fdtype;
|
||||
if is_unprep_type(old,new,True) then
|
||||
begin
|
||||
old:=StoreType(new);
|
||||
SetRegType(old);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrChain.AddLine(pLine:PspirvOp);
|
||||
var
|
||||
node:PVNode;
|
||||
begin
|
||||
node:=Emit.Alloc(SizeOf(TVNode));
|
||||
node^.pLine:=pLine;
|
||||
FList.Push_tail(node);
|
||||
end;
|
||||
|
||||
function TsrChain.FirstLine:PspirvOp;
|
||||
var
|
||||
node:PVNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=FList.pHead;
|
||||
if (node<>nil) then
|
||||
begin
|
||||
Result:=node^.pLine;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrChain.FetchLoad(pLine:PspirvOp;dst:PsrRegNode);
|
||||
var
|
||||
pTypeList:PsrTypeList;
|
||||
begin
|
||||
Assert(dst<>nil);
|
||||
|
||||
PrepType(dst^.dtype);
|
||||
|
||||
pTypeList:=Emit.GetTypeList;
|
||||
pLine:=PspirvOp(Emit.OpLoad(pLine,pTypeList^.Fetch(Fdtype),dst,@Self));
|
||||
|
||||
AddLine(pLine);
|
||||
end;
|
||||
|
||||
Procedure TsrChain.FetchStore(pLine:PspirvOp;src:PsrRegNode);
|
||||
begin
|
||||
if (src=nil) then Exit;
|
||||
|
||||
PrepType(src^.dtype);
|
||||
|
||||
pLine:=PspirvOp(Emit.OpStore(pLine,@Self,src));
|
||||
|
||||
AddLine(pLine);
|
||||
end;
|
||||
|
||||
function TsrChain.GetPrintName:RawByteString;
|
||||
begin
|
||||
Assert(ID.Alloc);
|
||||
Result:='ac'+IntToStr(ID.ID);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
procedure TsrDescriptor.InitVar(Emit:TCustomEmit);
|
||||
var
|
||||
pVariableList:PsrVariableList;
|
||||
begin
|
||||
if (Emit=nil) then Exit;
|
||||
if (FVar<>nil) then Exit;
|
||||
//
|
||||
pVariableList:=Emit.GetVariableList;
|
||||
//
|
||||
FVar:=pVariableList^.Fetch;
|
||||
FVar^.pSource:=@Self;
|
||||
end;
|
||||
|
||||
procedure TsrDescriptor.InitType(rtype:TsrDataType;Emit:TCustomEmit);
|
||||
var
|
||||
pTypeList:PsrTypeList;
|
||||
begin
|
||||
if (Emit=nil) then Exit;
|
||||
if (FType<>nil) then Exit;
|
||||
//
|
||||
pTypeList:=Emit.GetTypeList;
|
||||
//
|
||||
SetType(pTypeList^.Fetch(rtype));
|
||||
end;
|
||||
|
||||
procedure TsrDescriptor.SetType(t:PsrType);
|
||||
begin
|
||||
if (FType=t) then Exit;
|
||||
if not IsUsed then
|
||||
begin
|
||||
t^.mark_read (@Self);
|
||||
FType^.mark_unread(@Self);
|
||||
end;
|
||||
FType:=t;
|
||||
end;
|
||||
|
||||
function is_consistents(const chains:TsrChains;count:Byte):Boolean;
|
||||
|
@ -467,14 +840,14 @@ begin
|
|||
Result:=False;
|
||||
if (chains[0]=nil) then Exit;
|
||||
parent:=chains[0]^.parent;
|
||||
offset:=chains[0]^.key.offset;
|
||||
offset:=chains[0]^.offset;
|
||||
For i:=1 to count-1 do
|
||||
begin
|
||||
t:=chains[i-1]^.key.size;
|
||||
t:=chains[i-1]^.size;
|
||||
offset:=offset+t;
|
||||
if (chains[i]=nil) then Exit;
|
||||
if (chains[i]^.parent<>parent) then Exit;
|
||||
t:=chains[i]^.key.offset;
|
||||
t:=chains[i]^.offset;
|
||||
if (offset<>t) then Exit;
|
||||
end;
|
||||
Result:=True;
|
||||
|
@ -489,7 +862,7 @@ begin
|
|||
For i:=0 to count-1 do
|
||||
begin
|
||||
if (chains[i]=nil) then Exit;
|
||||
if (chains[i]^.key.ext.pIndex<>nil) then Exit;
|
||||
if (chains[i]^.key.lvl_1.pIndex<>nil) then Exit;
|
||||
end;
|
||||
Result:=True;
|
||||
end;
|
||||
|
|
|
@ -0,0 +1,443 @@
|
|||
unit srLiteral;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
half16,
|
||||
srType,
|
||||
ginodes,
|
||||
srNode;
|
||||
|
||||
type
|
||||
ntLiteral=class(TsrNodeVmt)
|
||||
class function GetPrintData(node:PsrNode):RawByteString; override;
|
||||
class function GetData(node:PsrNode;data:Pointer):Ptruint; override;
|
||||
end;
|
||||
|
||||
ntLiteralString=class(ntLiteral)
|
||||
class function GetPrintData(node:PsrNode):RawByteString; override;
|
||||
class function GetData(node:PsrNode;data:Pointer):Ptruint; override;
|
||||
end;
|
||||
|
||||
ntLiteralConst=class(ntLiteral)
|
||||
class function GetPrintData(node:PsrNode):RawByteString; override;
|
||||
class function GetData(node:PsrNode;data:Pointer):Ptruint; override;
|
||||
end;
|
||||
|
||||
PsrLiteral=^TsrLiteral;
|
||||
TsrLiteral=object(TsrNode)
|
||||
private
|
||||
pLeft,pRight:PsrLiteral;
|
||||
public
|
||||
dtype:TsrDataType;
|
||||
Value:PtrUint;
|
||||
name:PChar;
|
||||
function c(n1,n2:PsrLiteral):Integer; static;
|
||||
Procedure Init; inline;
|
||||
Function AsBool:Boolean; inline;
|
||||
Function AsUint8:Byte; inline;
|
||||
Function AsInt8:Shortint; inline;
|
||||
Function AsUint16:Word; inline;
|
||||
Function AsInt16:Smallint; inline;
|
||||
Function AsUint32:DWORD; inline;
|
||||
function AsInt32:Integer; inline;
|
||||
Function AsUint64:QWORD; inline;
|
||||
Function AsInt64:Int64; inline;
|
||||
Function AsHalf16:THalf16; inline;
|
||||
Function AsFloat32:Single; inline;
|
||||
Function AsFloat64:Double; inline;
|
||||
Function GetPrintData:RawByteString;
|
||||
Function GetData(data:Pointer):Ptruint;
|
||||
end;
|
||||
|
||||
PsrLiteralString=^TsrLiteralString;
|
||||
TsrLiteralString=object(TsrLiteral)
|
||||
Procedure Init; inline;
|
||||
Function GetPrintData:RawByteString;
|
||||
Function GetData(data:Pointer):Ptruint;
|
||||
end;
|
||||
|
||||
PsrLiteralConst=^TsrLiteralConst;
|
||||
TsrLiteralConst=object(TsrLiteral)
|
||||
Procedure Init; inline;
|
||||
Function GetPrintData:RawByteString;
|
||||
Function GetData(data:Pointer):Ptruint;
|
||||
end;
|
||||
|
||||
PsrLiteralList=^TsrLiteralList;
|
||||
TsrLiteralList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrLiteral,TsrLiteral>;
|
||||
var
|
||||
FEmit:TCustomEmit;
|
||||
FNTree:TNodeFetch;
|
||||
Procedure Init(Emit:TCustomEmit);
|
||||
function FetchLiteral(Value:PtrUint;name:PChar):PsrLiteral;
|
||||
function FetchString(name:PChar):PsrLiteralString;
|
||||
function FetchConst(dtype:TsrDataType;Value:PtrUint):PsrLiteralConst;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
class function ntLiteral.GetPrintData(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrLiteral(node)^.GetPrintData;
|
||||
end;
|
||||
|
||||
class function ntLiteral.GetData(node:PsrNode;data:Pointer):Ptruint;
|
||||
begin
|
||||
Result:=PsrLiteral(node)^.GetData(data);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
class function ntLiteralString.GetPrintData(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrLiteralString(node)^.GetPrintData;
|
||||
end;
|
||||
|
||||
class function ntLiteralString.GetData(node:PsrNode;data:Pointer):Ptruint;
|
||||
begin
|
||||
Result:=PsrLiteralString(node)^.GetData(data);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
class function ntLiteralConst.GetPrintData(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrLiteralConst(node)^.GetPrintData;
|
||||
end;
|
||||
|
||||
class function ntLiteralConst.GetData(node:PsrNode;data:Pointer):Ptruint;
|
||||
begin
|
||||
Result:=PsrLiteralConst(node)^.GetData(data);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TsrLiteral.c(n1,n2:PsrLiteral):Integer;
|
||||
begin
|
||||
Result:=ord(ptruint(n1^.fntype)>ptruint(n2^.fntype))-ord(ptruint(n1^.fntype)<ptruint(n2^.fntype));
|
||||
if (Result<>0) then Exit;
|
||||
//
|
||||
Result:=Integer(ord(n1^.dtype)>ord(n2^.dtype))-Integer(ord(n1^.dtype)<ord(n2^.dtype));
|
||||
if (Result<>0) then Exit;
|
||||
//
|
||||
Result:=Integer(n1^.Value>n2^.Value)-Integer(n1^.Value<n2^.Value);
|
||||
if (Result<>0) then Exit;
|
||||
//
|
||||
Result:=ComparePChar(n1^.name,n2^.name);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
Procedure TsrLiteral.Init; inline;
|
||||
begin
|
||||
fntype:=ntLiteral;
|
||||
end;
|
||||
|
||||
Function TsrLiteral.AsBool:Boolean; inline;
|
||||
begin
|
||||
Assert(@Self<>nil);
|
||||
Result:=PBoolean(@Value)^;
|
||||
end;
|
||||
|
||||
Function TsrLiteral.AsUint8:Byte; inline;
|
||||
begin
|
||||
Assert(@Self<>nil);
|
||||
Result:=PByte(@Value)^;
|
||||
end;
|
||||
|
||||
Function TsrLiteral.AsInt8:Shortint; inline;
|
||||
begin
|
||||
Assert(@Self<>nil);
|
||||
Result:=PShortint(@Value)^;
|
||||
end;
|
||||
|
||||
Function TsrLiteral.AsUint16:Word; inline;
|
||||
begin
|
||||
Assert(@Self<>nil);
|
||||
Result:=PWord(@Value)^;
|
||||
end;
|
||||
|
||||
Function TsrLiteral.AsInt16:Smallint; inline;
|
||||
begin
|
||||
Assert(@Self<>nil);
|
||||
Result:=PSmallint(@Value)^;
|
||||
end;
|
||||
|
||||
Function TsrLiteral.AsUint32:DWORD; inline;
|
||||
begin
|
||||
Assert(@Self<>nil);
|
||||
Result:=PDWORD(@Value)^;
|
||||
end;
|
||||
|
||||
Function TsrLiteral.AsInt32:Integer; inline;
|
||||
begin
|
||||
Assert(@Self<>nil);
|
||||
Result:=PInteger(@Value)^;
|
||||
end;
|
||||
|
||||
Function TsrLiteral.AsUint64:QWORD; inline;
|
||||
begin
|
||||
Assert(@Self<>nil);
|
||||
Result:=Value;
|
||||
end;
|
||||
|
||||
Function TsrLiteral.AsInt64:Int64; inline;
|
||||
begin
|
||||
Assert(@Self<>nil);
|
||||
Result:=Int64(Value);
|
||||
end;
|
||||
|
||||
Function TsrLiteral.AsHalf16:THalf16; inline;
|
||||
begin
|
||||
Assert(@Self<>nil);
|
||||
Result:=PHalf16(@Value)^
|
||||
end;
|
||||
|
||||
Function TsrLiteral.AsFloat32:Single; inline;
|
||||
begin
|
||||
Assert(@Self<>nil);
|
||||
Result:=PSingle(@Value)^;
|
||||
end;
|
||||
|
||||
Function TsrLiteral.AsFloat64:Double; inline;
|
||||
begin
|
||||
Assert(@Self<>nil);
|
||||
Result:=PDouble(@Value)^;
|
||||
end;
|
||||
|
||||
Function TsrLiteral.GetPrintData:RawByteString;
|
||||
begin
|
||||
if (name=nil) or (StrLen(name)=0) then
|
||||
begin
|
||||
Result:=IntToStr(Value);
|
||||
end else
|
||||
begin
|
||||
Result:=name;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrLiteral.GetData(data:Pointer):Ptruint;
|
||||
begin
|
||||
Result:=SizeOf(DWORD);
|
||||
if (data<>nil) then
|
||||
begin
|
||||
PDWORD(data)^:=DWORD(Value);
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
Procedure TsrLiteralString.Init; inline;
|
||||
begin
|
||||
fntype:=ntLiteralString;
|
||||
end;
|
||||
|
||||
Function TsrLiteralString.GetPrintData:RawByteString;
|
||||
begin
|
||||
Result:='"'+name+'"';
|
||||
end;
|
||||
|
||||
Function TsrLiteralString.GetData(data:Pointer):Ptruint;
|
||||
begin
|
||||
Result:=StrLen(name)+1;
|
||||
if (data<>nil) then
|
||||
begin
|
||||
Move(name^,data^,Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
Procedure TsrLiteralConst.Init; inline;
|
||||
begin
|
||||
fntype:=ntLiteralConst;
|
||||
end;
|
||||
|
||||
const
|
||||
DefaultFormatSettings : TFormatSettings = (
|
||||
CurrencyFormat: 1;
|
||||
NegCurrFormat: 5;
|
||||
ThousandSeparator: ',';
|
||||
DecimalSeparator: '.';
|
||||
CurrencyDecimals: 2;
|
||||
DateSeparator: '-';
|
||||
TimeSeparator: ':';
|
||||
ListSeparator: ',';
|
||||
CurrencyString: '$';
|
||||
ShortDateFormat: '';
|
||||
LongDateFormat: '';
|
||||
TimeAMString: '';
|
||||
TimePMString: '';
|
||||
ShortTimeFormat: '';
|
||||
LongTimeFormat : '';
|
||||
ShortMonthNames:('','','','','','','','','','','','');
|
||||
LongMonthNames :('','','','','','','','','','','','');
|
||||
ShortDayNames :('','','','','','','');
|
||||
LongDayNames :('','','','','','','');
|
||||
TwoDigitYearCenturyWindow: 50;
|
||||
);
|
||||
|
||||
Function TsrLiteralConst.GetPrintData:RawByteString;
|
||||
begin
|
||||
Result:='';
|
||||
case dtype of
|
||||
dtUnknow :Result:='0x'+HexStr(Value,4);
|
||||
|
||||
dtBool :
|
||||
Case AsBool of
|
||||
true :Result:='true';
|
||||
false:Result:='false';
|
||||
end;
|
||||
|
||||
dtHalf16 : Result:=FloatToStr(Single(AsHalf16),DefaultFormatSettings);
|
||||
dtFloat32: Result:=FloatToStr( AsFloat32,DefaultFormatSettings);
|
||||
dtFloat64: Result:=FloatToStr( AsFloat64,DefaultFormatSettings);
|
||||
|
||||
dtInt8 : Result:=IntToStr(AsInt8);
|
||||
dtUint8 : Result:=IntToStr(AsUint8);
|
||||
|
||||
dtInt16 : Result:=IntToStr(AsInt16);
|
||||
dtUint16 : Result:=IntToStr(AsUint16);
|
||||
|
||||
dtInt32 : Result:=IntToStr(AsInt32);
|
||||
dtUint32 : Result:=IntToStr(AsUint32);
|
||||
|
||||
dtInt64 : Result:=IntToStr(AsInt64);
|
||||
dtUint64 : Result:=IntToStr(AsUint64);
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrLiteralConst.GetData(data:Pointer):Ptruint;
|
||||
begin
|
||||
Result:=0;
|
||||
Case dtype.BitSize of
|
||||
8:begin
|
||||
Result:=SizeOf(BYTE);
|
||||
if (data<>nil) then
|
||||
begin
|
||||
PBYTE(data)^:=BYTE(Value);
|
||||
end;
|
||||
end;
|
||||
16:begin
|
||||
Result:=SizeOf(WORD);
|
||||
if (data<>nil) then
|
||||
begin
|
||||
PWORD(data)^:=WORD(Value);
|
||||
end;
|
||||
end;
|
||||
32:begin
|
||||
Result:=SizeOf(DWORD);
|
||||
if (data<>nil) then
|
||||
begin
|
||||
PDWORD(data)^:=DWORD(Value);
|
||||
end;
|
||||
end;
|
||||
64:begin
|
||||
Result:=SizeOf(QWORD);
|
||||
if (data<>nil) then
|
||||
begin
|
||||
PQWORD(data)^:=Value;
|
||||
end;
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
Procedure TsrLiteralList.Init(Emit:TCustomEmit);
|
||||
begin
|
||||
FEmit:=Emit;
|
||||
end;
|
||||
|
||||
function TsrLiteralList.FetchLiteral(Value:PtrUint;name:PChar):PsrLiteral;
|
||||
var
|
||||
node:TsrLiteral;
|
||||
size:ptrint;
|
||||
begin
|
||||
node:=Default(TsrLiteral);
|
||||
node.Init;
|
||||
node.dtype:=dtUint32;
|
||||
node.Value:=Value;
|
||||
node.name :=name;
|
||||
|
||||
Result:=FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=FEmit.Alloc(SizeOf(TsrLiteral));
|
||||
Move(node,Result^,SizeOf(TsrLiteral));
|
||||
|
||||
if (name<>nil) then
|
||||
begin
|
||||
size:=StrLen(name)+1;
|
||||
Result^.name:=FEmit.Alloc(size);
|
||||
Move(name^,Result^.name^,size);
|
||||
end;
|
||||
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrLiteralList.FetchString(name:PChar):PsrLiteralString;
|
||||
var
|
||||
node:TsrLiteralString;
|
||||
size_o:ptrint;
|
||||
size_a:ptrint;
|
||||
begin
|
||||
node:=Default(TsrLiteralString);
|
||||
node.Init;
|
||||
node.dtype:=dtString;
|
||||
node.name:=name;
|
||||
|
||||
Result:=Pointer(FNTree.Find(Pointer(@node)));
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=FEmit.Alloc(SizeOf(TsrLiteralString));
|
||||
Move(node,Result^,SizeOf(TsrLiteralString));
|
||||
|
||||
if (name<>nil) then
|
||||
begin
|
||||
size_o:=StrLen(name);
|
||||
size_a:=Align(size_o+1,SizeOf(DWORD)); //align DW
|
||||
|
||||
Result^.name:=FEmit.Alloc(size_a);
|
||||
Move(name^,Result^.name^,size_o);
|
||||
end else
|
||||
begin
|
||||
Result^.name:=FEmit.Alloc(SizeOf(DWORD));
|
||||
//space DW
|
||||
end;
|
||||
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrLiteralList.FetchConst(dtype:TsrDataType;Value:PtrUint):PsrLiteralConst;
|
||||
var
|
||||
node:TsrLiteralConst;
|
||||
begin
|
||||
node:=Default(TsrLiteralConst);
|
||||
node.Init;
|
||||
node.dtype:=dtype;
|
||||
node.Value:=Value;
|
||||
|
||||
Result:=Pointer(FNTree.Find(Pointer(@node)));
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=FEmit.Alloc(SizeOf(TsrLiteralConst));
|
||||
Move(node,Result^,SizeOf(TsrLiteralConst));
|
||||
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
|
@ -0,0 +1,548 @@
|
|||
unit srNode;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
PsrNode=^TsrNode;
|
||||
PPsrNode=^PsrNode;
|
||||
|
||||
PPrepTypeNode=^TPrepTypeNode;
|
||||
TPrepTypeNode=record
|
||||
dnode:PsrNode;
|
||||
rtype:Integer;
|
||||
end;
|
||||
|
||||
TsrNodeVmt=class
|
||||
class Procedure add_read (node,src:PsrNode); virtual;
|
||||
class Procedure rem_read (node,src:PsrNode); virtual;
|
||||
//
|
||||
class Procedure add_write (node,src:PsrNode); virtual;
|
||||
class Procedure rem_write (node,src:PsrNode); virtual;
|
||||
//
|
||||
class Procedure mark_read (node,src:PsrNode); virtual;
|
||||
class Procedure mark_unread (node,src:PsrNode); virtual;
|
||||
//
|
||||
class Procedure zero_read (node:PsrNode); virtual;
|
||||
class Procedure zero_unread (node:PsrNode); virtual;
|
||||
//
|
||||
class Procedure mark_write (node,src:PsrNode); virtual;
|
||||
class Procedure mark_unwrite(node,src:PsrNode); virtual;
|
||||
//
|
||||
class Function pwrite_count(node:PsrNode):PDWORD virtual;
|
||||
class Procedure SetWriter(node,w,line:PsrNode); virtual;
|
||||
class Procedure ResetWriter(node,w:PsrNode); virtual;
|
||||
class Function is_used(node:PsrNode):Boolean virtual;
|
||||
class Function GetPtype(node:PsrNode):PsrNode; virtual;
|
||||
class Function GetStorageClass(node:PsrNode):DWORD; virtual;
|
||||
class function GetStorageName(node:PsrNode):RawByteString; virtual;
|
||||
class function GetPrintName(node:PsrNode):RawByteString; virtual;
|
||||
class function GetPrintData(node:PsrNode):RawByteString; virtual;
|
||||
class function Down(node:PsrNode):Pointer; virtual;
|
||||
class function Next(node:PsrNode):Pointer; virtual;
|
||||
class function Prev(node:PsrNode):Pointer; virtual;
|
||||
class function Parent(node:PsrNode):Pointer; virtual;
|
||||
class function First(node:PsrNode):Pointer; virtual;
|
||||
class function Last(node:PsrNode):Pointer; virtual;
|
||||
class Procedure PrepType(node:PPrepTypeNode); virtual;
|
||||
//
|
||||
class function GetIndexCount(node:PsrNode):DWORD; virtual;
|
||||
//
|
||||
class function GetRef(node:PsrNode):Pointer; virtual;
|
||||
//
|
||||
class function GetData(node:PsrNode;data:Pointer):Ptruint; virtual;
|
||||
end;
|
||||
|
||||
TsrNodeType=class of TsrNodeVmt;
|
||||
|
||||
TsrNode=packed object
|
||||
protected
|
||||
fntype:TsrNodeType;
|
||||
private
|
||||
fread_count:DWORD;
|
||||
public
|
||||
property ntype:TsrNodeType read fntype;
|
||||
property read_count:DWORD read fread_count;
|
||||
function IsType(t:TsrNodeType):Boolean;
|
||||
function AsType(t:TsrNodeType):Pointer;
|
||||
Procedure mark_read (src:PsrNode);
|
||||
Procedure mark_unread (src:PsrNode);
|
||||
Procedure mark_write (src:PsrNode);
|
||||
Procedure mark_unwrite(src:PsrNode);
|
||||
function write_count:DWORD;
|
||||
Procedure SetWriter(w,line:PsrNode);
|
||||
Procedure ResetWriter(w:PsrNode);
|
||||
function IsUsed:Boolean;
|
||||
Function pType:Pointer;
|
||||
Function GetStorageClass:DWORD;
|
||||
function GetStorageName:RawByteString;
|
||||
function GetPrintName:RawByteString;
|
||||
function GetPrintData:RawByteString;
|
||||
function Next:Pointer;
|
||||
function Prev:Pointer;
|
||||
function Parent:Pointer;
|
||||
function First:Pointer;
|
||||
function Last:Pointer;
|
||||
procedure PrepType(rtype:Integer);
|
||||
function GetIndexCount:DWORD;
|
||||
function GetRef:Pointer;
|
||||
function GetData(data:Pointer):Ptruint;
|
||||
end;
|
||||
|
||||
TCustomEmit=class
|
||||
Function Alloc(Size:ptruint):Pointer; virtual abstract;
|
||||
Function GetConfig :Pointer; virtual abstract;
|
||||
Function GetCodeHeap :Pointer; virtual abstract;
|
||||
Function GetLiteralList :Pointer; virtual abstract;
|
||||
Function GetTypeList :Pointer; virtual abstract;
|
||||
Function GetConstList :Pointer; virtual abstract;
|
||||
Function GetRegsStory :Pointer; virtual abstract;
|
||||
Function GetCapabilityList :Pointer; virtual abstract;
|
||||
Function GetHeaderList :Pointer; virtual abstract;
|
||||
Function GetDecorateList :Pointer; virtual abstract;
|
||||
Function GetDebugInfoList :Pointer; virtual abstract;
|
||||
Function GetVariableList :Pointer; virtual abstract;
|
||||
Function GetInputList :Pointer; virtual abstract;
|
||||
Function GetOutputList :Pointer; virtual abstract;
|
||||
Function GetDataLayoutList :Pointer; virtual abstract;
|
||||
Function GetVertLayoutList :Pointer; virtual abstract;
|
||||
Function GetFragLayoutList :Pointer; virtual abstract;
|
||||
Function GetBufferList :Pointer; virtual abstract;
|
||||
Function GetUniformList :Pointer; virtual abstract;
|
||||
Function GetBitcastList :Pointer; virtual abstract;
|
||||
Function GetCacheOpList :Pointer; virtual abstract;
|
||||
Function GetFuncList :Pointer; virtual abstract;
|
||||
Function GetCursor :Pointer; virtual abstract;
|
||||
function curr_line :Pointer; virtual abstract;
|
||||
function init_line :Pointer; virtual abstract;
|
||||
function NewRefNode :PsrNode; virtual abstract;
|
||||
function OpCast (pLine, dst,src:PsrNode):PsrNode; virtual abstract;
|
||||
function OpLoad (pLine,dtype,dst,src:PsrNode):PsrNode; virtual abstract;
|
||||
function OpStore (pLine, dst,src:PsrNode):PsrNode; virtual abstract;
|
||||
procedure PostLink(pLine, dst:PsrNode); virtual abstract;
|
||||
procedure emit_spi; virtual abstract;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
class Procedure TsrNodeVmt.add_read(node,src:PsrNode);
|
||||
begin
|
||||
Inc(node^.fread_count);
|
||||
end;
|
||||
|
||||
class Procedure TsrNodeVmt.rem_read(node,src:PsrNode);
|
||||
begin
|
||||
Assert(node^.fread_count<>0);
|
||||
if (node^.fread_count=0) then Exit;
|
||||
Dec(node^.fread_count);
|
||||
end;
|
||||
|
||||
class Procedure TsrNodeVmt.add_write(node,src:PsrNode);
|
||||
var
|
||||
p:PDWORD;
|
||||
begin
|
||||
p:=node^.fntype.pwrite_count(node);
|
||||
if (p<>nil) then
|
||||
begin
|
||||
Inc(p^);
|
||||
end;
|
||||
end;
|
||||
|
||||
class Procedure TsrNodeVmt.rem_write(node,src:PsrNode);
|
||||
var
|
||||
p:PDWORD;
|
||||
begin
|
||||
p:=node^.fntype.pwrite_count(node);
|
||||
if (p<>nil) then
|
||||
begin
|
||||
Assert(p^<>0);
|
||||
if (p^=0) then Exit;
|
||||
Dec(p^);
|
||||
end;
|
||||
end;
|
||||
|
||||
class Procedure TsrNodeVmt.mark_read(node,src:PsrNode);
|
||||
var
|
||||
prv:Boolean;
|
||||
begin
|
||||
repeat
|
||||
Assert(node^.fntype<>nil);
|
||||
|
||||
prv:=node^.IsUsed;
|
||||
|
||||
node^.fntype.add_read(node,src);
|
||||
|
||||
if (prv=node^.IsUsed) then Exit;
|
||||
|
||||
node^.fntype.zero_read(node);
|
||||
|
||||
src :=node;
|
||||
node:=node^.fntype.Down(node);
|
||||
until (node=nil);
|
||||
end;
|
||||
|
||||
class Procedure TsrNodeVmt.mark_unread(node,src:PsrNode);
|
||||
var
|
||||
prv:Boolean;
|
||||
begin
|
||||
repeat
|
||||
Assert(node^.fntype<>nil);
|
||||
|
||||
prv:=node^.IsUsed;
|
||||
|
||||
node^.fntype.rem_read(node,src);
|
||||
|
||||
if (prv=node^.IsUsed) then Exit;
|
||||
|
||||
node^.fntype.zero_unread(node);
|
||||
|
||||
src :=node;
|
||||
node:=node^.fntype.Down(node);
|
||||
until (node=nil);
|
||||
end;
|
||||
|
||||
class Procedure TsrNodeVmt.zero_read(node:PsrNode);
|
||||
begin
|
||||
//
|
||||
end;
|
||||
|
||||
class Procedure TsrNodeVmt.zero_unread(node:PsrNode);
|
||||
begin
|
||||
//
|
||||
end;
|
||||
|
||||
class Procedure TsrNodeVmt.mark_write(node,src:PsrNode);
|
||||
var
|
||||
prv:Boolean;
|
||||
begin
|
||||
repeat
|
||||
Assert(node^.fntype<>nil);
|
||||
|
||||
prv:=node^.IsUsed;
|
||||
|
||||
node^.fntype.add_write(node,src);
|
||||
|
||||
if (prv=node^.IsUsed) then Exit;
|
||||
|
||||
node^.fntype.zero_read(node);
|
||||
|
||||
src :=node;
|
||||
node:=node^.fntype.Down(node);
|
||||
until (node=nil);
|
||||
end;
|
||||
|
||||
class Procedure TsrNodeVmt.mark_unwrite(node,src:PsrNode);
|
||||
var
|
||||
prv:Boolean;
|
||||
begin
|
||||
repeat
|
||||
Assert(node^.fntype<>nil);
|
||||
|
||||
prv:=node^.IsUsed;
|
||||
|
||||
node^.fntype.rem_write(node,src);
|
||||
|
||||
if (prv=node^.IsUsed) then Exit;
|
||||
|
||||
node^.fntype.zero_unread(node);
|
||||
|
||||
src :=node;
|
||||
node:=node^.fntype.Down(node);
|
||||
until (node=nil);
|
||||
end;
|
||||
|
||||
class Function TsrNodeVmt.pwrite_count(node:PsrNode):PDWORD;
|
||||
begin
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
class Procedure TsrNodeVmt.SetWriter(node,w,line:PsrNode);
|
||||
begin
|
||||
w^.mark_read(node);
|
||||
end;
|
||||
|
||||
class Procedure TsrNodeVmt.ResetWriter(node,w:PsrNode);
|
||||
begin
|
||||
w^.mark_unread(node);
|
||||
end;
|
||||
|
||||
class Function TsrNodeVmt.is_used(node:PsrNode):Boolean;
|
||||
begin
|
||||
Result:=(node^.read_count<>0) or (node^.write_count<>0);
|
||||
end;
|
||||
|
||||
class Function TsrNodeVmt.GetPtype(node:PsrNode):PsrNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
class Function TsrNodeVmt.GetStorageClass(node:PsrNode):DWORD;
|
||||
begin
|
||||
Result:=6;
|
||||
end;
|
||||
|
||||
class function TsrNodeVmt.GetStorageName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:='';
|
||||
end;
|
||||
|
||||
class function TsrNodeVmt.GetPrintName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:='';
|
||||
end;
|
||||
|
||||
class function TsrNodeVmt.GetPrintData(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:='';
|
||||
end;
|
||||
|
||||
class function TsrNodeVmt.Down(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
class function TsrNodeVmt.Next(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
class function TsrNodeVmt.Prev(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
class function TsrNodeVmt.Parent(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
class function TsrNodeVmt.First(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
class function TsrNodeVmt.Last(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
class Procedure TsrNodeVmt.PrepType(node:PPrepTypeNode);
|
||||
begin
|
||||
node^.dnode:=nil;
|
||||
end;
|
||||
|
||||
class function TsrNodeVmt.GetIndexCount(node:PsrNode):DWORD;
|
||||
begin
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
class function TsrNodeVmt.GetRef(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
end;
|
||||
|
||||
class function TsrNodeVmt.GetData(node:PsrNode;data:Pointer):Ptruint;
|
||||
begin
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TsrNode.IsType(t:TsrNodeType):Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
if (@Self=nil) then Exit;
|
||||
Result:=fntype.InheritsFrom(t);
|
||||
end;
|
||||
|
||||
function TsrNode.AsType(t:TsrNodeType):Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if not fntype.InheritsFrom(t) then Exit;
|
||||
Result:=@Self;
|
||||
end;
|
||||
|
||||
Procedure TsrNode.mark_read(src:PsrNode);
|
||||
begin
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
fntype.mark_read(@Self,src);
|
||||
end;
|
||||
|
||||
Procedure TsrNode.mark_unread(src:PsrNode);
|
||||
begin
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
fntype.mark_unread(@Self,src);
|
||||
end;
|
||||
|
||||
Procedure TsrNode.mark_write(src:PsrNode);
|
||||
begin
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
fntype.mark_write(@Self,src);
|
||||
end;
|
||||
|
||||
Procedure TsrNode.mark_unwrite(src:PsrNode);
|
||||
begin
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
fntype.mark_unwrite(@Self,src);
|
||||
end;
|
||||
|
||||
function TsrNode.write_count:DWORD;
|
||||
var
|
||||
p:PDWORD;
|
||||
begin
|
||||
Result:=0;
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
p:=fntype.pwrite_count(@Self);
|
||||
if (p=nil) then Exit;
|
||||
Result:=p^;
|
||||
end;
|
||||
|
||||
Procedure TsrNode.SetWriter(w,line:PsrNode);
|
||||
begin
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
fntype.SetWriter(@Self,w,line);
|
||||
end;
|
||||
|
||||
Procedure TsrNode.ResetWriter(w:PsrNode);
|
||||
begin
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
fntype.ResetWriter(@Self,w);
|
||||
end;
|
||||
|
||||
function TsrNode.IsUsed:Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.is_used(@Self);
|
||||
end;
|
||||
|
||||
Function TsrNode.pType:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.GetPtype(@Self);
|
||||
end;
|
||||
|
||||
Function TsrNode.GetStorageClass:DWORD;
|
||||
begin
|
||||
Result:=6;
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.GetStorageClass(@Self);
|
||||
end;
|
||||
|
||||
function TsrNode.GetStorageName:RawByteString;
|
||||
begin
|
||||
Result:='';
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.GetStorageName(@Self);
|
||||
end;
|
||||
|
||||
function TsrNode.GetPrintName:RawByteString;
|
||||
begin
|
||||
Result:='';
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.GetPrintName(@Self);
|
||||
end;
|
||||
|
||||
function TsrNode.GetPrintData:RawByteString;
|
||||
begin
|
||||
Result:='';
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.GetPrintData(@Self);
|
||||
end;
|
||||
|
||||
function TsrNode.Next:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.Next(@Self);
|
||||
end;
|
||||
|
||||
function TsrNode.Prev:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.Prev(@Self);
|
||||
end;
|
||||
|
||||
function TsrNode.Parent:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.Parent(@Self);
|
||||
end;
|
||||
|
||||
function TsrNode.First:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.First(@Self);
|
||||
end;
|
||||
|
||||
function TsrNode.Last:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.Last(@Self);
|
||||
end;
|
||||
|
||||
procedure TsrNode.PrepType(rtype:Integer);
|
||||
var
|
||||
node:TPrepTypeNode;
|
||||
begin
|
||||
node:=Default(TPrepTypeNode);
|
||||
node.dnode:=@Self;
|
||||
node.rtype:=rtype;
|
||||
While (node.dnode<>nil) do
|
||||
begin
|
||||
Assert(node.dnode^.fntype<>nil);
|
||||
node.dnode^.fntype.PrepType(@node);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrNode.GetIndexCount:DWORD;
|
||||
begin
|
||||
Result:=0;
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.GetIndexCount(@Self);
|
||||
end;
|
||||
|
||||
function TsrNode.GetRef:Pointer;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.GetRef(@Self);
|
||||
end;
|
||||
|
||||
function TsrNode.GetData(data:Pointer):Ptruint;
|
||||
begin
|
||||
Result:=0;
|
||||
if (@Self=nil) then Exit;
|
||||
Assert(fntype<>nil);
|
||||
Result:=fntype.GetData(@Self,data);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
859
spirv/srOp.pas
859
spirv/srOp.pas
File diff suppressed because it is too large
Load Diff
|
@ -1,228 +1,241 @@
|
|||
unit srOpUtils;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$MODESWITCH ADVANCEDRECORDS}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
spirv,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srNode,
|
||||
srOp,
|
||||
srReg,
|
||||
srConst,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srOp;
|
||||
srVariable;
|
||||
|
||||
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
|
||||
OpIAddExt=DWORD(-1);
|
||||
OpISubExt=DWORD(-2);
|
||||
OpAbsDiff=DWORD(-3);
|
||||
OpWQM32 =DWORD(-4);
|
||||
|
||||
OpCUBEID =DWORD(-10);
|
||||
OpCUBESC =DWORD(-11);
|
||||
OpCUBETC =DWORD(-12);
|
||||
OpCUBEMA =DWORD(-13);
|
||||
OpBFEU32 =DWORD(-5);
|
||||
OpBFIB32 =DWORD(-6);
|
||||
|
||||
OpMakeCM =DWORD(-14);
|
||||
OpPackAnc=DWORD(-7);
|
||||
OpPackOfs=DWORD(-8);
|
||||
OpMakeExp=DWORD(-9);
|
||||
OpMakeVec=DWORD(-10);
|
||||
OpMakeCub=DWORD(-11);
|
||||
|
||||
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;
|
||||
OpCUBEID =DWORD(-12);
|
||||
OpCUBESC =DWORD(-13);
|
||||
OpCUBETC =DWORD(-14);
|
||||
OpCUBEMA =DWORD(-15);
|
||||
|
||||
function InsSpirvOp(pLine,pNew:PspirvOp):PSpirvOp;
|
||||
Procedure MarkUnreadParamSingle(const node:TOpParamSingle);
|
||||
function InsSpirvOp(pLine,pNew:PspirvOp):PspirvOp;
|
||||
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);
|
||||
procedure up_merge_line(var pLine:PspirvOp);
|
||||
function FindUpSameOp(pLine,node:PspirvOp):PspirvOp;
|
||||
|
||||
function isGTLine(p1,p2:PspirvOp):Boolean; //(p1>p2)
|
||||
function IsGTFlow(pSrc,pDst:PSpirvOp):Boolean;
|
||||
function GetGlobalIndex(pLine:PspirvOp):DWORD;
|
||||
function MaxLine(p1,p2:PspirvOp):PspirvOp;
|
||||
function GetMaxPlace(pLine:PSpirvOp;count:Byte;src:PPsrRegNode):PSpirvOp;
|
||||
|
||||
function GetChainRegNode(node:PsrRegNode):PsrChain;
|
||||
function GetSourceRegNode(node:PsrRegNode):PsrNode;
|
||||
|
||||
function flow_down_next_up(pLine:PspirvOp):PspirvOp;
|
||||
function flow_down_prev_up(pLine:PspirvOp):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;
|
||||
function flow_down_next_up(pLine:PspirvOp):PspirvOp;
|
||||
begin
|
||||
Result:=pLine^.First;
|
||||
if (Result=nil) then
|
||||
begin
|
||||
repeat
|
||||
Result:=pLine^.Next;
|
||||
pLine:=pLine^.Parent;
|
||||
until (pLine=nil) or (Result<>nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
function flow_down_prev_up(pLine:PspirvOp):PspirvOp;
|
||||
begin
|
||||
Result:=pLine^.Last;
|
||||
if (Result=nil) then
|
||||
begin
|
||||
repeat
|
||||
Result:=pLine^.Prev;
|
||||
pLine:=pLine^.Parent;
|
||||
until (pLine=nil) or (Result<>nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
function flow_prev_up(pLine:PspirvOp):PspirvOp;
|
||||
begin
|
||||
repeat
|
||||
Result:=pLine^.Prev;
|
||||
pLine:=pLine^.Parent;
|
||||
until (pLine=nil) or (Result<>nil);
|
||||
end;
|
||||
|
||||
function InsSpirvOp(pLine,pNew:PspirvOp):PspirvOp;
|
||||
var
|
||||
tmp:PspirvOp;
|
||||
begin
|
||||
Result:=nil;
|
||||
Assert(pLine<>nil);
|
||||
if (pLine=nil) or (pNew=nil) then Exit;
|
||||
|
||||
if (pLine^.pNext<>nil) then
|
||||
if (pLine^.Next<>nil) then
|
||||
if pNew^.IsType(ntOp) then
|
||||
begin
|
||||
pNew^.adr:=pLine^.adr;
|
||||
tmp:=pLine;
|
||||
while (not tmp^.IsType(ntOp)) do
|
||||
begin
|
||||
tmp:=flow_down_prev_up(tmp);
|
||||
Assert(tmp<>nil);
|
||||
end;
|
||||
pNew^.Adr:=tmp^.Adr;
|
||||
end;
|
||||
|
||||
pLine^.InsertAfter(pNew);
|
||||
Result:=pNew;
|
||||
end;
|
||||
|
||||
Procedure MarkUnreadParamSingle(const node:TOpParamSingle);
|
||||
function GetCurrentIndex(pLine:PspirvOp):DWORD;
|
||||
var
|
||||
pParent:PsrOpBlock;
|
||||
node:PspirvOp;
|
||||
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);
|
||||
Result:=0;
|
||||
if (pLine=nil) then Exit;
|
||||
pParent:=pLine^.Parent;
|
||||
if (pParent=nil) then Exit;
|
||||
node:=pParent^.First;
|
||||
While (node<>nil) and (node<>pLine) do
|
||||
begin
|
||||
Result:=Result+node^.GetIndexCount;
|
||||
node:=node^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetGlobalIndex(pLine:PspirvOp):DWORD;
|
||||
var
|
||||
pParent:PsrOpBlock;
|
||||
node:PspirvOp;
|
||||
begin
|
||||
Result:=0;
|
||||
if (pLine=nil) then Exit;
|
||||
node:=pLine;
|
||||
pParent:=node^.Parent;
|
||||
While (pParent<>nil) do
|
||||
begin
|
||||
Result:=Result+GetCurrentIndex(node);
|
||||
node:=PspirvOp(pParent);
|
||||
pParent:=node^.Parent;
|
||||
end;
|
||||
end;
|
||||
|
||||
function isGTLine(p1,p2:PspirvOp):Boolean; //(p1>p2)
|
||||
begin
|
||||
Result:=False;
|
||||
p2:=p2^.pNext;
|
||||
p2:=p2^.Next;
|
||||
While (p2<>nil) do
|
||||
begin
|
||||
if (p1=p2) then Exit(True);
|
||||
p2:=p2^.pNext;
|
||||
p2:=p2^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
function isGTELine(p1,p2:PspirvOp):Boolean; //(p1>=p2)
|
||||
Function IsGTLevel(p1,p2:PspirvOp):Boolean; //(p1>p2)
|
||||
var
|
||||
pParent1:PsrOpBlock;
|
||||
pParent2:PsrOpBlock;
|
||||
begin
|
||||
Result:=False;
|
||||
While (p2<>nil) do
|
||||
pParent1:=p1^.Parent;
|
||||
pParent2:=p2^.Parent;
|
||||
Result:=(pParent1^.Level>pParent2^.Level);
|
||||
end;
|
||||
|
||||
function MaxLine(p1,p2:PspirvOp):PspirvOp;
|
||||
var
|
||||
pParent:PsrOpBlock;
|
||||
node:PspirvOp;
|
||||
i,w:DWORD;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (p1=nil) then Exit(p2);
|
||||
if (p2=nil) or (p1=p2) then Exit(p1);
|
||||
|
||||
if IsGTLevel(p2,p1) then //(p2>p1)
|
||||
begin
|
||||
if (p1=p2) then Exit(True);
|
||||
p2:=p2^.pNext;
|
||||
//swap
|
||||
node:=p1;
|
||||
p1:=p2;
|
||||
p2:=node;
|
||||
end;
|
||||
|
||||
i:=0;
|
||||
node:=p1;
|
||||
pParent:=node^.Parent;
|
||||
While (pParent<>nil) do
|
||||
begin
|
||||
if (pParent=p2^.Parent) then
|
||||
begin
|
||||
if isGTLine(node,p2) then //(node>p2)
|
||||
begin
|
||||
//Assert(not isGTLine(p2,node));
|
||||
Exit(p1);
|
||||
end else
|
||||
begin
|
||||
//Assert(isGTLine(p2,node));
|
||||
Exit(p2);
|
||||
end;
|
||||
end;
|
||||
i:=i+GetCurrentIndex(node);
|
||||
node:=PspirvOp(pParent);
|
||||
pParent:=node^.Parent;
|
||||
end;
|
||||
|
||||
w:=GetGlobalIndex(p2);
|
||||
if (i>w) then
|
||||
begin
|
||||
Result:=p1;
|
||||
end else
|
||||
begin
|
||||
Result:=p2;
|
||||
end;
|
||||
end;
|
||||
|
||||
Function IsParentOf(pLine,pCurr:PsrOpBlock):Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
if not pLine^.IsType(ntOpBlock) then Exit;
|
||||
if not pCurr^.IsType(ntOpBlock) then Exit;
|
||||
While (pLine<>nil) do
|
||||
begin
|
||||
if (pLine=pCurr) then Exit(True);
|
||||
pLine:=pLine^.pParent;
|
||||
pLine:=pLine^.Parent;
|
||||
end;
|
||||
end;
|
||||
|
||||
function FindBlockLine(pCurent,node:PsrOpBlock):PspirvOp;
|
||||
var
|
||||
tmp:PspirvOp;
|
||||
Function IsParentOfLine(pLine,pCurr:PSpirvOp):Boolean;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (pCurent=nil) then Exit;
|
||||
tmp:=pCurent^.pHead;
|
||||
While (tmp<>nil) do
|
||||
begin
|
||||
if (tmp^.OpId=OpBlock) and (tmp^.dst.pData=node) then
|
||||
begin
|
||||
Exit(tmp);
|
||||
end;
|
||||
tmp:=tmp^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
{
|
||||
[pSrc]
|
||||
|
|
||||
V
|
||||
[pBlock] -> [pDst]
|
||||
}
|
||||
|
||||
function IsGTFlow(pSrc,pDst:PSpirvOp):Boolean;
|
||||
var
|
||||
pLine,pCurr:PsrOpBlock;
|
||||
tmp:PSpirvOp;
|
||||
begin
|
||||
Result:=False;
|
||||
|
||||
pLine:=pDst^.pParent;
|
||||
pCurr:=pSrc^.pParent;
|
||||
|
||||
While (pLine<>nil) do
|
||||
begin
|
||||
|
||||
if (pLine=pCurr) then
|
||||
begin
|
||||
Result:=isGTELine(pSrc,pDst);
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if (pLine^.pParent=nil) then Exit;
|
||||
|
||||
tmp:=pLine^.pUpLine;
|
||||
if (tmp=nil) then
|
||||
begin
|
||||
tmp:=FindBlockLine(pLine^.pParent,pLine);
|
||||
end;
|
||||
pDst:=tmp;
|
||||
|
||||
pLine:=pDst^.pParent;
|
||||
end;
|
||||
Result:=IsParentOf(pLine^.Parent,pCurr^.Parent);
|
||||
end;
|
||||
|
||||
function GetMaxPlace(pLine:PSpirvOp;count:Byte;src:PPsrRegNode):PSpirvOp;
|
||||
var
|
||||
m,t:PSpirvOp;
|
||||
m:PSpirvOp;
|
||||
i:Byte;
|
||||
begin
|
||||
Result:=pLine;
|
||||
|
@ -230,25 +243,10 @@ begin
|
|||
m:=nil;
|
||||
For i:=0 to count-1 do
|
||||
begin
|
||||
t:=src[i]^.pLine;
|
||||
if not src[i]^.is_const then
|
||||
if IsParentOf(pLine^.pParent,t^.pParent) then
|
||||
if (not src[i]^.is_const) then
|
||||
if IsParentOfLine(pLine,src[i]^.pLine) then
|
||||
begin
|
||||
if (m=nil) then
|
||||
begin
|
||||
m:=t;
|
||||
end else
|
||||
if (m^.pParent=t^.pParent) then
|
||||
begin
|
||||
if isGTLine(t,m) then
|
||||
begin
|
||||
m:=t;
|
||||
end;
|
||||
end else
|
||||
if (t^.pParent^.FLevel>m^.pParent^.FLevel) then
|
||||
begin
|
||||
m:=t;
|
||||
end;
|
||||
m:=MaxLine(m,src[i]^.pLine);
|
||||
end;
|
||||
end;
|
||||
if (m<>nil) then
|
||||
|
@ -325,36 +323,57 @@ begin
|
|||
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;
|
||||
|
||||
if pLine^.IsType(ntOpBlock) then
|
||||
begin
|
||||
//
|
||||
end else
|
||||
if pLine^.IsType(ntOp) then
|
||||
begin
|
||||
if not pLine^.is_cleared then
|
||||
begin
|
||||
Case pLine^.OpId of
|
||||
Op.OpNop:; //
|
||||
else
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
Exit;
|
||||
end;
|
||||
if (pLine=nil) then Exit;
|
||||
|
||||
pLine:=flow_down_prev_up(pLine);
|
||||
|
||||
until false;
|
||||
|
||||
Result:=is_term_op(pLine^.OpId);
|
||||
end;
|
||||
|
||||
procedure _up_merge_line(var pLine:PspirvOp);
|
||||
procedure up_merge_line(var pLine:PspirvOp);
|
||||
var
|
||||
node:PspirvOp;
|
||||
begin
|
||||
repeat
|
||||
if is_merge_op(pLine^.OpId) then
|
||||
if pLine^.IsType(ntOp) then
|
||||
begin
|
||||
pLine:=pLine^.pPrev;
|
||||
Assert(pLine<>nil);
|
||||
end else
|
||||
begin
|
||||
Break;
|
||||
if pLine^.is_cleared or is_merge_op(pLine^.OpId) then
|
||||
begin
|
||||
node:=pLine^.Prev;
|
||||
if (node<>nil) then
|
||||
begin
|
||||
pLine:=node;
|
||||
Continue;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
Break;
|
||||
until false;
|
||||
end;
|
||||
|
||||
function CompareParam(p1,p2:POpParamNode):Boolean;
|
||||
begin
|
||||
Result:=(p1^.ntype=p2^.ntype) and (p1^.pData=p2^.pData);
|
||||
Result:=(p1^.Value=p2^.Value);
|
||||
end;
|
||||
|
||||
function CompareOp(p1,p2:PspirvOp):Boolean;
|
||||
|
@ -362,51 +381,68 @@ 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;
|
||||
if not p1^.IsType(ntOp) then Exit;
|
||||
if not p2^.IsType(ntOp) then Exit;
|
||||
|
||||
if (p1^.OpId<>p2^.OpId) then Exit;
|
||||
if (p1^.pDst<>p2^.pDst) then Exit;
|
||||
|
||||
n1:=p1^.ParamNode(0);
|
||||
n2:=p2^.ParamNode(0);
|
||||
|
||||
While (n1<>nil) do
|
||||
begin
|
||||
if (n2=nil) then Exit;
|
||||
if not CompareParam(n1,n2) then Exit;
|
||||
n1:=n1^.pNext;
|
||||
n2:=n2^.pNext;
|
||||
n1:=n1^.Next;
|
||||
n2:=n2^.Next;
|
||||
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
|
||||
if not pLine^.is_cleared then
|
||||
begin
|
||||
pBlock:=pLine^.pParent;
|
||||
if (pBlock=nil) then Exit;
|
||||
if (pBlock^.pParent=nil) then Exit;
|
||||
tmp:=pBlock^.pUpLine;
|
||||
if (tmp=nil) then
|
||||
begin
|
||||
tmp:=FindBlockLine(pBlock^.pParent,pBlock);
|
||||
end;
|
||||
tmp:=tmp^.pPrev;
|
||||
if CompareOp(pLine,node) then Exit(pLine);
|
||||
end;
|
||||
pLine:=tmp;
|
||||
pLine:=flow_prev_up(pLine);
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetChainRegNode(node:PsrRegNode):PsrChain;
|
||||
var
|
||||
pOp:PSpirvOp;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=RegDown(node);
|
||||
pOp:=node^.pWriter^.AsType(ntOp);
|
||||
if (pOp=nil) then Exit;
|
||||
if (pOp^.OpId<>Op.OpLoad) then Exit;
|
||||
Result:=pOp^.ParamNode(0)^.Value^.AsType(ntChain);
|
||||
end;
|
||||
|
||||
function GetSourceRegNode(node:PsrRegNode):PsrNode;
|
||||
var
|
||||
pOp:PSpirvOp;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
Result:=nil;
|
||||
node:=RegDown(node);
|
||||
pOp:=node^.pWriter^.AsType(ntOp);
|
||||
if (pOp=nil) then Exit;
|
||||
if (pOp^.OpId<>Op.OpLoad) then Exit;
|
||||
pVar:=pOp^.ParamNode(0)^.Value^.AsType(ntVariable);
|
||||
if (pVar=nil) then Exit;
|
||||
Result:=pVar^.pSource;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
|
|
@ -5,13 +5,14 @@ unit srOutput;
|
|||
interface
|
||||
|
||||
uses
|
||||
typinfo,
|
||||
spirv,
|
||||
srNodes,
|
||||
srOp,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srDecorate;
|
||||
typinfo,
|
||||
spirv,
|
||||
srNode,
|
||||
srType,
|
||||
srOp,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srDecorate;
|
||||
|
||||
type
|
||||
TpsslExportType=(
|
||||
|
@ -39,55 +40,83 @@ type
|
|||
etParam28,etParam29,etParam30,etParam31
|
||||
);
|
||||
|
||||
PsrOutput=^TsrOutput;
|
||||
TsrOutput=object(TsrDescriptor)
|
||||
etype:TpsslExportType;
|
||||
function GetName:RawByteString;
|
||||
ntOutput=class(ntDescriptor)
|
||||
class Function pwrite_count (node:PsrNode):PDWORD; override;
|
||||
class function GetStorageName(node:PsrNode):RawByteString; override;
|
||||
end;
|
||||
|
||||
PsrOutput=^TsrOutput;
|
||||
TsrOutput=object(TsrDescriptor)
|
||||
fwrite_count:DWORD;
|
||||
etype:TpsslExportType;
|
||||
function GetStorageName:RawByteString;
|
||||
end;
|
||||
|
||||
PsrOutputList=^TsrOutputList;
|
||||
TsrOutputList=object
|
||||
FEmit:TCustomEmit;
|
||||
data:array[TpsslExportType] of TsrOutput;
|
||||
Procedure Init;
|
||||
function Fetch(etype:TpsslExportType):PsrOutput;
|
||||
procedure AllocBinding(Decorates:PsrDecorateList);
|
||||
Procedure Init(Emit:TCustomEmit); inline;
|
||||
function Fetch(etype:TpsslExportType;rtype:TsrDataType):PsrOutput;
|
||||
procedure AllocBinding;
|
||||
procedure AllocEntryPoint(EntryPoint:PSpirvOp);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
function TsrOutput.GetName:RawByteString;
|
||||
class Function ntOutput.pwrite_count(node:PsrNode):PDWORD;
|
||||
begin
|
||||
Result:=@PsrOutput(node)^.fwrite_count;
|
||||
end;
|
||||
|
||||
class function ntOutput.GetStorageName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrOutput(node)^.GetStorageName;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TsrOutput.GetStorageName:RawByteString;
|
||||
begin
|
||||
Result:=GetEnumName(TypeInfo(TpsslExportType),ord(etype));
|
||||
end;
|
||||
|
||||
Procedure TsrOutputList.Init;
|
||||
Procedure TsrOutputList.Init(Emit:TCustomEmit); inline;
|
||||
var
|
||||
i:TpsslExportType;
|
||||
begin
|
||||
FEmit:=Emit;
|
||||
For i:=Low(TpsslExportType) to High(TpsslExportType) do
|
||||
begin
|
||||
data[i].etype:=i;
|
||||
data[i].fntype :=ntOutput;
|
||||
data[i].etype :=i;
|
||||
data[i].FStorage:=StorageClass.Output;
|
||||
data[i].FBinding:=-1;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrOutputList.Fetch(etype:TpsslExportType):PsrOutput;
|
||||
function TsrOutputList.Fetch(etype:TpsslExportType;rtype:TsrDataType):PsrOutput;
|
||||
begin
|
||||
Result:=@data[etype];
|
||||
//
|
||||
Result^.InitType(rtype,FEmit);
|
||||
Result^.InitVar(FEmit);
|
||||
end;
|
||||
|
||||
procedure TsrOutputList.AllocBinding(Decorates:PsrDecorateList);
|
||||
//
|
||||
|
||||
procedure TsrOutputList.AllocBinding;
|
||||
var
|
||||
pDecorateList:PsrDecorateList;
|
||||
i:TpsslExportType;
|
||||
pVar:PsrVariable;
|
||||
FLocation:Integer;
|
||||
begin
|
||||
if (Decorates=nil) then Exit;
|
||||
pDecorateList:=FEmit.GetDecorateList;
|
||||
For i:=Low(TpsslExportType) to High(TpsslExportType) do
|
||||
begin
|
||||
pVar:=data[i].pVar;
|
||||
if (pVar<>nil) then
|
||||
if (pVar<>nil) and data[i].IsUsed then
|
||||
begin
|
||||
Case i of
|
||||
etMrt0..etMrt7:
|
||||
|
@ -95,7 +124,7 @@ begin
|
|||
if (data[i].FBinding=-1) then //alloc
|
||||
begin
|
||||
FLocation:=ord(i)-ord(etMrt0);
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,FLocation);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.Location,FLocation);
|
||||
data[i].FBinding:=FLocation;
|
||||
end;
|
||||
//Decoration.Index; ???
|
||||
|
@ -103,13 +132,13 @@ begin
|
|||
//etMrtz,
|
||||
etPos0:
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.BuiltIn,BuiltIn.Position);
|
||||
pDecorateList^.OpDecorate(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);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.Location,FLocation);
|
||||
data[i].FBinding:=FLocation;
|
||||
end;
|
||||
else
|
||||
|
@ -129,9 +158,10 @@ begin
|
|||
For i:=Low(TpsslExportType) to High(TpsslExportType) do
|
||||
begin
|
||||
pVar:=data[i].pVar;
|
||||
if (pVar<>nil) then
|
||||
if (not data[i].IsUsed) and (pVar<>nil) then assert(false);
|
||||
if (pVar<>nil) and data[i].IsUsed then
|
||||
begin
|
||||
EntryPoint^.AddParam(ntVar,pVar);
|
||||
EntryPoint^.AddParam(pVar);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
|
|
@ -0,0 +1,873 @@
|
|||
unit srPrivate;
|
||||
|
||||
{$mode ObjFPC}{$H+}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
ginodes,
|
||||
srNode,
|
||||
srType,
|
||||
srTypes,
|
||||
srLayout,
|
||||
srOp,
|
||||
srOpUtils,
|
||||
srReg,
|
||||
srVariable,
|
||||
srBitcast;
|
||||
|
||||
type
|
||||
ntPrivate=class(ntDescriptor)
|
||||
class Function pwrite_count (node:PsrNode):PDWORD; override;
|
||||
class Procedure PrepType (node:PPrepTypeNode); override;
|
||||
class function GetStorageName(node:PsrNode):RawByteString; override;
|
||||
end;
|
||||
|
||||
ntVolatile=class(TsrNodeVmt)
|
||||
class Procedure zero_read (node:PsrNode); override;
|
||||
class Procedure zero_unread (node:PsrNode); override;
|
||||
class Procedure PrepType (node:PPrepTypeNode); override;
|
||||
end;
|
||||
|
||||
PsrPrivate=^TsrPrivate;
|
||||
|
||||
PsrVolatile=^TsrVolatile;
|
||||
TsrVolatile=object(TsrNode)
|
||||
type
|
||||
PVNode=^TVNode;
|
||||
TVNode=record
|
||||
pPrev,pNext:PVNode;
|
||||
pReg:PsrRegNode;
|
||||
end;
|
||||
TNodeList=specialize TNodeList<PVNode>;
|
||||
var
|
||||
pPrev,pNext:PsrVolatile;
|
||||
FSource:PsrPrivate;
|
||||
FList:TNodeList;
|
||||
Procedure Init(Source:PsrPrivate); inline;
|
||||
Procedure AddStore(src:PsrRegNode);
|
||||
Procedure PushStore(node:PVNode);
|
||||
Function PopStore:PVNode;
|
||||
Procedure RemoveAllStore;
|
||||
Procedure zero_read;
|
||||
Procedure zero_unread;
|
||||
procedure PrepType(new:TsrDataType);
|
||||
end;
|
||||
|
||||
TsrPrivate=object(TsrDescriptor)
|
||||
type
|
||||
PVNode=^TVNode;
|
||||
TVNode=record
|
||||
pPrev,pNext:PVNode;
|
||||
pLine:PspirvOp;
|
||||
end;
|
||||
TNodeList=specialize TNodeList<PVNode>;
|
||||
TVoltList=specialize TNodeList<PsrVolatile>;
|
||||
private
|
||||
pLeft,pRight:PsrPrivate;
|
||||
//----
|
||||
fwrite_count:DWORD;
|
||||
//
|
||||
FSource:PsrRegSlot;
|
||||
//
|
||||
FLineList:TNodeList;
|
||||
FVoltList:TVoltList;
|
||||
function c(n1,n2:PsrPrivate):Integer; static;
|
||||
Procedure SetRegType(rtype:TsrDataType);
|
||||
function GetRegType:TsrDataType;
|
||||
public
|
||||
//FVolatile:TsrVolatile;
|
||||
property dtype:TsrDataType read GetRegType write SetRegType;
|
||||
property Source:PsrRegSlot read FSource;
|
||||
Procedure Init; inline;
|
||||
function Emit:TCustomEmit;
|
||||
function GetStorageName:RawByteString;
|
||||
function isBoolOnly:Boolean;
|
||||
Procedure UpdateRegType;
|
||||
Procedure PrepType(new:TsrDataType);
|
||||
Procedure SortLines;
|
||||
Procedure Optimize;
|
||||
procedure AddLine(pLine:PspirvOp);
|
||||
procedure AddLine(pLine:PspirvOp;node:TsrVolatile.PVNode);
|
||||
procedure FetchLoad(pLine:PspirvOp;dst:PsrRegNode);
|
||||
Procedure FetchStore(pLine:PspirvOp;node:TsrVolatile.PVNode);
|
||||
function NewVolatile:PsrVolatile;
|
||||
procedure RemoveAllStore;
|
||||
end;
|
||||
|
||||
PsrPrivateList=^TsrPrivateList;
|
||||
TsrPrivateList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrPrivate,TsrPrivate>;
|
||||
var
|
||||
FEmit:TCustomEmit;
|
||||
FNTree:TNodeFetch;
|
||||
procedure Init(Emit:TCustomEmit); inline;
|
||||
function Fetch(pSource:PsrRegSlot):PsrPrivate;
|
||||
function First:PsrPrivate; inline;
|
||||
Function Next(node:PsrPrivate):PsrPrivate;
|
||||
//
|
||||
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);
|
||||
Procedure Post;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
class Procedure ntVolatile.zero_read(node:PsrNode);
|
||||
begin
|
||||
PsrVolatile(node)^.zero_read;
|
||||
end;
|
||||
|
||||
class Procedure ntVolatile.zero_unread(node:PsrNode);
|
||||
begin
|
||||
PsrVolatile(node)^.zero_unread;
|
||||
end;
|
||||
|
||||
class Procedure ntVolatile.PrepType(node:PPrepTypeNode);
|
||||
begin
|
||||
PsrVolatile(node^.dnode)^.PrepType(TsrDataType(node^.rtype));
|
||||
node^.dnode:=nil;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
Procedure TsrVolatile.Init(Source:PsrPrivate); inline;
|
||||
begin
|
||||
fntype :=ntVolatile;
|
||||
FSource:=Source;
|
||||
end;
|
||||
|
||||
procedure TsrVolatile.PrepType(new:TsrDataType);
|
||||
var
|
||||
node:PVNode;
|
||||
begin
|
||||
if FSource^.isBoolOnly then
|
||||
begin
|
||||
new:=dtBool;
|
||||
end;
|
||||
if (new=dtUnknow) then exit;
|
||||
|
||||
node:=FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
node^.pReg^.PrepType(ord(new));
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrVolatile.AddStore(src:PsrRegNode);
|
||||
var
|
||||
node:PVNode;
|
||||
begin
|
||||
if (src=nil) then Exit;
|
||||
node:=FSource^.Emit.Alloc(SizeOf(TVNode));
|
||||
node^.pReg:=src;
|
||||
if IsUsed then
|
||||
begin
|
||||
src^.mark_read(@Self);
|
||||
end;
|
||||
FList.Push_head(node);
|
||||
end;
|
||||
|
||||
Procedure TsrVolatile.PushStore(node:PVNode);
|
||||
begin
|
||||
if (node=nil) then Exit;
|
||||
if IsUsed then
|
||||
begin
|
||||
node^.pReg^.mark_read(@Self);
|
||||
end;
|
||||
FList.Push_head(node);
|
||||
end;
|
||||
|
||||
Function TsrVolatile.PopStore:PVNode;
|
||||
begin
|
||||
Result:=FList.Pop_head;
|
||||
if (Result<>nil) and IsUsed then
|
||||
begin
|
||||
Result^.pReg^.mark_unread(@Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrVolatile.RemoveAllStore;
|
||||
var
|
||||
node:PVNode;
|
||||
begin
|
||||
repeat
|
||||
node:=PopStore;
|
||||
until (node=nil);
|
||||
end;
|
||||
|
||||
Procedure TsrVolatile.zero_read;
|
||||
var
|
||||
node:PVNode;
|
||||
begin
|
||||
node:=FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
node^.pReg^.mark_read(@Self);
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrVolatile.zero_unread;
|
||||
var
|
||||
node:PVNode;
|
||||
begin
|
||||
node:=FList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
node^.pReg^.mark_unread(@Self);
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
class Function ntPrivate.pwrite_count(node:PsrNode):PDWORD;
|
||||
begin
|
||||
Result:=@PsrPrivate(node)^.fwrite_count;
|
||||
end;
|
||||
|
||||
class Procedure ntPrivate.PrepType(node:PPrepTypeNode);
|
||||
begin
|
||||
PsrPrivate(node^.dnode)^.PrepType(TsrDataType(node^.rtype));
|
||||
node^.dnode:=nil;
|
||||
end;
|
||||
|
||||
class function ntPrivate.GetStorageName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrPrivate(node)^.GetStorageName;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function TsrPrivate.c(n1,n2:PsrPrivate):Integer;
|
||||
begin
|
||||
Result:=Integer(n1^.FSource>n2^.FSource)-Integer(n1^.FSource<n2^.FSource);
|
||||
end;
|
||||
|
||||
Procedure TsrPrivate.Init; inline;
|
||||
begin
|
||||
fntype :=ntPrivate;
|
||||
FStorage:=StorageClass.Private_;
|
||||
FBinding:=-1;
|
||||
end;
|
||||
|
||||
function TsrPrivate.Emit:TCustomEmit;
|
||||
begin
|
||||
Result:=FSource^.FEmit;
|
||||
end;
|
||||
|
||||
function TsrPrivate.GetStorageName:RawByteString;
|
||||
begin
|
||||
Result:='v'+FSource^.rid;
|
||||
end;
|
||||
|
||||
function TsrPrivate.isBoolOnly:Boolean;
|
||||
begin
|
||||
Result:=(FSource^.isBoolOnly);
|
||||
end;
|
||||
|
||||
Procedure TsrPrivate.SetRegType(rtype:TsrDataType);
|
||||
var
|
||||
pTypeList:PsrTypeList;
|
||||
node:PVNode;
|
||||
pLine:PspirvOp;
|
||||
begin
|
||||
pTypeList:=Emit.GetTypeList;
|
||||
Ftype:=pTypeList^.Fetch(rtype);
|
||||
|
||||
node:=FLineList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pLine:=node^.pLine;
|
||||
|
||||
Case pLine^.OpId of
|
||||
|
||||
Op.OpLoad:
|
||||
begin
|
||||
pLine^.pDst^.PrepType(ord(rtype));
|
||||
pLine^.pType:=Ftype;
|
||||
end;
|
||||
|
||||
Op.OpStore:
|
||||
begin
|
||||
pLine^.ParamFirst^.Value^.PrepType(ord(rtype));
|
||||
end;
|
||||
|
||||
else;
|
||||
end;
|
||||
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrPrivate.GetRegType:TsrDataType;
|
||||
begin
|
||||
Result:=FType^.dtype;
|
||||
end;
|
||||
|
||||
Procedure TsrPrivate.UpdateRegType;
|
||||
var
|
||||
pBitcastList:PsrBitcastList;
|
||||
node:PVNode;
|
||||
pLine:PspirvOp;
|
||||
dst:PsrRegNode;
|
||||
old,rtype:TsrDataType;
|
||||
begin
|
||||
rtype:=FType^.dtype;
|
||||
|
||||
pBitcastList:=Emit.GetBitcastList;
|
||||
|
||||
node:=FLineList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pLine:=node^.pLine;
|
||||
|
||||
Case pLine^.OpId of
|
||||
|
||||
Op.OpLoad:
|
||||
begin
|
||||
pLine^.pDst^.PrepType(ord(rtype));
|
||||
pLine^.pType:=Ftype;
|
||||
|
||||
dst:=pLine^.pDst^.AsType(ntReg);
|
||||
if (dst<>nil) then
|
||||
begin
|
||||
old:=dst^.dtype;
|
||||
if (old<>dtUnknow) and (not CompareType(rtype,old)) then
|
||||
begin
|
||||
//OpLoad -> new -> dst
|
||||
pBitcastList:=Emit.GetBitcastList;
|
||||
dst:=pBitcastList^.FetchDstr(rtype,dst);
|
||||
pLine^.pDst:=dst;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
Op.OpStore:
|
||||
begin
|
||||
pLine^.ParamFirst^.Value^.PrepType(ord(rtype));
|
||||
|
||||
dst:=pLine^.ParamFirst^.Value^.AsType(ntReg);
|
||||
if (dst<>nil) then
|
||||
begin
|
||||
old:=dst^.dtype;
|
||||
if (old<>dtUnknow) and (rtype<>old) then
|
||||
begin
|
||||
//OpStore <- new <- dst
|
||||
pBitcastList:=Emit.GetBitcastList;
|
||||
dst:=pBitcastList^.FetchRead(rtype,dst);
|
||||
pLine^.ParamFirst^.Value:=dst;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
else;
|
||||
end;
|
||||
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrPrivate.PrepType(new:TsrDataType);
|
||||
var
|
||||
old:TsrDataType;
|
||||
begin
|
||||
if isBoolOnly then
|
||||
begin
|
||||
new:=dtBool;
|
||||
end;
|
||||
if (new=dtUnknow) then Exit;
|
||||
old:=GetRegType;
|
||||
if is_unprep_type(old,new,True) then
|
||||
begin
|
||||
SetRegType(new);
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrPrivate.SortLines;
|
||||
var
|
||||
pnode,pnext:PVNode;
|
||||
pLine:array[0..1] of PspirvOp;
|
||||
nswp:Boolean;
|
||||
begin
|
||||
repeat
|
||||
nswp:=True;
|
||||
pnode:=FLineList.pHead;
|
||||
While true do
|
||||
begin
|
||||
pnext:=pnode^.pNext;
|
||||
if (pnext=nil) then Break;
|
||||
|
||||
pLine[0]:=pnode^.pLine;
|
||||
pLine[1]:=pnext^.pLine;
|
||||
|
||||
if (MaxLine(pLine[0],pLine[1])=pLine[0]) then //pnode>pnext
|
||||
begin
|
||||
//swap
|
||||
nswp:=False;
|
||||
FLineList.Remove(pnode);
|
||||
FLineList.InsertAfter(pnext,pnode);
|
||||
end else
|
||||
begin
|
||||
pnode:=pnext;
|
||||
end;
|
||||
|
||||
end;
|
||||
until nswp;
|
||||
end;
|
||||
|
||||
Procedure TsrPrivate.Optimize;
|
||||
var
|
||||
pnode,pprev:PVNode;
|
||||
pLine:array[0..1] of PspirvOp;
|
||||
begin
|
||||
pnode:=FLineList.pTail;
|
||||
While true do
|
||||
begin
|
||||
pprev:=pnode^.pPrev;
|
||||
if (pprev=nil) then Break;
|
||||
|
||||
pLine[0]:=pnode^.pLine;
|
||||
pLine[1]:=pprev^.pLine;
|
||||
|
||||
if (pLine[0]^.Parent=pLine[1]^.Parent) then
|
||||
begin
|
||||
//OpStore %v %r
|
||||
//OpStore %v %r
|
||||
if (pLine[0]^.OpId=Op.OpStore) and (pLine[1]^.OpId=Op.OpStore) then
|
||||
begin
|
||||
//Remove pprev
|
||||
FLineList.Remove(pprev);
|
||||
pLine[1]^.mark_not_used;
|
||||
Continue;
|
||||
end else
|
||||
if (pLine[0]^.OpId=Op.OpStore) and (pLine[1]^.OpId=Op.OpLoad) then
|
||||
begin
|
||||
//%r = OpLoad %type %v ; pLine[1] ; pprev
|
||||
//OpStore %v %r ; pLine[0] ; pnode
|
||||
if CompareReg(RegDown(pLine[0]^.pDst^.AsType(ntReg)),RegDown(pLine[1]^.ParamFirst^.Value^.AsType(ntReg))) then
|
||||
begin
|
||||
//Remove pnode
|
||||
FLineList.Remove(pnode);
|
||||
pLine[0]^.mark_not_used;
|
||||
|
||||
pnode:=pprev;
|
||||
Continue;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
pnode:=pprev;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrPrivate.AddLine(pLine:PspirvOp);
|
||||
var
|
||||
node:PVNode;
|
||||
begin
|
||||
node:=Emit.Alloc(SizeOf(TVNode));
|
||||
node^.pLine:=pLine;
|
||||
FLineList.Push_tail(node);
|
||||
end;
|
||||
|
||||
procedure TsrPrivate.AddLine(pLine:PspirvOp;node:TsrVolatile.PVNode);
|
||||
var
|
||||
_node:PVNode;
|
||||
begin
|
||||
_node:=Pointer(node); //hack
|
||||
_node^:=Default(TVNode);
|
||||
_node^.pLine:=pLine;
|
||||
FLineList.Push_tail(_node);
|
||||
end;
|
||||
|
||||
procedure TsrPrivate.FetchLoad(pLine:PspirvOp;dst:PsrRegNode);
|
||||
begin
|
||||
Assert(dst<>nil);
|
||||
|
||||
pLine:=PspirvOp(Emit.OpLoad(pLine,FType,dst,FVar));
|
||||
|
||||
AddLine(pLine);
|
||||
end;
|
||||
|
||||
Procedure TsrPrivate.FetchStore(pLine:PspirvOp;node:TsrVolatile.PVNode);
|
||||
var
|
||||
src:PsrRegNode;
|
||||
begin
|
||||
if (node=nil) then Exit;
|
||||
src:=node^.pReg;
|
||||
if (src=nil) then Exit;
|
||||
|
||||
pLine:=PspirvOp(Emit.OpStore(pLine,FVar,src));
|
||||
|
||||
AddLine(pLine,node);
|
||||
end;
|
||||
|
||||
function TsrPrivate.NewVolatile:PsrVolatile;
|
||||
begin
|
||||
Result:=Emit.Alloc(SizeOf(TsrVolatile));
|
||||
Result^.Init(@Self);
|
||||
FVoltList.Push_tail(Result);
|
||||
end;
|
||||
|
||||
procedure TsrPrivate.RemoveAllStore;
|
||||
var
|
||||
node:PsrVolatile;
|
||||
begin
|
||||
node:=FVoltList.pHead;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
node^.RemoveAllStore;
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
procedure TsrPrivateList.Init(Emit:TCustomEmit); inline;
|
||||
begin
|
||||
FEmit:=Emit;
|
||||
end;
|
||||
|
||||
function TsrPrivateList.Fetch(pSource:PsrRegSlot):PsrPrivate;
|
||||
var
|
||||
node:TsrPrivate;
|
||||
begin
|
||||
Assert(pSource<>nil);
|
||||
node:=Default(TsrPrivate);
|
||||
node.Init;
|
||||
node.FSource:=pSource;
|
||||
Result:=FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=FEmit.Alloc(SizeOf(TsrPrivate));
|
||||
Move(node,Result^,SizeOf(TsrPrivate));
|
||||
//
|
||||
//Result^.FVolatile.Init(Result);
|
||||
//
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
Function TsrPrivateList.First:PsrPrivate;
|
||||
begin
|
||||
Result:=FNTree.Min;
|
||||
end;
|
||||
|
||||
Function TsrPrivateList.Next(node:PsrPrivate):PsrPrivate;
|
||||
begin
|
||||
Result:=FNTree.Next(node);
|
||||
end;
|
||||
|
||||
procedure TsrPrivateList.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 TsrPrivateList.build_slot_cur(pSlot:PsrRegSlot;var old:PsrRegNode);
|
||||
var
|
||||
cur,prv,new:PsrRegNode;
|
||||
pPrivate :PsrPrivate;
|
||||
pVolatile:PsrVolatile;
|
||||
rtype:TsrDataType;
|
||||
begin
|
||||
cur:=RegDownSlot(pSlot^.current);
|
||||
prv:=RegDownSlot(old);
|
||||
if CompareReg(cur,prv) then Exit;
|
||||
|
||||
cur:=pSlot^.current;
|
||||
|
||||
if (cur=nil) then
|
||||
begin
|
||||
Assert(false,'WTF');
|
||||
end;
|
||||
if (old=nil) then
|
||||
begin
|
||||
//////old:=pSlot^.New(line,rtype); //Unresolve
|
||||
end;
|
||||
|
||||
pPrivate :=Fetch(pSlot);
|
||||
//pVolatile:=@pPrivate^.FVolatile;
|
||||
pVolatile:=pPrivate^.NewVolatile;
|
||||
|
||||
rtype:=dtUnknow;
|
||||
|
||||
if (old<>nil) then
|
||||
//if (old^.pWriter^.AsType(ntVolatile)<>pVolatile) then
|
||||
//if not old^.pWriter^.IsType(ntVolatile) then
|
||||
begin
|
||||
pVolatile^.AddStore(old);
|
||||
rtype:=old^.dtype;
|
||||
end;
|
||||
//
|
||||
if (cur<>nil) then
|
||||
//if (cur^.pWriter^.AsType(ntVolatile)<>pVolatile) then
|
||||
//if not cur^.pWriter^.IsType(ntVolatile) then
|
||||
begin
|
||||
pVolatile^.AddStore(cur);
|
||||
rtype:=cur^.dtype;
|
||||
end;
|
||||
|
||||
//old^.PrepType(ord(pVolatile^.Ftype));
|
||||
//cur^.PrepType(ord(pVolatile^.Ftype));
|
||||
|
||||
new:=pSlot^.New(cur^.pLine,rtype);
|
||||
new^.pWriter:=pVolatile;
|
||||
FEmit.PostLink(cur^.pLine,new); //post processing
|
||||
|
||||
old:=new; //update snap
|
||||
end;
|
||||
|
||||
procedure TsrPrivateList.build_slot_old(pSlot:PsrRegSlot;var old:PsrRegNode);
|
||||
var
|
||||
cur,prv,new:PsrRegNode;
|
||||
pPrivate :PsrPrivate;
|
||||
pVolatile:PsrVolatile;
|
||||
begin
|
||||
cur:=RegDownSlot(pSlot^.current);
|
||||
prv:=RegDownSlot(old);
|
||||
if CompareReg(cur,prv) then Exit;
|
||||
|
||||
cur:=pSlot^.current;
|
||||
|
||||
if (old<>nil) then
|
||||
if old^.pWriter^.IsType(ntVolatile) then
|
||||
begin
|
||||
pVolatile:=old^.pWriter^.AsType(ntVolatile);
|
||||
//if (pVolatile<>cur^.pWriter^.AsType(ntVolatile)) then
|
||||
begin
|
||||
pVolatile^.AddStore(cur);
|
||||
end;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
prv:=nil;
|
||||
if (old<>nil) then
|
||||
begin
|
||||
prv:=old^.pWriter^.AsType(ntReg);
|
||||
Assert(prv<>nil);
|
||||
end;
|
||||
|
||||
pPrivate :=Fetch(pSlot);
|
||||
//pVolatile:=@pPrivate^.FVolatile;
|
||||
pVolatile:=pPrivate^.NewVolatile;
|
||||
|
||||
//if (pVolatile<>prv^.pWriter^.AsType(ntVolatile)) then
|
||||
begin
|
||||
pVolatile^.AddStore(prv);
|
||||
end;
|
||||
|
||||
//if (pVolatile<>cur^.pWriter^.AsType(ntVolatile)) then
|
||||
begin
|
||||
pVolatile^.AddStore(cur);
|
||||
end;
|
||||
|
||||
if (old<>nil) then
|
||||
begin
|
||||
old^.pWriter:=pVolatile;
|
||||
end else
|
||||
if (cur<>nil) then
|
||||
begin
|
||||
new:=pSlot^.New(cur^.pLine,cur^.dtype);
|
||||
new^.pWriter:=pVolatile;
|
||||
FEmit.PostLink(FEmit.curr_line,new); //post processing
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
procedure TsrPrivateList.build_volatile_dis(old:PsrRegsSnapshot);
|
||||
var
|
||||
pRegsStory:PsrRegsStory;
|
||||
begin
|
||||
//exit;
|
||||
pRegsStory:=FEmit.GetRegsStory;
|
||||
pRegsStory^.ForEachSnap(@build_slot_dis,old);
|
||||
end;
|
||||
|
||||
procedure TsrPrivateList.build_volatile_cur(old:PsrRegsSnapshot);
|
||||
var
|
||||
pRegsStory:PsrRegsStory;
|
||||
begin
|
||||
//exit;
|
||||
pRegsStory:=FEmit.GetRegsStory;
|
||||
//NextVolatileID; FVolatileID:SizeUint;
|
||||
pRegsStory^.ForEachSnap(@build_slot_cur,old);
|
||||
end;
|
||||
|
||||
procedure TsrPrivateList.build_volatile_old(old:PsrRegsSnapshot);
|
||||
var
|
||||
pRegsStory:PsrRegsStory;
|
||||
begin
|
||||
//exit;
|
||||
pRegsStory:=FEmit.GetRegsStory;
|
||||
//NextVolatileID; FVolatileID:SizeUint;
|
||||
pRegsStory^.ForEachSnap(@build_slot_old,old);
|
||||
end;
|
||||
|
||||
procedure TsrPrivateList.make_copy_slot(pSlot:PsrRegSlot);
|
||||
var
|
||||
cur,node:PsrRegNode;
|
||||
begin
|
||||
//exit;
|
||||
if (pSlot^.current<>nil) then
|
||||
begin
|
||||
cur:=pSlot^.current;
|
||||
|
||||
//MakeCopy(pSlot,cur);
|
||||
node:=pSlot^.New(FEmit.curr_line,cur^.dtype);
|
||||
node^.pWriter:=cur;
|
||||
FEmit.PostLink(FEmit.curr_line,node); //post processing
|
||||
|
||||
pSlot^.current^.pLine:=cur^.pLine;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrPrivateList.make_copy_all;
|
||||
var
|
||||
pRegsStory:PsrRegsStory;
|
||||
begin
|
||||
//exit;
|
||||
pRegsStory:=FEmit.GetRegsStory;
|
||||
pRegsStory^.ForEachSlot(@make_copy_slot);
|
||||
end;
|
||||
|
||||
function get_load_from(r:PsrRegNode):PsrVariable;
|
||||
var
|
||||
pOp:PspirvOp;
|
||||
begin
|
||||
Result:=nil;
|
||||
pOp:=r^.pWriter^.AsType(ntOp);
|
||||
if (pOp=nil) then Exit;
|
||||
if (pOp^.OpId<>Op.OpLoad) then Exit;
|
||||
Result:=pOp^.ParamFirst^.Value^.AsType(ntVariable);
|
||||
end;
|
||||
|
||||
function get_load_from2(r:PsrRegNode):PsrVolatile;
|
||||
begin
|
||||
Result:=r^.pWriter^.AsType(ntVolatile);
|
||||
end;
|
||||
|
||||
procedure _Move(dst,src:PsrVolatile);
|
||||
var
|
||||
node:TsrVolatile.PVNode;
|
||||
begin
|
||||
node:=src^.PopStore;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
dst^.PushStore(node);
|
||||
node:=src^.PopStore;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrPrivateList.PrepVolatile(dst:PspirvOp;src:PsrRegNode); //use forward only
|
||||
var
|
||||
tmp:PsrRegNode;
|
||||
pPrivate :PsrPrivate;
|
||||
pVolatile:PsrVolatile;
|
||||
node:TsrVolatile.PVNode;
|
||||
pLine:PspirvOp;
|
||||
vtmp:PsrVolatile;
|
||||
begin
|
||||
if (src=nil) then Exit;
|
||||
if (not src^.pWriter^.IsType(ntVolatile)) then Exit;
|
||||
|
||||
pVolatile:=src^.pWriter^.AsType(ntVolatile);
|
||||
pPrivate :=pVolatile^.FSource;
|
||||
src^.pWriter:=nil;
|
||||
|
||||
pPrivate^.InitVar(FEmit);
|
||||
|
||||
pPrivate ^.PrepType(src^.dtype);
|
||||
pVolatile^.PrepType(pPrivate^.GetRegType);
|
||||
|
||||
if (pPrivate^.GetRegType=dtUnknow) then
|
||||
begin
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
node:=pVolatile^.PopStore;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
|
||||
tmp:=RegDown{Slot}(node^.pReg);
|
||||
|
||||
if (src<>tmp) {and (pPrivate^.pVar<>get_load_from(tmp))} then
|
||||
begin
|
||||
pLine:=node^.pReg^.pLine;
|
||||
Assert(pLine<>nil);
|
||||
|
||||
if (tmp^.pWriter^.IsType(ntVolatile)) then
|
||||
begin
|
||||
vtmp:=tmp^.pWriter^.AsType(ntVolatile);
|
||||
Assert(vtmp<>nil);
|
||||
|
||||
_Move(pVolatile,vtmp);
|
||||
|
||||
tmp^.pWriter:=src;
|
||||
|
||||
Continue;
|
||||
end;
|
||||
|
||||
up_merge_line(pLine);
|
||||
|
||||
pPrivate^.FetchStore(pLine,node);
|
||||
end;
|
||||
|
||||
node:=pVolatile^.PopStore;
|
||||
end;
|
||||
|
||||
pLine:=dst;
|
||||
Assert(pLine<>nil);
|
||||
pLine:=pLine^.Prev;
|
||||
Assert(pLine<>nil);
|
||||
|
||||
up_merge_line(pLine);
|
||||
|
||||
Assert(pLine<>nil);
|
||||
|
||||
//ntVolatile -> src -> next
|
||||
//Opload -> src -> next
|
||||
|
||||
pPrivate^.FetchLoad(pLine,src); //before reg
|
||||
end;
|
||||
|
||||
Procedure TsrPrivateList.Post;
|
||||
var
|
||||
node:PsrPrivate;
|
||||
begin
|
||||
node:=FNTree.Min;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if node^.IsUsed then
|
||||
begin
|
||||
node^.RemoveAllStore;
|
||||
node^.SortLines;
|
||||
node^.Optimize;
|
||||
node^.UpdateRegType;
|
||||
end;
|
||||
node:=FNTree.Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
||||
|
||||
|
|
@ -4,11 +4,27 @@ unit srRefId;
|
|||
|
||||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
srNode;
|
||||
|
||||
type
|
||||
ntRefId=class(TsrNodeVmt)
|
||||
class function GetPrintName(node:PsrNode):RawByteString; override;
|
||||
class function GetRef(node:PsrNode):Pointer; override;
|
||||
end;
|
||||
|
||||
PsrRefId=^TsrRefId;
|
||||
TsrRefId=packed object
|
||||
TsrRefId=object
|
||||
ID:DWORD;
|
||||
function Alloc:Boolean; inline;
|
||||
function Alloc:Boolean; inline;
|
||||
end;
|
||||
|
||||
PsrRefNode=^TsrRefNode;
|
||||
TsrRefNode=object(TsrNode)
|
||||
ID:TsrRefId;
|
||||
Procedure Init; inline;
|
||||
function GetPrintName:RawByteString;
|
||||
end;
|
||||
|
||||
PsrRefIdAlloc=^TsrRefIdAlloc;
|
||||
|
@ -21,6 +37,27 @@ type
|
|||
|
||||
implementation
|
||||
|
||||
class function ntRefId.GetPrintName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrRefNode(node)^.GetPrintName;
|
||||
end;
|
||||
|
||||
class function ntRefId.GetRef(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=@PsrRefNode(node)^.ID;
|
||||
end;
|
||||
|
||||
Procedure TsrRefNode.Init; inline;
|
||||
begin
|
||||
fntype:=ntRefId;
|
||||
end;
|
||||
|
||||
function TsrRefNode.GetPrintName:RawByteString;
|
||||
begin
|
||||
Assert(ID.ID<>0);
|
||||
Result:=IntToStr(ID.ID);
|
||||
end;
|
||||
|
||||
function TsrRefId.Alloc:Boolean; inline;
|
||||
begin
|
||||
Result:=(ID<>0);
|
||||
|
|
654
spirv/srReg.pas
654
spirv/srReg.pas
|
@ -5,38 +5,101 @@ unit srReg;
|
|||
interface
|
||||
|
||||
uses
|
||||
srNodes,
|
||||
srRefId,
|
||||
srTypes,
|
||||
srConst;
|
||||
sysutils,
|
||||
ginodes,
|
||||
srNode,
|
||||
srRefId,
|
||||
srType,
|
||||
srConst;
|
||||
|
||||
type
|
||||
ntReg=class(TsrNodeVmt)
|
||||
class Procedure add_read (node,src:PsrNode); override;
|
||||
class Procedure rem_read (node,src:PsrNode); override;
|
||||
class Procedure SetWriter (node,w,line:PsrNode); override;
|
||||
class Procedure ResetWriter (node,w:PsrNode); override;
|
||||
class function Down (node:PsrNode):Pointer; override;
|
||||
class function Next (node:PsrNode):Pointer; override;
|
||||
class function Prev (node:PsrNode):Pointer; override;
|
||||
class Procedure PrepType (node:PPrepTypeNode); override;
|
||||
class function GetPrintName(node:PsrNode):RawByteString; override;
|
||||
class function GetRef (node:PsrNode):Pointer; override;
|
||||
end;
|
||||
|
||||
ntRegPair=class(TsrNodeVmt)
|
||||
class function Down (node:PsrNode):Pointer; override;
|
||||
class Procedure SetWriter (node,w,line:PsrNode); override;
|
||||
class Procedure ResetWriter(node,w:PsrNode); override;
|
||||
end;
|
||||
|
||||
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);
|
||||
procedure SetReg(pReg:PsrRegNode);
|
||||
function AsConst:PsrConst;
|
||||
function AsOp:Pointer;
|
||||
function AsReg:PsrRegNode;
|
||||
function is_const:Boolean;
|
||||
function is_bool:Boolean;
|
||||
function is_bool_or_const_bool:Boolean;
|
||||
function is_unknow:Boolean;
|
||||
|
||||
PRegDNode=^TRegDNode;
|
||||
TRegDNode=record
|
||||
pNext:PRegDNode;
|
||||
pNode:PsrNode;
|
||||
end;
|
||||
TRegDNodeList=specialize TNodeStack<PRegDNode>;
|
||||
|
||||
TsrRegNode=packed object(TsrNode)
|
||||
private
|
||||
pPrev,pNext:PsrRegNode;
|
||||
//
|
||||
ID:TsrRefId; //post id
|
||||
F:bitpacked record
|
||||
dtype:TsrDataType;
|
||||
weak:Boolean;
|
||||
end;
|
||||
FSlot:PsrRegSlot;
|
||||
FWriter:PsrNode; //ntReg,ntConst,ntOp,ntVolatile
|
||||
FDList:TRegDNodeList;
|
||||
FLine:Pointer;
|
||||
Procedure AddDep(t:PsrNode);
|
||||
Procedure RemDep(t:PsrNode);
|
||||
function GetDtype:TsrDataType;
|
||||
Procedure SetDtype(t:TsrDataType);
|
||||
function GetWeak:Boolean;
|
||||
Procedure SetWeak(t:Boolean);
|
||||
Procedure SetWriter(t:PsrNode);
|
||||
Function GetWriter:PsrNode;
|
||||
Procedure SetLine(t:Pointer);
|
||||
public
|
||||
property pLine :Pointer read FLine write SetLine; //PspirvOp;
|
||||
property pSlot :PsrRegSlot read FSlot;
|
||||
property dtype :TsrDataType read GetDtype write SetDtype;
|
||||
property Weak :Boolean read GetWeak write SetWeak;
|
||||
property pWriter:PsrNode read GetWriter write SetWriter;
|
||||
Procedure Init; inline;
|
||||
function FirstDep:PRegDNode;
|
||||
function GetName:RawByteString;
|
||||
function AsConst:PsrConst;
|
||||
function AsReg:PsrRegNode;
|
||||
function is_const:Boolean;
|
||||
function is_bool:Boolean;
|
||||
function is_bool_or_const_bool:Boolean;
|
||||
function is_unknow:Boolean;
|
||||
function GetPrintName:RawByteString;
|
||||
end;
|
||||
|
||||
PsrRegPair=^TsrRegPair;
|
||||
TsrRegPair=object(TsrNode)
|
||||
private
|
||||
FWriter:PsrNode;
|
||||
FDst0:PsrNode;
|
||||
FDst1:PsrNode;
|
||||
Procedure SetWriter(t:PsrNode);
|
||||
Procedure SetDst0(r:PsrNode);
|
||||
Procedure SetDst1(r:PsrNode);
|
||||
public
|
||||
property pLine:PsrNode read FWriter;
|
||||
property pWriter:PsrNode read FWriter write SetWriter;
|
||||
property pDst0:PsrNode read FDst0 write SetDst0;
|
||||
property pDst1:PsrNode read FDst1 write SetDst1;
|
||||
Procedure Init; inline;
|
||||
end;
|
||||
|
||||
TRegStory=specialize TNodeList<PsrRegNode>;
|
||||
|
@ -44,15 +107,16 @@ type
|
|||
TString5=string[5];
|
||||
|
||||
TsrRegSlot=object
|
||||
Alloc:TfnAlloc;
|
||||
pVar:Pointer;
|
||||
FEmit:TCustomEmit;
|
||||
pStory:TRegStory;
|
||||
rid:TString5;
|
||||
Procedure Init(a:TfnAlloc;const n:TString5);
|
||||
Procedure Init(Emit:TCustomEmit;const n:TString5);
|
||||
function first:PsrRegNode;
|
||||
function current:PsrRegNode;
|
||||
function isBoolOnly:Boolean;
|
||||
function New(pLine:Pointer;rtype:TsrDataType):PsrRegNode;
|
||||
function NewAfter(rtype:TsrDataType;r:PsrRegNode):PsrRegNode;
|
||||
function NewBefore(rtype:TsrDataType;r:PsrRegNode):PsrRegNode;
|
||||
procedure Remove(r:PsrRegNode);
|
||||
end;
|
||||
|
||||
|
@ -69,6 +133,7 @@ type
|
|||
TForEachSlot=procedure(pSlot:PsrRegSlot) of object;
|
||||
TForEachSnap=procedure(pSlot:PsrRegSlot;var old:PsrRegNode) of object;
|
||||
|
||||
PsrRegsStory=^TsrRegsStory;
|
||||
TsrRegsStory=object
|
||||
SGRP:array[0..103] of TsrRegSlot;
|
||||
VCC:array[0..1] of TsrRegSlot;
|
||||
|
@ -77,25 +142,171 @@ type
|
|||
SCC:TsrRegSlot;
|
||||
VGRP:array[0..255] of TsrRegSlot;
|
||||
FUnattach:TsrRegSlot;
|
||||
Procedure Init(Alloc:TfnAlloc);
|
||||
function get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean;
|
||||
//
|
||||
FDList:TRegDNodeList;
|
||||
//
|
||||
Procedure Init(Emit:TCustomEmit);
|
||||
//
|
||||
Function AllocDep:PRegDNode;
|
||||
Procedure FreeDep(node:PRegDNode);
|
||||
//
|
||||
function get_sdst7(SDST:Byte):PsrRegSlot;
|
||||
function get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean;
|
||||
function get_ssrc8(SSRC:Byte):PsrRegSlot;
|
||||
function get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean;
|
||||
function get_ssrc9(SSRC:Word):PsrRegSlot;
|
||||
function get_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean;
|
||||
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;
|
||||
|
||||
function RegDown(node:PsrRegNode):PsrRegNode;
|
||||
function RegDownSlot(node:PsrRegNode):PsrRegNode;
|
||||
function CompareReg(r1,r2:PsrRegNode):Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
Procedure TsrRegsStory.Init(Alloc:TfnAlloc);
|
||||
//
|
||||
|
||||
class Procedure ntReg.add_read(node,src:PsrNode);
|
||||
begin
|
||||
inherited;
|
||||
PsrRegNode(node)^.AddDep(src);
|
||||
end;
|
||||
|
||||
class Procedure ntReg.rem_read(node,src:PsrNode);
|
||||
begin
|
||||
inherited;
|
||||
PsrRegNode(node)^.RemDep(src);
|
||||
end;
|
||||
|
||||
class Procedure ntReg.SetWriter(node,w,line:PsrNode);
|
||||
begin
|
||||
With PsrRegNode(node)^ do
|
||||
begin
|
||||
SetWriter(w);
|
||||
pLine:=line;
|
||||
end;
|
||||
end;
|
||||
|
||||
class Procedure ntReg.ResetWriter(node,w:PsrNode);
|
||||
begin
|
||||
With PsrRegNode(node)^ do
|
||||
if (FWriter=w) then
|
||||
begin
|
||||
SetWriter(nil);
|
||||
pLine:=nil;
|
||||
end;
|
||||
end;
|
||||
|
||||
class function ntReg.Down(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=PsrRegNode(node)^.FWriter;
|
||||
end;
|
||||
|
||||
class function ntReg.Next(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=PsrRegNode(node)^.pNext;
|
||||
end;
|
||||
|
||||
class function ntReg.Prev(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=PsrRegNode(node)^.pPrev;
|
||||
end;
|
||||
|
||||
class Procedure ntReg.PrepType(node:PPrepTypeNode);
|
||||
var
|
||||
new:TsrDataType;
|
||||
pConstList:PsrConstList;
|
||||
begin
|
||||
With PsrRegNode(node^.dnode)^ do
|
||||
begin
|
||||
new:=TsrDataType(node^.rtype);
|
||||
if (new=dtUnknow) then
|
||||
begin
|
||||
node^.dnode:=nil;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if FSlot^.isBoolOnly then
|
||||
begin
|
||||
//next
|
||||
node^.rtype:=ord(dtBool);
|
||||
node^.dnode:=pWriter;
|
||||
Exit;
|
||||
end else
|
||||
if is_unprep_type(dtype,new,Weak) then
|
||||
begin
|
||||
dtype:=new;
|
||||
Weak:=True;
|
||||
if is_const then
|
||||
begin
|
||||
pConstList:=FSlot^.FEmit.GetConstList;
|
||||
pWriter:=pConstList^.Bitcast(new,pWriter^.AsType(ntConst));
|
||||
end else
|
||||
begin
|
||||
//next
|
||||
node^.dnode:=pWriter;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
||||
node^.dnode:=nil;
|
||||
end;
|
||||
|
||||
class function ntReg.GetPrintName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrRegNode(node)^.GetPrintName;
|
||||
end;
|
||||
|
||||
class function ntReg.GetRef(node:PsrNode):Pointer;
|
||||
begin
|
||||
With PsrRegNode(node)^ do
|
||||
begin
|
||||
if is_const then
|
||||
begin
|
||||
Result:=AsConst^.GetRef;
|
||||
end else
|
||||
begin
|
||||
Result:=@ID;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
class function ntRegPair.Down(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=PsrRegPair(node)^.FWriter;
|
||||
end;
|
||||
|
||||
class Procedure ntRegPair.SetWriter(node,w,line:PsrNode);
|
||||
begin
|
||||
With PsrRegPair(node)^ do
|
||||
begin
|
||||
SetWriter(w);
|
||||
end;
|
||||
end;
|
||||
|
||||
class Procedure ntRegPair.ResetWriter(node,w:PsrNode);
|
||||
begin
|
||||
With PsrRegPair(node)^ do
|
||||
if (FWriter=w) then
|
||||
begin
|
||||
SetWriter(nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
Procedure TsrRegsStory.Init(Emit:TCustomEmit);
|
||||
var
|
||||
i:Word;
|
||||
n:TString5;
|
||||
|
@ -104,20 +315,50 @@ begin
|
|||
For i:=0 to 103 do
|
||||
begin
|
||||
Str(i,n);
|
||||
SGRP[i].Init(Alloc,'S'+n);
|
||||
SGRP[i].Init(Emit,'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');
|
||||
VCC[0].Init(Emit,'VCCL');
|
||||
VCC[1].Init(Emit,'VCCH');
|
||||
M0.Init(Emit,'M0');
|
||||
EXEC[0].Init(Emit,'EXECL');
|
||||
EXEC[1].Init(Emit,'EXECH');
|
||||
SCC.Init(Emit,'SCC');
|
||||
For i:=0 to 255 do
|
||||
begin
|
||||
Str(i,n);
|
||||
VGRP[i].Init(Alloc,'V'+n);
|
||||
VGRP[i].Init(Emit,'V'+n);
|
||||
end;
|
||||
FUnattach.Init(Emit,'UNATT');
|
||||
end;
|
||||
|
||||
Function TsrRegsStory.AllocDep:PRegDNode;
|
||||
begin
|
||||
Result:=FDList.Pop_head;
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=FUnattach.FEmit.Alloc(SizeOf(TRegDNode));
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrRegsStory.FreeDep(node:PRegDNode);
|
||||
begin
|
||||
if (node=nil) then Exit;
|
||||
node^:=Default(TRegDNode);
|
||||
FDList.Push_head(node);
|
||||
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;
|
||||
FUnattach.Init(Alloc,'UNATT');
|
||||
end;
|
||||
|
||||
function TsrRegsStory.get_sdst7_pair(SDST:Byte;dst:PPsrRegSlot):Boolean;
|
||||
|
@ -145,20 +386,6 @@ begin
|
|||
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
|
||||
|
@ -179,6 +406,27 @@ begin
|
|||
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_ssrc9_pair(SSRC:Word;src:PPsrRegSlot):Boolean;
|
||||
begin
|
||||
Result:=True;
|
||||
|
@ -209,27 +457,6 @@ begin
|
|||
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];
|
||||
|
@ -350,85 +577,210 @@ end;
|
|||
|
||||
//--
|
||||
|
||||
Procedure TsrRegNode.Init; inline;
|
||||
begin
|
||||
fntype:=ntReg;
|
||||
end;
|
||||
|
||||
function TsrRegNode.GetName:RawByteString;
|
||||
begin
|
||||
Result:='';
|
||||
if (pSlot<>nil) then Result:=pSlot^.rid;
|
||||
if (FSlot<>nil) then Result:=FSlot^.rid;
|
||||
end;
|
||||
|
||||
Procedure TsrRegNode.mark_read;
|
||||
Procedure TsrRegNode.AddDep(t:PsrNode);
|
||||
var
|
||||
pRegsStory:PsrRegsStory;
|
||||
node:PRegDNode;
|
||||
begin
|
||||
Inc(read_count);
|
||||
if (t=nil) or (@Self=nil) then Exit;
|
||||
|
||||
pRegsStory:=FSlot^.FEmit.GetRegsStory;
|
||||
node:=pRegsStory^.AllocDep;
|
||||
|
||||
node^.pNode:=t;
|
||||
FDList.Push_head(node);
|
||||
end;
|
||||
|
||||
Procedure TsrRegNode.mark_unread;
|
||||
Procedure TsrRegNode.RemDep(t:PsrNode);
|
||||
var
|
||||
pRegsStory:PsrRegsStory;
|
||||
node,_prev:PRegDNode;
|
||||
begin
|
||||
Assert(read_count<>0);
|
||||
if (read_count<>0) then Dec(read_count);
|
||||
if (t=nil) or (@Self=nil) then Exit;
|
||||
node:=FDList.pHead;
|
||||
_prev:=nil;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.pNode=t) then
|
||||
begin
|
||||
if (_prev=nil) then
|
||||
begin
|
||||
FDList.pHead:=node^.pNext;
|
||||
end else
|
||||
begin
|
||||
_prev^.pNext:=node^.pNext;
|
||||
end;
|
||||
|
||||
pRegsStory:=FSlot^.FEmit.GetRegsStory;
|
||||
pRegsStory^.FreeDep(node);
|
||||
|
||||
Exit;
|
||||
end;
|
||||
_prev:=node;
|
||||
node:=node^.pNext;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrRegNode.SetConst(pConst:PsrConst);
|
||||
function TsrRegNode.FirstDep:PRegDNode;
|
||||
begin
|
||||
pWriter.SetParam(ntConst,pConst);
|
||||
dtype:=pConst^.key.dtype;
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
Result:=FDList.pHead;
|
||||
end;
|
||||
|
||||
procedure TsrRegNode.SetReg(pReg:PsrRegNode);
|
||||
function TsrRegNode.GetDtype:TsrDataType;
|
||||
begin
|
||||
Assert(@Self<>pReg);
|
||||
pWriter.SetParam(ntReg,pReg);
|
||||
Result:=F.dtype;
|
||||
end;
|
||||
|
||||
Procedure TsrRegNode.SetDtype(t:TsrDataType);
|
||||
begin
|
||||
F.dtype:=t;
|
||||
end;
|
||||
|
||||
function TsrRegNode.GetWeak:Boolean;
|
||||
begin
|
||||
Result:=F.weak;
|
||||
end;
|
||||
|
||||
Procedure TsrRegNode.SetWeak(t:Boolean);
|
||||
begin
|
||||
F.weak:=t;
|
||||
end;
|
||||
|
||||
Procedure TsrRegNode.SetWriter(t:PsrNode);
|
||||
begin
|
||||
if (@Self=nil) then Exit;
|
||||
if (FWriter=t) then Exit;
|
||||
|
||||
Assert(RegDown(t^.AsType(ntReg))<>@Self,'Circular reference');
|
||||
|
||||
if isUsed then
|
||||
begin
|
||||
t^.mark_read (@Self);
|
||||
FWriter^.mark_unread(@Self);
|
||||
end;
|
||||
FWriter:=t;
|
||||
end;
|
||||
|
||||
Function TsrRegNode.GetWriter:PsrNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
Result:=FWriter;
|
||||
end;
|
||||
|
||||
Procedure TsrRegNode.SetLine(t:Pointer);
|
||||
begin
|
||||
if (@Self=nil) then Exit;
|
||||
if (FWriter<>nil) then
|
||||
if (FWriter^.ntype.ClassName='ntOp') then
|
||||
begin
|
||||
Assert(FWriter=t);
|
||||
end;
|
||||
FLine:=t;
|
||||
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;
|
||||
if (@Self=nil) then Exit(nil);
|
||||
Result:=PsrConst(FWriter^.AsType(ntConst));
|
||||
end;
|
||||
|
||||
function TsrRegNode.AsReg:PsrRegNode;
|
||||
begin
|
||||
Result:=nil;
|
||||
if (@Self=nil) then Exit;
|
||||
if (pWriter.ntype<>ntReg) then Exit;
|
||||
Result:=pWriter.pData;
|
||||
if (@Self=nil) then Exit(nil);
|
||||
Result:=PsrRegNode(FWriter^.AsType(ntReg));
|
||||
end;
|
||||
|
||||
function TsrRegNode.is_const:Boolean;
|
||||
begin
|
||||
Result:=(pWriter.ntype=ntConst);
|
||||
if (@Self=nil) then Exit(False);
|
||||
Result:=FWriter^.IsType(ntConst);
|
||||
end;
|
||||
|
||||
function TsrRegNode.is_bool:Boolean;
|
||||
begin
|
||||
if (@Self=nil) then Exit(False);
|
||||
Result:=(dtype=dtBool);
|
||||
end;
|
||||
|
||||
function TsrRegNode.is_bool_or_const_bool:Boolean;
|
||||
begin
|
||||
if (@Self=nil) then Exit(False);
|
||||
Result:=is_bool or
|
||||
(is_const and (AsConst<>nil) and AsConst^.isBoolVal);
|
||||
(is_const and AsConst^.isBoolVal);
|
||||
end;
|
||||
|
||||
function TsrRegNode.is_unknow:Boolean;
|
||||
begin
|
||||
if (@Self=nil) then Exit(True);
|
||||
Result:=(dtype=dtUnknow);
|
||||
end;
|
||||
|
||||
function TsrRegNode.GetPrintName:RawByteString;
|
||||
begin
|
||||
if is_const then
|
||||
begin
|
||||
Result:=AsConst^.GetPrintName;
|
||||
end else
|
||||
begin
|
||||
Assert(ID.Alloc);
|
||||
Result:='r'+IntToStr(ID.ID);
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
|
||||
Procedure TsrRegPair.SetWriter(t:PsrNode);
|
||||
begin
|
||||
if (FWriter=t) then Exit;
|
||||
if isUsed then
|
||||
begin
|
||||
t^.mark_read (@Self);
|
||||
FWriter^.mark_unread(@Self);
|
||||
end;
|
||||
FWriter:=t;
|
||||
end;
|
||||
|
||||
Procedure TsrRegPair.SetDst0(r:PsrNode);
|
||||
begin
|
||||
if (FDst0=r) then Exit;
|
||||
FDst0^.ResetWriter(@Self);
|
||||
FDst0:=r;
|
||||
FDst0^.SetWriter(@Self,pLine);
|
||||
end;
|
||||
|
||||
Procedure TsrRegPair.SetDst1(r:PsrNode);
|
||||
begin
|
||||
if (FDst1=r) then Exit;
|
||||
FDst1^.ResetWriter(@Self);
|
||||
FDst1:=r;
|
||||
FDst1^.SetWriter(@Self,pLine);
|
||||
end;
|
||||
|
||||
Procedure TsrRegPair.Init; inline;
|
||||
begin
|
||||
fntype:=ntRegPair;
|
||||
end;
|
||||
|
||||
//--
|
||||
|
||||
Procedure TsrRegSlot.Init(a:TfnAlloc;const n:TString5);
|
||||
Procedure TsrRegSlot.Init(Emit:TCustomEmit;const n:TString5);
|
||||
begin
|
||||
Alloc:=a;
|
||||
FEmit:=Emit;
|
||||
rid :=n;
|
||||
end;
|
||||
|
||||
|
@ -442,12 +794,22 @@ begin
|
|||
Result:=pStory.pTail;
|
||||
end;
|
||||
|
||||
function TsrRegSlot.isBoolOnly:Boolean;
|
||||
begin
|
||||
Result:=(rid='SCC');
|
||||
end;
|
||||
|
||||
function TsrRegSlot.New(pLine:Pointer;rtype:TsrDataType):PsrRegNode;
|
||||
var
|
||||
node:PsrRegNode;
|
||||
begin
|
||||
node:=Alloc(SizeOf(TsrRegNode));
|
||||
node^.pSlot:=@Self;
|
||||
if isBoolOnly then
|
||||
begin
|
||||
rtype:=dtBool;
|
||||
end;
|
||||
node:=FEmit.Alloc(SizeOf(TsrRegNode));
|
||||
node^.Init;
|
||||
node^.FSlot:=@Self;
|
||||
node^.dtype:=rtype;
|
||||
node^.pLine:=pLine;
|
||||
pStory.Push_tail(node);
|
||||
|
@ -458,19 +820,85 @@ function TsrRegSlot.NewAfter(rtype:TsrDataType;r:PsrRegNode):PsrRegNode;
|
|||
var
|
||||
node:PsrRegNode;
|
||||
begin
|
||||
node:=Alloc(SizeOf(TsrRegNode));
|
||||
node^.pSlot:=@Self;
|
||||
if isBoolOnly then
|
||||
begin
|
||||
rtype:=dtBool;
|
||||
end;
|
||||
node:=FEmit.Alloc(SizeOf(TsrRegNode));
|
||||
node^.Init;
|
||||
node^.FSlot:=@Self;
|
||||
node^.dtype:=rtype;
|
||||
node^.pLine:=r^.pLine;
|
||||
pStory.InsertAfter(r,node);
|
||||
Result:=node;
|
||||
end;
|
||||
|
||||
function TsrRegSlot.NewBefore(rtype:TsrDataType;r:PsrRegNode):PsrRegNode;
|
||||
var
|
||||
node:PsrRegNode;
|
||||
begin
|
||||
if isBoolOnly then
|
||||
begin
|
||||
rtype:=dtBool;
|
||||
end;
|
||||
node:=FEmit.Alloc(SizeOf(TsrRegNode));
|
||||
node^.Init;
|
||||
node^.FSlot:=@Self;
|
||||
node^.dtype:=rtype;
|
||||
node^.pLine:=r^.pLine;
|
||||
pStory.InsertBefore(r,node);
|
||||
Result:=node;
|
||||
end;
|
||||
|
||||
procedure TsrRegSlot.Remove(r:PsrRegNode);
|
||||
begin
|
||||
if (r=nil) then Exit;
|
||||
pStory.Remove(r);
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
function RegDown(node:PsrRegNode):PsrRegNode;
|
||||
var
|
||||
tmp:PsrRegNode;
|
||||
begin
|
||||
//backtrace
|
||||
Result:=node;
|
||||
While (Result<>nil) do
|
||||
begin
|
||||
tmp:=Result^.AsReg; //next
|
||||
if (tmp=nil) then Break;
|
||||
Assert(tmp<>Result);
|
||||
Result:=tmp;
|
||||
end;
|
||||
end;
|
||||
|
||||
function RegDownSlot(node:PsrRegNode):PsrRegNode;
|
||||
var
|
||||
tmp:PsrRegNode;
|
||||
begin
|
||||
//backtrace
|
||||
Result:=node;
|
||||
While (Result<>nil) do
|
||||
begin
|
||||
tmp:=Result^.AsReg; //next
|
||||
if (tmp=nil) then Break;
|
||||
Assert(tmp<>Result);
|
||||
if (tmp^.pSlot<>Result^.pSlot) then Break;
|
||||
Result:=tmp;
|
||||
end;
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
end.
|
||||
|
||||
|
|
|
@ -0,0 +1,623 @@
|
|||
unit srType;
|
||||
|
||||
{$mode objfpc}{$H+}
|
||||
{$modeswitch typehelpers}
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
bittype,
|
||||
Half16;
|
||||
|
||||
type
|
||||
TsrDataType=(
|
||||
//Real types
|
||||
dtUnknow,
|
||||
dtBool,
|
||||
|
||||
dtHalf16,
|
||||
dtFloat32,
|
||||
dtFloat64,
|
||||
|
||||
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,
|
||||
|
||||
dtVec2h,
|
||||
dtVec4h,
|
||||
|
||||
dtVec2f,
|
||||
dtVec3f,
|
||||
dtVec4f,
|
||||
|
||||
//Spirv types
|
||||
dtTypeVoid,
|
||||
dtTypeFunction,
|
||||
dtTypePointer,
|
||||
dtTypeStruct,
|
||||
dtTypeArray,
|
||||
dtTypeRuntimeArray,
|
||||
dtTypeImage,
|
||||
dtTypeSampler,
|
||||
dtTypeSampledImage,
|
||||
|
||||
dtString,
|
||||
dtConstant
|
||||
);
|
||||
|
||||
TsrDataTypeHelper = type helper for TsrDataType
|
||||
function isInt:Boolean;
|
||||
function isFloat:Boolean;
|
||||
function isBool:Boolean;
|
||||
function isVector:Boolean;
|
||||
function isScalar:Boolean;
|
||||
function Child:TsrDataType;
|
||||
function Count:Byte;
|
||||
function Sign:Byte;
|
||||
function BitSize:Byte;
|
||||
function High:QWORD;
|
||||
function AsVector(_count:Byte):TsrDataType;
|
||||
end;
|
||||
|
||||
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;
|
||||
|
||||
//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;
|
||||
|
||||
function type_get_base_name1(dtype:TsrDataType):RawByteString;
|
||||
function LazyType2(t1,t2:TsrDataType):TsrDataType;
|
||||
function LazyType3(t1,t2,t3:TsrDataType):TsrDataType;
|
||||
function StoreType(t:TsrDataType):TsrDataType;
|
||||
function CompareType(rtype1,rtype2:TsrDataType):Boolean;
|
||||
function TryBitcastType(rtype1,rtype2:TsrDataType):Boolean;
|
||||
function is_unprep_type(old,new:TsrDataType;weak:Boolean):Boolean;
|
||||
|
||||
implementation
|
||||
|
||||
function type_get_base_name1(dtype:TsrDataType):RawByteString;
|
||||
begin
|
||||
Result:='';
|
||||
case dtype of
|
||||
|
||||
dtBool :Result:='bool';
|
||||
|
||||
dtHalf16 :Result:='half';
|
||||
dtFloat32 :Result:='float';
|
||||
dtFloat64 :Result:='double';
|
||||
|
||||
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';
|
||||
|
||||
dtVec2h :Result:='hvec2';
|
||||
dtVec4h :Result:='hvec4';
|
||||
|
||||
dtVec2f :Result:='vec2';
|
||||
dtVec3f :Result:='vec3';
|
||||
dtVec4f :Result:='vec4';
|
||||
|
||||
dtTypeVoid :Result:='void';
|
||||
dtTypeSampler:Result:='samp';
|
||||
|
||||
else;
|
||||
end;
|
||||
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 StoreType(t:TsrDataType):TsrDataType;
|
||||
begin
|
||||
if (t=dtBool) then
|
||||
Result:=dtUint32
|
||||
else
|
||||
Result:=t;
|
||||
end;
|
||||
|
||||
function TsrDataTypeHelper.isInt:Boolean;
|
||||
begin
|
||||
Case Self of
|
||||
dtInt8,
|
||||
dtUint8,
|
||||
|
||||
dtInt16,
|
||||
dtUint16,
|
||||
|
||||
dtInt32,
|
||||
dtUint32,
|
||||
|
||||
dtInt64,
|
||||
dtUint64,
|
||||
|
||||
dtStruct2u,
|
||||
|
||||
dtVec2u8,
|
||||
dtVec4u8,
|
||||
|
||||
dtVec2i8,
|
||||
dtVec4i8,
|
||||
|
||||
dtVec2u16,
|
||||
dtVec4u16,
|
||||
|
||||
dtVec2i16,
|
||||
dtVec4i16,
|
||||
|
||||
dtVec2u,
|
||||
dtVec3u,
|
||||
dtVec4u,
|
||||
|
||||
dtVec2i,
|
||||
dtVec3i,
|
||||
dtVec4i,
|
||||
|
||||
dtVec2f,
|
||||
dtVec3f,
|
||||
dtVec4f:
|
||||
Result:=True;
|
||||
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataTypeHelper.isFloat:Boolean;
|
||||
begin
|
||||
Case Self of
|
||||
dtHalf16,
|
||||
dtFloat32,
|
||||
dtFloat64,
|
||||
|
||||
dtVec2h,
|
||||
dtVec4h,
|
||||
|
||||
dtVec2f,
|
||||
dtVec3f,
|
||||
dtVec4f:
|
||||
Result:=True;
|
||||
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataTypeHelper.isBool:Boolean;
|
||||
begin
|
||||
Case Self of
|
||||
dtBool,
|
||||
|
||||
dtVec2b,
|
||||
dtVec3b,
|
||||
dtVec4b:Result:=True;
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataTypeHelper.isVector:Boolean;
|
||||
begin
|
||||
Case Self of
|
||||
dtVec2b,
|
||||
dtVec3b,
|
||||
dtVec4b,
|
||||
|
||||
dtStruct2u,
|
||||
|
||||
dtVec2u8,
|
||||
dtVec4u8,
|
||||
|
||||
dtVec2i8,
|
||||
dtVec4i8,
|
||||
|
||||
dtVec2u16,
|
||||
dtVec4u16,
|
||||
|
||||
dtVec2i16,
|
||||
dtVec4i16,
|
||||
|
||||
dtVec2u,
|
||||
dtVec3u,
|
||||
dtVec4u,
|
||||
|
||||
dtVec2i,
|
||||
dtVec3i,
|
||||
dtVec4i,
|
||||
|
||||
dtVec2h,
|
||||
dtVec4h,
|
||||
|
||||
dtVec2f,
|
||||
dtVec3f,
|
||||
dtVec4f:
|
||||
Result:=True;
|
||||
|
||||
else
|
||||
Result:=False;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataTypeHelper.isScalar:Boolean;
|
||||
begin
|
||||
Result:=not isVector;
|
||||
end;
|
||||
|
||||
function TsrDataTypeHelper.Child:TsrDataType;
|
||||
begin
|
||||
Case Self 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;
|
||||
|
||||
dtVec2h,
|
||||
dtVec4h:Result:=dtHalf16;
|
||||
|
||||
dtVec2f,
|
||||
dtVec3f,
|
||||
dtVec4f:Result:=dtFloat32;
|
||||
else
|
||||
Result:=dtUnknow;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataTypeHelper.Count:Byte;
|
||||
begin
|
||||
Case Self of
|
||||
dtVec2b,
|
||||
dtVec2u8,
|
||||
dtVec2i8,
|
||||
dtVec2u16,
|
||||
dtVec2i16,
|
||||
dtVec2u,
|
||||
dtVec2i,
|
||||
dtVec2h,
|
||||
dtVec2f,
|
||||
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 TsrDataTypeHelper.Sign:Byte;
|
||||
begin
|
||||
Case Self of
|
||||
dtInt8,
|
||||
dtInt16,
|
||||
dtInt32,
|
||||
dtInt64,
|
||||
|
||||
dtHalf16,
|
||||
dtFloat32,
|
||||
dtFloat64,
|
||||
dtVec2h,
|
||||
dtVec4h,
|
||||
dtVec2f,
|
||||
dtVec3f,
|
||||
dtVec4f:Result:=1;
|
||||
|
||||
else
|
||||
Result:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataTypeHelper.BitSize:Byte;
|
||||
begin
|
||||
Case Self of
|
||||
dtInt8,
|
||||
dtUint8:Result:=8;
|
||||
|
||||
dtHalf16,
|
||||
dtInt16,
|
||||
dtUint16,
|
||||
dtVec2u8,
|
||||
dtVec2i8:Result:=16;
|
||||
|
||||
dtUnknow,
|
||||
dtBool, //for typecast
|
||||
dtFloat32,
|
||||
dtInt32,
|
||||
dtUint32,
|
||||
dtVec4u8,
|
||||
dtVec4i8,
|
||||
dtVec2u16,
|
||||
dtVec2i16,
|
||||
dtVec2h:Result:=32;
|
||||
|
||||
dtFloat64,
|
||||
dtInt64,
|
||||
dtUint64,
|
||||
dtVec4u16,
|
||||
dtVec4i16,
|
||||
dtVec2f,
|
||||
dtVec4h,
|
||||
dtStruct2u:Result:=64;
|
||||
|
||||
dtVec3u,
|
||||
dtVec3i,
|
||||
dtVec3f:Result:=96;
|
||||
|
||||
dtVec4u,
|
||||
dtVec4i,
|
||||
dtVec4f:Result:=128;
|
||||
|
||||
else
|
||||
Result:=0;
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataTypeHelper.High:QWORD;
|
||||
var
|
||||
s:Byte;
|
||||
begin
|
||||
Result:=0;
|
||||
if (Self=dtBool) then Exit(1);
|
||||
s:=BitSize;
|
||||
Case s of
|
||||
8:Result:=System.High(Byte);
|
||||
16:Result:=System.High(Word);
|
||||
32:Result:=System.High(DWord);
|
||||
64:Result:=System.High(QWord);
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TsrDataTypeHelper.AsVector(_count:Byte):TsrDataType;
|
||||
begin
|
||||
Result:=dtUnknow;
|
||||
if (_count<=1) then Exit(Self);
|
||||
Case Self 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 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 TryBitcastType(rtype1,rtype2:TsrDataType):Boolean;
|
||||
var
|
||||
s,d:Byte;
|
||||
begin
|
||||
s:=rtype1.BitSize;
|
||||
d:=rtype2.BitSize;
|
||||
Result:=(s<>0) and (d<>0) and (s=d);
|
||||
end;
|
||||
|
||||
function is_unprep_type(old,new:TsrDataType;weak:Boolean):Boolean;
|
||||
begin
|
||||
Result:=False;
|
||||
if (new<>dtUnknow) and (old<>new) then
|
||||
begin
|
||||
Case old of
|
||||
dtUnknow:Result:=True;
|
||||
dtBool :Result:=weak;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
1336
spirv/srTypes.pas
1336
spirv/srTypes.pas
File diff suppressed because it is too large
Load Diff
|
@ -5,77 +5,245 @@ unit srUniform;
|
|||
interface
|
||||
|
||||
uses
|
||||
spirv,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srLayout,
|
||||
srReg,
|
||||
srVariable,
|
||||
srDecorate;
|
||||
sysutils,
|
||||
spirv,
|
||||
ginodes,
|
||||
srNode,
|
||||
srRefId,
|
||||
srType,
|
||||
srTypes,
|
||||
srLayout,
|
||||
srVariable,
|
||||
srCapability,
|
||||
srDecorate,
|
||||
srConfig;
|
||||
|
||||
type
|
||||
ntRegUniform=class(TsrNodeVmt)
|
||||
class function Down (node:PsrNode):Pointer; override;
|
||||
class Procedure SetWriter (node,w,line:PsrNode); override;
|
||||
class Procedure ResetWriter (node,w:PsrNode); override;
|
||||
class Function pwrite_count(node:PsrNode):PDWORD; override;
|
||||
class function GetPrintName(node:PsrNode):RawByteString; override;
|
||||
class function GetRef (node:PsrNode):Pointer; override;
|
||||
end;
|
||||
|
||||
ntUniform=class(ntDescriptor)
|
||||
class Function pwrite_count (node:PsrNode):PDWORD; override;
|
||||
class function GetStorageName(node:PsrNode):RawByteString; override;
|
||||
end;
|
||||
|
||||
String2=String[2];
|
||||
|
||||
PsrRegUniform=^TsrRegUniform;
|
||||
TsrRegUniform=packed object(TsrNode)
|
||||
private
|
||||
fwrite_count:DWORD;
|
||||
ID:TsrRefId; //post id
|
||||
//
|
||||
FWriter:PsrNode;
|
||||
FVar:PsrVariable;
|
||||
Procedure SetWriter(t:PsrNode);
|
||||
public
|
||||
property pLine:PsrNode read FWriter;
|
||||
Procedure Init(pVar:PsrVariable); inline;
|
||||
function GetPrintName:RawByteString;
|
||||
end;
|
||||
|
||||
PsrUniform=^TsrUniform;
|
||||
TsrUniform=object(TsrDescriptor)
|
||||
pLeft,pRight:PsrUniform;
|
||||
//----
|
||||
|
||||
key:packed record
|
||||
private
|
||||
pLeft,pRight:PsrUniform;
|
||||
//----
|
||||
pLayout:PsrDataLayout;
|
||||
pType:PsrType;
|
||||
end;
|
||||
|
||||
pReg:PsrRegNode;
|
||||
|
||||
function c(n1,n2:PsrUniform):Integer; static;
|
||||
function GetTypeChar:String2;
|
||||
function GetString:RawByteString;
|
||||
//
|
||||
fwrite_count:DWORD;
|
||||
//
|
||||
FReg:TsrRegUniform;
|
||||
function c(n1,n2:PsrUniform):Integer; static;
|
||||
public
|
||||
Procedure Init; inline;
|
||||
function pReg:PsrRegUniform; inline;
|
||||
function GetStorageName:RawByteString;
|
||||
function GetTypeChar:String2;
|
||||
function GetString:RawByteString;
|
||||
end;
|
||||
|
||||
PsrUniformList=^TsrUniformList;
|
||||
TsrUniformList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrUniform,TsrUniform>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
FEmit:TCustomEmit;
|
||||
FNTree:TNodeFetch;
|
||||
procedure Init(cb:TfnAlloc);
|
||||
procedure Init(Emit:TCustomEmit); inline;
|
||||
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);
|
||||
procedure AllocBinding(Var FBinding:Integer);
|
||||
procedure AllocSourceExtension;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
class function ntRegUniform.Down(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=PsrRegUniform(node)^.FVar;
|
||||
end;
|
||||
|
||||
class Procedure ntRegUniform.SetWriter(node,w,line:PsrNode);
|
||||
begin
|
||||
With PsrRegUniform(node)^ do
|
||||
begin
|
||||
SetWriter(w);
|
||||
end;
|
||||
end;
|
||||
|
||||
class Procedure ntRegUniform.ResetWriter(node,w:PsrNode);
|
||||
begin
|
||||
With PsrRegUniform(node)^ do
|
||||
if (FWriter=w) then
|
||||
begin
|
||||
SetWriter(nil);
|
||||
end;
|
||||
end;
|
||||
|
||||
class Function ntRegUniform.pwrite_count(node:PsrNode):PDWORD;
|
||||
begin
|
||||
Result:=@PsrRegUniform(node)^.fwrite_count;
|
||||
end;
|
||||
|
||||
class function ntRegUniform.GetPrintName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrRegUniform(node)^.GetPrintName;
|
||||
end;
|
||||
|
||||
class function ntRegUniform.GetRef(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=@PsrRegUniform(node)^.ID;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
class Function ntUniform.pwrite_count(node:PsrNode):PDWORD;
|
||||
begin
|
||||
Result:=@PsrUniform(node)^.fwrite_count;
|
||||
end;
|
||||
|
||||
class function ntUniform.GetStorageName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrUniform(node)^.GetStorageName;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
Procedure TsrRegUniform.Init(pVar:PsrVariable); inline;
|
||||
begin
|
||||
fntype:=ntRegUniform;
|
||||
FVar:=pVar;
|
||||
end;
|
||||
|
||||
Procedure TsrRegUniform.SetWriter(t:PsrNode);
|
||||
begin
|
||||
if (FWriter=t) then Exit;
|
||||
if isUsed then
|
||||
begin
|
||||
t^.mark_read (@Self);
|
||||
FWriter^.mark_unread(@Self);
|
||||
end;
|
||||
FWriter:=t;
|
||||
end;
|
||||
|
||||
function TsrRegUniform.GetPrintName:RawByteString;
|
||||
begin
|
||||
Result:=FVar^.GetStorageName;
|
||||
if (Result<>'') then
|
||||
begin
|
||||
Result:='r_'+Result;
|
||||
end else
|
||||
begin
|
||||
Assert(ID.Alloc);
|
||||
Result:='r'+IntToStr(ID.ID);
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
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);
|
||||
Result:=Integer(n1^.pLayout>n2^.pLayout)-Integer(n1^.pLayout<n2^.pLayout);
|
||||
if (Result<>0) then Exit;
|
||||
//second pType
|
||||
Result:=Integer(n1^.key.pType>n2^.key.pType)-Integer(n1^.key.pType<n2^.key.pType);
|
||||
Result:=Integer(n1^.FType>n2^.FType)-Integer(n1^.FType<n2^.FType);
|
||||
end;
|
||||
|
||||
function TsrUniform.GetTypeChar:String2;
|
||||
Procedure TsrUniform.Init; inline;
|
||||
begin
|
||||
fntype :=ntUniform;
|
||||
FStorage:=StorageClass.UniformConstant;
|
||||
FBinding:=-1;
|
||||
end;
|
||||
|
||||
function TsrUniform.pReg:PsrRegUniform; inline;
|
||||
begin
|
||||
Result:=@FReg;
|
||||
end;
|
||||
|
||||
function TsrUniform.GetStorageName:RawByteString;
|
||||
var
|
||||
image_info:TsrTypeImageInfo;
|
||||
begin
|
||||
Result:='';
|
||||
if (key.pType<>nil) then
|
||||
With key.pType^.key do
|
||||
Case key.pType^.dtype of
|
||||
if (FType<>nil) then
|
||||
Case FType^.dtype of
|
||||
dtTypeImage:
|
||||
begin
|
||||
if (ext.image.Dim=Dim.Buffer) then
|
||||
image_info:=FType^.image_info;
|
||||
|
||||
if (image_info.Dim=Dim.Buffer) then
|
||||
begin
|
||||
Case ext.image.Sampled of
|
||||
Case image_info.Sampled of
|
||||
1:Result:='uTex'+IntToStr(FBinding);
|
||||
2:Result:='sTex'+IntToStr(FBinding);
|
||||
else Result:='rTex'+IntToStr(FBinding);
|
||||
end;
|
||||
end else
|
||||
begin
|
||||
Case image_info.Sampled of
|
||||
1:Result:='uImg'+IntToStr(FBinding);
|
||||
2:Result:='sImg'+IntToStr(FBinding);
|
||||
else Result:='rImg'+IntToStr(FBinding);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
dtTypeSampler:Result:='uSmp'+IntToStr(FBinding);
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
function TsrUniform.GetTypeChar:String2;
|
||||
var
|
||||
image_info:TsrTypeImageInfo;
|
||||
begin
|
||||
Result:='';
|
||||
if (FType<>nil) then
|
||||
Case FType^.dtype of
|
||||
dtTypeImage:
|
||||
begin
|
||||
image_info:=FType^.image_info;
|
||||
|
||||
if (image_info.Dim=Dim.Buffer) then
|
||||
begin
|
||||
Case image_info.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
|
||||
Case image_info.Sampled of
|
||||
1:Result:='UI'; //VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
|
||||
2:Result:='SI'; //VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
|
||||
else Result:='RI'; //runtime image
|
||||
|
@ -92,18 +260,18 @@ var
|
|||
PID:DWORD;
|
||||
begin
|
||||
PID:=0;
|
||||
if (key.pLayout<>nil) then
|
||||
if (pLayout<>nil) then
|
||||
begin
|
||||
PID:=key.pLayout^.FID;
|
||||
PID:=pLayout^.FID;
|
||||
end;
|
||||
Result:=GetTypeChar+
|
||||
';PID='+HexStr(PID,8)+
|
||||
';BND='+HexStr(FBinding,8);
|
||||
end;
|
||||
|
||||
procedure TsrUniformList.Init(cb:TfnAlloc);
|
||||
procedure TsrUniformList.Init(Emit:TCustomEmit); inline;
|
||||
begin
|
||||
Alloc:=cb;
|
||||
FEmit:=Emit;
|
||||
end;
|
||||
|
||||
function TsrUniformList.Fetch(s:PsrDataLayout;t:PsrType):PsrUniform;
|
||||
|
@ -111,19 +279,19 @@ var
|
|||
node:TsrUniform;
|
||||
begin
|
||||
node:=Default(TsrUniform);
|
||||
node.key.pLayout:=s;
|
||||
node.key.pType:=t;
|
||||
node.FStorage:=StorageClass.UniformConstant;
|
||||
node.FBinding:=-1;
|
||||
node.Init;
|
||||
node.pLayout:=s;
|
||||
node.FType :=t;
|
||||
Result:=FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrUniform));
|
||||
Result:=FEmit.Alloc(SizeOf(TsrUniform));
|
||||
Move(node,Result^,SizeOf(TsrUniform));
|
||||
//
|
||||
Result^.InitVar(FEmit);
|
||||
Result^.FReg.Init(Result^.FVar);
|
||||
//
|
||||
FNTree.Insert(Result);
|
||||
end else
|
||||
begin
|
||||
t^.mark_unread;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -137,43 +305,144 @@ begin
|
|||
Result:=FNTree.Next(node);
|
||||
end;
|
||||
|
||||
procedure TsrUniformList.AllocBinding(Var FBinding:Integer;Decorates:PsrDecorateList);
|
||||
procedure TsrUniformList.AllocBinding(Var FBinding:Integer);
|
||||
var
|
||||
pConfig:PsrConfig;
|
||||
pDecorateList:PsrDecorateList;
|
||||
pCapabilityList:PsrCapabilityList;
|
||||
//
|
||||
node:PsrUniform;
|
||||
pVar:PsrVariable;
|
||||
//
|
||||
FType:PsrType;
|
||||
image_info:TsrTypeImageInfo;
|
||||
begin
|
||||
if (Decorates=nil) then Exit;
|
||||
pConfig :=FEmit.GetConfig;
|
||||
pDecorateList :=FEmit.GetDecorateList;
|
||||
pCapabilityList:=FEmit.GetCapabilityList;
|
||||
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
if (pVar<>nil) and node^.IsUsed and (node^.FBinding=-1) then
|
||||
begin
|
||||
if (node^.FBinding=-1) then //alloc
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.Binding,FBinding);
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.DescriptorSet,pConfig^.DescriptorSet);
|
||||
|
||||
node^.FBinding:=FBinding;
|
||||
Inc(FBinding);
|
||||
|
||||
FType:=node^.pType;
|
||||
if (FType<>nil) then
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Binding,FBinding);
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.DescriptorSet,Decorates^.FDescriptorSet);
|
||||
node^.FBinding:=FBinding;
|
||||
Inc(FBinding);
|
||||
Case FType^.dtype of
|
||||
dtTypeImage:
|
||||
begin
|
||||
image_info:=FType^.image_info;
|
||||
|
||||
if (image_info.Sampled=2) then //storage image
|
||||
begin
|
||||
if (node^.FReg.read_count=0) then
|
||||
begin
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.NonReadable,0);
|
||||
end;
|
||||
if (node^.FReg.write_count=0) then
|
||||
begin
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.NonWritable,0);
|
||||
end;
|
||||
end;
|
||||
|
||||
Case image_info.Dim of
|
||||
Dim.Dim1D:
|
||||
Case image_info.Sampled of
|
||||
1:pCapabilityList^.Add(Capability.Sampled1D); //sampling
|
||||
2:pCapabilityList^.Add(Capability.Image1D); //read/write
|
||||
else;
|
||||
end;
|
||||
Dim.Buffer:
|
||||
Case image_info.Sampled of
|
||||
1:pCapabilityList^.Add(Capability.SampledBuffer); //sampling
|
||||
2:pCapabilityList^.Add(Capability.ImageBuffer); //read/write
|
||||
else;
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
|
||||
if (image_info.Sampled=2) and
|
||||
(image_info.Arrayed=1) then
|
||||
begin
|
||||
pCapabilityList^.Add(Capability.ImageMSArray);
|
||||
end;
|
||||
|
||||
Case image_info.Format of
|
||||
|
||||
ImageFormat.Unknown:
|
||||
begin
|
||||
if (node^.FReg.read_count<>0) then
|
||||
begin
|
||||
pCapabilityList^.Add(Capability.StorageImageWriteWithoutFormat);
|
||||
end;
|
||||
if (node^.FReg.write_count<>0) then
|
||||
begin
|
||||
pCapabilityList^.Add(Capability.StorageImageWriteWithoutFormat);
|
||||
end;
|
||||
end;
|
||||
|
||||
ImageFormat.Rg32f ,
|
||||
ImageFormat.Rg16f ,
|
||||
ImageFormat.R11fG11fB10f,
|
||||
ImageFormat.R16f ,
|
||||
ImageFormat.Rgba16 ,
|
||||
ImageFormat.Rgb10A2 ,
|
||||
ImageFormat.Rg16 ,
|
||||
ImageFormat.Rg8 ,
|
||||
ImageFormat.R16 ,
|
||||
ImageFormat.R8 ,
|
||||
ImageFormat.Rgba16Snorm ,
|
||||
ImageFormat.Rg16Snorm ,
|
||||
ImageFormat.Rg8Snorm ,
|
||||
ImageFormat.R16Snorm ,
|
||||
ImageFormat.R8Snorm ,
|
||||
ImageFormat.Rg32i ,
|
||||
ImageFormat.Rg16i ,
|
||||
ImageFormat.Rg8i ,
|
||||
ImageFormat.R16i ,
|
||||
ImageFormat.R8i ,
|
||||
ImageFormat.Rgb10a2ui ,
|
||||
ImageFormat.Rg32ui ,
|
||||
ImageFormat.Rg16ui ,
|
||||
ImageFormat.Rg8ui ,
|
||||
ImageFormat.R16ui ,
|
||||
ImageFormat.R8ui :pCapabilityList^.Add(Capability.StorageImageExtendedFormats);
|
||||
|
||||
else;
|
||||
end;
|
||||
|
||||
end;
|
||||
else;
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrUniformList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
procedure TsrUniformList.AllocSourceExtension;
|
||||
var
|
||||
pDebugInfoList:PsrDebugInfoList;
|
||||
node:PsrUniform;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (FDebugInfo=nil) then Exit;
|
||||
pDebugInfoList:=FEmit.GetDebugInfoList;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
if (pVar<>nil) and node^.IsUsed then
|
||||
begin
|
||||
FDebugInfo^.emit_source_extension(node^.GetString);
|
||||
pDebugInfoList^.OpSourceExtension(node^.GetString);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
|
|
|
@ -5,9 +5,8 @@ unit srVBufInfo;
|
|||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
ps4_pssl,
|
||||
srTypes,
|
||||
srType,
|
||||
srLayout,
|
||||
spirv;
|
||||
|
||||
|
|
|
@ -5,112 +5,235 @@ unit srVariable;
|
|||
interface
|
||||
|
||||
uses
|
||||
spirv,
|
||||
srNodes,
|
||||
srTypes,
|
||||
srRefId;
|
||||
sysutils,
|
||||
ginodes,
|
||||
srNode,
|
||||
srTypes,
|
||||
srRefId,
|
||||
srDecorate;
|
||||
|
||||
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;
|
||||
ntVariable=class(TsrNodeVmt)
|
||||
class Procedure zero_read (node:PsrNode); override;
|
||||
class Procedure zero_unread (node:PsrNode); override;
|
||||
class Function pwrite_count (node:PsrNode):PDWORD; override;
|
||||
class Function GetStorageClass(node:PsrNode):DWORD; override;
|
||||
class function GetStorageName (node:PsrNode):RawByteString; override;
|
||||
class function Down (node:PsrNode):Pointer; override;
|
||||
class function Next (node:PsrNode):Pointer; override;
|
||||
class function Prev (node:PsrNode):Pointer; override;
|
||||
class Procedure PrepType (node:PPrepTypeNode); override;
|
||||
class Function GetPtype (node:PsrNode):PsrNode; override;
|
||||
class function GetPrintName (node:PsrNode):RawByteString; override;
|
||||
class function GetRef (node:PsrNode):Pointer; override;
|
||||
end;
|
||||
|
||||
TsrVariableList=specialize TNodeList<PsrVariable>;
|
||||
PsrVariable=^TsrVariable;
|
||||
TsrVariable=packed object(TsrNode)
|
||||
private
|
||||
pPrev,pNext:PsrVariable;
|
||||
//
|
||||
fwrite_count:DWORD;
|
||||
ID:TsrRefId; //post id
|
||||
FType:PsrType;
|
||||
FSource:PsrNode; //ntInput,ntVertLayout,ntFragLayout,ntUniform,ntBuffer,ntOutput
|
||||
procedure SetType(t:PsrType);
|
||||
procedure SetSource(t:PsrNode);
|
||||
public
|
||||
property pSource:PsrNode read FSource write SetSource;
|
||||
procedure UpdateType(Emit:TCustomEmit);
|
||||
Procedure Init; inline;
|
||||
function GetPrintName:RawByteString;
|
||||
end;
|
||||
|
||||
PsrVariableList=^TsrVariableList;
|
||||
TsrVariableList=object
|
||||
type
|
||||
TNodeList=specialize TNodeList<PsrVariable>;
|
||||
var
|
||||
FEmit:TCustomEmit;
|
||||
FList:TNodeList;
|
||||
procedure Init(Emit:TCustomEmit); inline;
|
||||
function Fetch:PsrVariable;
|
||||
function First:PsrVariable; inline;
|
||||
procedure AllocName;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
srLayout,
|
||||
srVertLayout,
|
||||
srFragLayout,
|
||||
srInput,
|
||||
srOutput;
|
||||
|
||||
Procedure TsrVariable.mark_read;
|
||||
class Procedure ntVariable.zero_read(node:PsrNode);
|
||||
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');
|
||||
With PsrVariable(node)^ do
|
||||
begin
|
||||
FType^.mark_read(@Self);
|
||||
end;
|
||||
end;
|
||||
|
||||
Procedure TsrVariable.Clear;
|
||||
class Procedure ntVariable.zero_unread(node:PsrNode);
|
||||
begin
|
||||
if (pType<>nil) then
|
||||
With PsrVariable(node)^ do
|
||||
begin
|
||||
pType^.mark_unread;
|
||||
pType:=nil;
|
||||
FType^.mark_unread(@Self);
|
||||
end;
|
||||
if (pSource.pData<>nil) then
|
||||
end;
|
||||
|
||||
class Function ntVariable.pwrite_count(node:PsrNode):PDWORD;
|
||||
begin
|
||||
Result:=@PsrVariable(node)^.fwrite_count;
|
||||
end;
|
||||
|
||||
class Function ntVariable.GetStorageClass(node:PsrNode):DWORD;
|
||||
begin
|
||||
Result:=inherited;
|
||||
With PsrVariable(node)^ do
|
||||
if (FSource<>nil) then
|
||||
if (FSource^.ntype<>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;
|
||||
Result:=FSource^.ntype.GetStorageClass(FSource);
|
||||
end;
|
||||
end;
|
||||
|
||||
class function ntVariable.GetStorageName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=inherited;
|
||||
With PsrVariable(node)^ do
|
||||
if (FSource<>nil) then
|
||||
if (FSource^.ntype<>nil) then
|
||||
begin
|
||||
Result:=FSource^.ntype.GetStorageName(FSource);
|
||||
end;
|
||||
end;
|
||||
|
||||
class function ntVariable.Down(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=PsrVariable(node)^.FSource;
|
||||
end;
|
||||
|
||||
class function ntVariable.Next(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=PsrVariable(node)^.pNext;
|
||||
end;
|
||||
|
||||
class function ntVariable.Prev(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=PsrVariable(node)^.pPrev;
|
||||
end;
|
||||
|
||||
class Procedure ntVariable.PrepType(node:PPrepTypeNode);
|
||||
begin
|
||||
node^.dnode:=PsrVariable(node^.dnode)^.FSource;
|
||||
end;
|
||||
|
||||
class Function ntVariable.GetPtype(node:PsrNode):PsrNode;
|
||||
begin
|
||||
Result:=PsrVariable(node)^.FType;
|
||||
end;
|
||||
|
||||
class function ntVariable.GetPrintName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrVariable(node)^.GetPrintName;
|
||||
end;
|
||||
|
||||
class function ntVariable.GetRef(node:PsrNode):Pointer;
|
||||
begin
|
||||
Result:=@PsrVariable(node)^.ID;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
Procedure TsrVariable.Init; inline;
|
||||
begin
|
||||
fntype:=ntVariable;
|
||||
end;
|
||||
|
||||
procedure TsrVariable.SetType(t:PsrType);
|
||||
begin
|
||||
if (FType=t) then Exit;
|
||||
if IsUsed then
|
||||
begin
|
||||
t^.mark_read (@Self);
|
||||
FType^.mark_unread(@Self);
|
||||
end;
|
||||
FType:=t;
|
||||
end;
|
||||
|
||||
procedure TsrVariable.UpdateType(Emit:TCustomEmit);
|
||||
var
|
||||
_Type:PsrType;
|
||||
pTypeList:PsrTypeList;
|
||||
begin
|
||||
if (@Self=nil) then Exit;
|
||||
_Type:=FSource^.pType;
|
||||
if (_Type=nil) then
|
||||
begin
|
||||
SetType(nil);
|
||||
end else
|
||||
begin
|
||||
pTypeList:=Emit.GetTypeList;
|
||||
_Type:=pTypeList^.FetchPointer(_Type,FSource^.GetStorageClass);
|
||||
SetType(_Type);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrVariable.SetSource(t:PsrNode);
|
||||
begin
|
||||
if (FSource=t) then Exit;
|
||||
if IsUsed then
|
||||
begin
|
||||
t^.mark_read (@Self);
|
||||
FSource^.mark_unread(@Self);
|
||||
end;
|
||||
FSource:=t;
|
||||
end;
|
||||
|
||||
function TsrVariable.GetPrintName:RawByteString;
|
||||
begin
|
||||
Result:=GetStorageName;
|
||||
if (Result='') then
|
||||
begin
|
||||
Assert(ID.Alloc);
|
||||
Result:='v'+IntToStr(ID.ID);
|
||||
end;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
procedure TsrVariableList.Init(Emit:TCustomEmit); inline;
|
||||
begin
|
||||
FEmit:=Emit;
|
||||
end;
|
||||
|
||||
function TsrVariableList.Fetch:PsrVariable;
|
||||
begin
|
||||
Result:=FEmit.Alloc(SizeOf(TsrVariable));
|
||||
Result^.Init;
|
||||
FList.Push_tail(Result);
|
||||
end;
|
||||
|
||||
function TsrVariableList.First:PsrVariable; inline;
|
||||
begin
|
||||
Result:=FList.pHead;
|
||||
end;
|
||||
|
||||
procedure TsrVariableList.AllocName;
|
||||
var
|
||||
FDebugInfo:PsrDebugInfoList;
|
||||
node:PsrVariable;
|
||||
n:RawByteString;
|
||||
begin
|
||||
FDebugInfo:=FEmit.GetDebugInfoList;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
if (node^.pType<>nil) then
|
||||
begin
|
||||
n:=node^.GetStorageName;
|
||||
if (n<>'') then
|
||||
begin
|
||||
FDebugInfo^.OpName(node,n);
|
||||
end;
|
||||
end;
|
||||
node:=node^.Next;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
|
|
@ -5,48 +5,72 @@ unit srVertLayout;
|
|||
interface
|
||||
|
||||
uses
|
||||
sysutils,
|
||||
spirv,
|
||||
srNodes,
|
||||
srReg,
|
||||
srOp,
|
||||
srVariable,
|
||||
srLayout,
|
||||
srDecorate;
|
||||
sysutils,
|
||||
spirv,
|
||||
ginodes,
|
||||
srNode,
|
||||
srType,
|
||||
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;
|
||||
ntVertLayout=class(ntDescriptor)
|
||||
class function GetStorageName(node:PsrNode):RawByteString; override;
|
||||
end;
|
||||
|
||||
PsrVertLayout=^TsrVertLayout;
|
||||
TsrVertLayout=object(TsrDescriptor)
|
||||
private
|
||||
pLeft,pRight:PsrVertLayout;
|
||||
//----
|
||||
pLayout:PsrDataLayout;
|
||||
function c(n1,n2:PsrVertLayout):Integer; static;
|
||||
public
|
||||
pReg:PsrRegNode;
|
||||
procedure Init(p:PsrDataLayout); inline;
|
||||
function GetString:RawByteString;
|
||||
function GetStorageName:RawByteString;
|
||||
end;
|
||||
|
||||
PsrVertLayoutList=^TsrVertLayoutList;
|
||||
TsrVertLayoutList=object
|
||||
type
|
||||
TNodeFetch=specialize TNodeFetch<PsrVertLayout,TsrVertLayout>;
|
||||
var
|
||||
Alloc:TfnAlloc;
|
||||
FEmit:TCustomEmit;
|
||||
FNTree:TNodeFetch;
|
||||
procedure Init(cb:TfnAlloc);
|
||||
function Fetch(p:PsrDataLayout):PsrVertLayout;
|
||||
procedure Init(Emit:TCustomEmit); inline;
|
||||
function Fetch(p:PsrDataLayout;rtype:TsrDataType):PsrVertLayout;
|
||||
Function First:PsrVertLayout;
|
||||
Function Next(node:PsrVertLayout):PsrVertLayout;
|
||||
procedure AllocBinding(Decorates:PsrDecorateList);
|
||||
procedure AllocBinding;
|
||||
procedure AllocEntryPoint(EntryPoint:PSpirvOp);
|
||||
procedure AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
procedure AllocSourceExtension;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
class function ntVertLayout.GetStorageName(node:PsrNode):RawByteString;
|
||||
begin
|
||||
Result:=PsrVertLayout(node)^.GetStorageName;
|
||||
end;
|
||||
|
||||
//
|
||||
|
||||
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;
|
||||
|
||||
procedure TsrVertLayout.Init(p:PsrDataLayout); inline;
|
||||
begin
|
||||
fntype :=ntVertLayout;
|
||||
FStorage:=StorageClass.Input;
|
||||
FBinding:=-1;
|
||||
pLayout :=p;
|
||||
end;
|
||||
|
||||
function TsrVertLayout.GetString:RawByteString;
|
||||
|
@ -62,29 +86,31 @@ begin
|
|||
';BND='+HexStr(FBinding,8);
|
||||
end;
|
||||
|
||||
function TsrVertLayout.GetName:RawByteString;
|
||||
function TsrVertLayout.GetStorageName:RawByteString;
|
||||
begin
|
||||
Result:='atParam'+IntToStr(FBinding);
|
||||
end;
|
||||
|
||||
procedure TsrVertLayoutList.Init(cb:TfnAlloc);
|
||||
procedure TsrVertLayoutList.Init(Emit:TCustomEmit); inline;
|
||||
begin
|
||||
Alloc:=cb;
|
||||
FEmit:=Emit;
|
||||
end;
|
||||
|
||||
function TsrVertLayoutList.Fetch(p:PsrDataLayout):PsrVertLayout;
|
||||
function TsrVertLayoutList.Fetch(p:PsrDataLayout;rtype:TsrDataType):PsrVertLayout;
|
||||
var
|
||||
node:TsrVertLayout;
|
||||
begin
|
||||
node:=Default(TsrVertLayout);
|
||||
node.pLayout:=p;
|
||||
node.Init(p);
|
||||
Result:=FNTree.Find(@node);
|
||||
if (Result=nil) then
|
||||
begin
|
||||
Result:=Alloc(SizeOf(TsrVertLayout));
|
||||
Result^.pLayout:=p;
|
||||
Result^.FStorage:=StorageClass.Input;
|
||||
Result^.FBinding:=-1;
|
||||
Result:=FEmit.Alloc(SizeOf(TsrVertLayout));
|
||||
Move(node,Result^,SizeOf(TsrVertLayout));
|
||||
//
|
||||
Result^.InitType(rtype,FEmit);
|
||||
Result^.InitVar(FEmit);
|
||||
//
|
||||
FNTree.Insert(Result);
|
||||
end;
|
||||
end;
|
||||
|
@ -99,26 +125,24 @@ begin
|
|||
Result:=FNTree.Next(node);
|
||||
end;
|
||||
|
||||
procedure TsrVertLayoutList.AllocBinding(Decorates:PsrDecorateList);
|
||||
procedure TsrVertLayoutList.AllocBinding;
|
||||
var
|
||||
pDecorateList:PsrDecorateList;
|
||||
node:PsrVertLayout;
|
||||
pVar:PsrVariable;
|
||||
FBinding:Integer;
|
||||
begin
|
||||
if (Decorates=nil) then Exit;
|
||||
pDecorateList:=FEmit.GetDecorateList;
|
||||
FBinding:=0;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
if (pVar<>nil) and node^.IsUsed and (node^.FBinding=-1) then
|
||||
begin
|
||||
if (node^.FBinding=-1) then //alloc
|
||||
begin
|
||||
Decorates^.emit_decorate(ntVar,pVar,Decoration.Location,FBinding);
|
||||
node^.FBinding:=FBinding;
|
||||
Inc(FBinding);
|
||||
end;
|
||||
pDecorateList^.OpDecorate(pVar,Decoration.Location,FBinding);
|
||||
node^.FBinding:=FBinding;
|
||||
Inc(FBinding);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
|
@ -134,27 +158,28 @@ begin
|
|||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
if (pVar<>nil) and node^.IsUsed then
|
||||
begin
|
||||
EntryPoint^.AddParam(ntVar,pVar);
|
||||
EntryPoint^.AddParam(pVar);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TsrVertLayoutList.AllocSourceExtension(FDebugInfo:PsrDebugInfoList);
|
||||
procedure TsrVertLayoutList.AllocSourceExtension;
|
||||
var
|
||||
FDebugInfo:PsrDebugInfoList;
|
||||
node:PsrVertLayout;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
if (FDebugInfo=nil) then Exit;
|
||||
FDebugInfo:=FEmit.GetDebugInfoList;
|
||||
node:=First;
|
||||
While (node<>nil) do
|
||||
begin
|
||||
pVar:=node^.pVar;
|
||||
if (pVar<>nil) then
|
||||
if (pVar<>nil) and node^.IsUsed then
|
||||
begin
|
||||
FDebugInfo^.emit_source_extension(node^.GetString);
|
||||
FDebugInfo^.OpSourceExtension(node^.GetString);
|
||||
end;
|
||||
node:=Next(node);
|
||||
end;
|
||||
|
|
|
@ -1,489 +0,0 @@
|
|||
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 is_load_from(dst:PspirvOp;r:PsrRegNode;v:PsrVariable):Boolean;
|
||||
var
|
||||
src:PspirvOp;
|
||||
pVar:PsrVariable;
|
||||
begin
|
||||
Result:=False;
|
||||
src:=r^.AsOp;
|
||||
if (src=nil) then Exit;
|
||||
if (src^.OpId<>Op.OpLoad) then Exit;
|
||||
pVar:=src^.pParam.pHead^.AsVar;
|
||||
if (pVar<>v) then Exit;
|
||||
Result:=IsGTFlow(src,dst);
|
||||
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^.SetReg(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 (src<>tmp) and (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
|
||||
|
||||
begin
|
||||
st_tmp.pHead:=tmp^.pWriter.pData;
|
||||
Assert(st_tmp.pHead<>nil);
|
||||
|
||||
st.Move_from(st_tmp);
|
||||
|
||||
src^.mark_read;
|
||||
tmp^.SetReg(src);
|
||||
|
||||
//tmp^.pLine:=dst;
|
||||
//writeln;
|
||||
//PrepVolatile(pReg^.pLine,pReg);
|
||||
|
||||
node^.pReg:=nil;
|
||||
Continue;
|
||||
end;
|
||||
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,False);
|
||||
|
||||
{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
|
||||
node^.pReg:=nil;
|
||||
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.
|
||||
|
|
@ -21,6 +21,7 @@ uses
|
|||
|
||||
type
|
||||
TvResourceType=(
|
||||
vtRoot,
|
||||
vtBufPtr2,
|
||||
vtFunPtr2,
|
||||
vtVSharp4,
|
||||
|
@ -279,6 +280,7 @@ end;
|
|||
procedure TvShaderExt.OnDataLayout(P:PChar);
|
||||
begin
|
||||
Case P[1] of
|
||||
'R':AddDataLayout(vtRoot ,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
||||
'B':AddDataLayout(vtBufPtr2,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
||||
'F':AddDataLayout(vtFunPtr2,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
||||
'V':AddDataLayout(vtVSharp4,_get_hex_dword(@P[7]),_get_hex_dword(@P[$14]));
|
||||
|
@ -473,12 +475,15 @@ begin
|
|||
|
||||
pSharp:=pData;
|
||||
|
||||
if (Length(addr)>1) then
|
||||
For i:=High(addr)-1 downto 0 do
|
||||
For i:=High(addr) downto 0 do
|
||||
begin
|
||||
pData:=pData+addr[i].offset;
|
||||
|
||||
Case addr[i].rtype of
|
||||
vtRoot:
|
||||
begin
|
||||
pSharp:=pData;
|
||||
end;
|
||||
vtBufPtr2:
|
||||
begin
|
||||
pData:=Pointer(PPtrUint(pData)^ and (not 3));
|
||||
|
@ -895,6 +900,7 @@ begin
|
|||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
||||
Case b.addr[0].rtype of
|
||||
vtRoot,
|
||||
vtBufPtr2:
|
||||
begin
|
||||
a:=AlignShift(P,limits.minStorageBufferOffsetAlignment);
|
||||
|
@ -905,7 +911,8 @@ begin
|
|||
a:=AlignShift(Pointer(PVSharpResource4(P)^.base),limits.minStorageBufferOffsetAlignment);
|
||||
if (a<>b.offset) then FResult:=False;
|
||||
end;
|
||||
else;
|
||||
else
|
||||
Assert(false);
|
||||
end;
|
||||
|
||||
else;
|
||||
|
|
|
@ -14,6 +14,8 @@ uses
|
|||
ps4_gpu_regs,
|
||||
shader_dump,
|
||||
|
||||
ps4_program,
|
||||
|
||||
vDevice,
|
||||
|
||||
vShaderExt,
|
||||
|
@ -163,12 +165,39 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
Procedure DumpSpv(FStage:TvShaderStage;M:TMemoryStream);
|
||||
var
|
||||
hash:DWORD;
|
||||
F:THandle;
|
||||
fname:RawByteString;
|
||||
begin
|
||||
hash:=FastHash(M.Memory,M.Size);
|
||||
|
||||
case FStage of
|
||||
vShaderStagePs:fname:='_ps_';
|
||||
vShaderStageVs:fname:='_vs_';
|
||||
vShaderStageCs:fname:='_cs_';
|
||||
else
|
||||
Exit;
|
||||
end;
|
||||
|
||||
fname:='shader_dump\'+get_dev_progname+fname+HexStr(hash,8)+'.spv';
|
||||
|
||||
if FileExists(fname) then Exit;
|
||||
|
||||
CreateDir('shader_dump');
|
||||
|
||||
F:=FileCreate(fname);
|
||||
FileWrite(F,M.Memory^,M.Size);
|
||||
FileClose(F);
|
||||
end;
|
||||
|
||||
function ParseShader(FStage:TvShaderStage;pData:PDWORD;var GPU_REGS:TGPU_REGS):TMemoryStream;
|
||||
var
|
||||
SprvEmit:TSprvEmit;
|
||||
begin
|
||||
Result:=nil;
|
||||
SprvEmit:=Default(TSprvEmit);
|
||||
SprvEmit:=TSprvEmit.Create;
|
||||
|
||||
case FStage of
|
||||
vShaderStagePs :
|
||||
|
@ -191,37 +220,37 @@ begin
|
|||
Exit;
|
||||
end;
|
||||
|
||||
SprvEmit.FPrintAsm :=False;
|
||||
SprvEmit.FUseVertexInput:=True;
|
||||
SprvEmit.FUseTexelBuffer:=False;
|
||||
SprvEmit.FUseOutput16 :=storageInputOutput16;
|
||||
SprvEmit.Config.PrintAsm :=False;
|
||||
SprvEmit.Config.UseVertexInput:=True;
|
||||
SprvEmit.Config.UseTexelBuffer:=False;
|
||||
SprvEmit.Config.UseOutput16 :=storageInputOutput16;
|
||||
|
||||
SprvEmit.FBuffers.cfg.maxUniformBufferRange :=0; // $FFFF
|
||||
SprvEmit.FBuffers.cfg.PushConstantsOffset :=0; // 0
|
||||
SprvEmit.FBuffers.cfg.maxPushConstantsSize :=limits.maxPushConstantsSize; // 128
|
||||
SprvEmit.FBuffers.cfg.minStorageBufferOffsetAlignment:=limits.minStorageBufferOffsetAlignment; // $10
|
||||
SprvEmit.FBuffers.cfg.minUniformBufferOffsetAlignment:=limits.minUniformBufferOffsetAlignment; // $100
|
||||
SprvEmit.Config.maxUniformBufferRange :=0; // $FFFF
|
||||
SprvEmit.Config.PushConstantsOffset :=0; // 0
|
||||
SprvEmit.Config.maxPushConstantsSize :=limits.maxPushConstantsSize; // 128
|
||||
SprvEmit.Config.minStorageBufferOffsetAlignment:=limits.minStorageBufferOffsetAlignment; // $10
|
||||
SprvEmit.Config.minUniformBufferOffsetAlignment:=limits.minUniformBufferOffsetAlignment; // $100
|
||||
|
||||
SprvEmit.FBuffers.cfg.maxPushConstantsSize:=16*4;
|
||||
SprvEmit.FBuffers.cfg.maxPushConstantsSize:=12;
|
||||
//SprvEmit.FUseVertexInput:=False;
|
||||
SprvEmit.Config.maxPushConstantsSize:=16*4;
|
||||
SprvEmit.Config.maxPushConstantsSize:=12;
|
||||
//SprvEmit.Config.UseVertexInput:=False;
|
||||
|
||||
if (SprvEmit.Parse(pData)>1) then
|
||||
if (SprvEmit.ParseStage(pData)>1) then
|
||||
begin
|
||||
Writeln(StdErr,'Shader Parse Err');
|
||||
SprvEmit.FAllocator.Free;
|
||||
SprvEmit.Free;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
TSprvEmit_post(SprvEmit).Post;
|
||||
TSprvEmit_alloc(SprvEmit).Alloc;
|
||||
|
||||
//TSprvEmit_print(SprvEmit).Print;
|
||||
SprvEmit.PostStage;
|
||||
SprvEmit.AllocStage;
|
||||
|
||||
Result:=TMemoryStream.Create;
|
||||
TSprvEmit_bin(SprvEmit).SaveToStream(Result);
|
||||
SprvEmit.SaveToStream(Result);
|
||||
|
||||
SprvEmit.FAllocator.Free;
|
||||
SprvEmit.Free;
|
||||
|
||||
//DumpSpv(FStage,Result);
|
||||
end;
|
||||
|
||||
function _FetchShader(FStage:TvShaderStage;pData:PDWORD;FDescSetId:Integer;var GPU_REGS:TGPU_REGS):TvShaderExt;
|
||||
|
|
Loading…
Reference in New Issue