FPPS4/spirv/emit_alloc.pas

387 lines
7.6 KiB
Plaintext

unit emit_alloc;
{$mode objfpc}{$H+}
interface
uses
sysutils,
spirv,
srNode,
srInterface,
srType,
srTypes,
srConst,
srRefId,
srReg,
srLayout,
srVariable,
srInput,
srOutput,
srVertLayout,
srFragLayout,
srUniform,
srBuffer,
srDecorate,
srOp,
srOpUtils,
emit_fetch;
type
TSprvEmit_alloc=class(TEmitFetch)
procedure AllocSourceExtension;
procedure AllocStage;
procedure AllocSpirvID(P:PsrRefId);
procedure AllocBinding;
procedure AllocTypeBinding;
procedure AllocEntryPoint;
function AddExecutionMode(mode:PtrUint):TSpirvOp;
procedure AllocHeader;
procedure AllocOpListId(node:TspirvOp);
procedure AllocListId(node:TsrNode);
procedure AllocFuncId;
procedure AllocOpId(node:TSpirvOp);
procedure AllocOpBlock(pBlock:TsrOpBlock);
end;
implementation
procedure TSprvEmit_alloc.AllocSourceExtension;
var
i:Integer;
Writer:TseWriter;
begin
DataLayoutList.AllocSourceExtension2;
Writer:=Default(TseWriter);
Writer.pList:=GetDebugInfoList;
Writer.Header('-C');
if (FExecutionModel=ExecutionModel.Vertex) then
if (VGPR_COMP_CNT>=1) then
begin
Writer.IntOpt('VGPR_COMP_CNT' ,VGPR_COMP_CNT);
Writer.HexOpt('VGT_STEP_RATE_0' ,VGT_STEP_RATE_0);
if (VGPR_COMP_CNT>=2) then
begin
Writer.HexOpt('VGT_STEP_RATE_1',VGT_STEP_RATE_1);
end;
end;
if (FExecutionModel=ExecutionModel.Fragment) then
begin
Writer.HexOpt('DB_SHADER_CONTROL',DWORD(DB_SHADER_CONTROL));
//
if (PS_NUM_INTERP<>0) then
begin
Writer.IntOpt('PS_NUM_INTERP',PS_NUM_INTERP);
for i:=0 to PS_NUM_INTERP-1 do
begin
Writer.HexOpt('PS_INPUT_CNTL',DWORD(FPSInputCntl[i].DATA));
end;
end;
//
if (EXPORT_COUNT<>0) then
begin
Writer.IntOpt('EXPORT_COUNT',EXPORT_COUNT);
for i:=0 to EXPORT_COUNT-1 do
begin
Inc(Writer.deep);
//
Writer.Header('-EXPORT_COLOR');
//
Writer.IntOpt('FORMAT' ,FExportInfo[i].FORMAT);
Writer.IntOpt('NUMBER_TYPE',FExportInfo[i].NUMBER_TYPE);
Writer.IntOpt('COMP_SWAP' ,FExportInfo[i].COMP_SWAP);
//
Dec(Writer.deep);
end;
end;
end;
if (FExecutionModel=ExecutionModel.GLCompute) then
begin
Writer.HexOpt('CS_NUM_THREAD_X',CS_NUM_THREAD_X);
Writer.HexOpt('CS_NUM_THREAD_Y',CS_NUM_THREAD_Y);
Writer.HexOpt('CS_NUM_THREAD_Z',CS_NUM_THREAD_Z);
end;
end;
procedure TSprvEmit_alloc.AllocStage;
begin
AllocBinding;
BufferList.AllocTypeBinding;
AllocTypeBinding;
AllocHeader;
//Source Extension
AllocSourceExtension;
//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);
AllocFuncId;
end;
procedure TSprvEmit_alloc.AllocSpirvID(P:PsrRefId);
begin
RefIdAlloc.FetchSpirvID(P);
end;
procedure TSprvEmit_alloc.AllocBinding;
var
FBinding:Integer;
begin
InputList .AllocBinding;
OutputList.AllocBinding;
VertLayoutList.AllocBinding;
FragLayoutList.AllocBinding;
FBinding:=0;
UniformList.AllocBinding(FBinding);
BufferList .AllocBinding(FBinding);
end;
procedure TSprvEmit_alloc.AllocTypeBinding;
var
node:TsrType;
begin
node:=TypeList.First;
While (node<>nil) do
begin
case node.OpId of
Op.OpTypeArray,
Op.OpTypeRuntimeArray:
begin
if (node.array_stride<>0) then
begin
DecorateList.OpDecorate(node,Decoration.ArrayStride,node.array_stride);
end;
//
if (node.OpId=Op.OpTypeRuntimeArray) then
if (node.is_array_image) then
begin
AddCapability(Capability.RuntimeDescriptorArray);
HeaderList.SPV_EXT_descriptor_indexing;
end;
end;
Op.OpTypeFloat:
begin
case node.dtype.BitSize of
16:AddCapability(Capability.Float16);
64:AddCapability(Capability.Float64);
else;
end;
end;
Op.OpTypeInt:
begin
case node.dtype.BitSize of
8:AddCapability(Capability.Int8);
16:AddCapability(Capability.Int16);
64:AddCapability(Capability.Int64);
else;
end;
end;
else;
end;
node:=node.Next;
end;
end;
procedure TSprvEmit_alloc.AllocOpListId(node:TspirvOp);
begin
While (node<>nil) do
begin
AllocOpId(node);
node:=node.Next;
end;
end;
procedure TSprvEmit_alloc.AllocEntryPoint;
var
node:TSpirvOp;
begin
node:=HeaderList.AddSpirvOp(Op.OpEntryPoint);
node.AddLiteral(FExecutionModel,ExecutionModel.GetStr(FExecutionModel));
node.AddParam(Main);
node.AddString(Main.name);
InputList .AllocEntryPoint(node);
VertLayoutList.AllocEntryPoint(node);
FragLayoutList.AllocEntryPoint(node);
OutputList .AllocEntryPoint(node);
end;
function TSprvEmit_alloc.AddExecutionMode(mode:PtrUint):TSpirvOp;
begin
Result:=HeaderList.AddExecutionMode(Main,mode);
end;
procedure TSprvEmit_alloc.AllocHeader;
var
node:TSpirvOp;
begin
node:=HeaderList.AddSpirvOp(Op.OpMemoryModel);
node.AddLiteral(AddressingModel.Logical,AddressingModel.GetStr(AddressingModel.Logical));
node.AddLiteral(MemoryModel.GLSL450,MemoryModel.GetStr(MemoryModel.GLSL450));
AllocEntryPoint;
Case FExecutionModel of
ExecutionModel.Fragment:
begin
AddExecutionMode(ExecutionMode.OriginUpperLeft);
if FEarlyFragmentTests then
begin
AddExecutionMode(ExecutionMode.EarlyFragmentTests);
end;
case OutputList.FDepthMode of
foDepthReplacing:AddExecutionMode(ExecutionMode.DepthReplacing);
foDepthGreater :AddExecutionMode(ExecutionMode.DepthGreater);
foDepthLess :AddExecutionMode(ExecutionMode.DepthLess);
foDepthUnchanged:AddExecutionMode(ExecutionMode.DepthUnchanged);
else;
end;
end;
ExecutionModel.GLCompute:
begin
node:=AddExecutionMode(ExecutionMode.LocalSize);
node.AddLiteral(FLocalSize.x);
node.AddLiteral(FLocalSize.y);
node.AddLiteral(FLocalSize.z);
end;
ExecutionModel.Geometry:
begin
node:=AddExecutionMode(ExecutionMode.OutputVertices);
node.AddLiteral(FGeometryInfo.outputVertCount);
//
node:=AddExecutionMode(ExecutionMode.Invocations);
node.AddLiteral(FGeometryInfo.invocationCount);
//
node:=AddExecutionMode(FGeometryInfo.InputMode);
node:=AddExecutionMode(FGeometryInfo.OutputMode);
end;
end;
end;
procedure TSprvEmit_alloc.AllocListId(node:TsrNode);
begin
While (node<>nil) do
begin
AllocSpirvID(node.GetRef);
node:=node.Next;
end;
end;
procedure TSprvEmit_alloc.AllocFuncId;
var
pFunc:TSpirvFunc;
begin
pFunc:=FuncList.First;
While (pFunc<>nil) do
begin
AllocOpBlock(pFunc.pTop);
pFunc:=pFunc.Next;
end;
end;
procedure TSprvEmit_alloc.AllocOpId(node:TSpirvOp);
var
Param:POpParamNode;
Info:Op.TOpInfo;
pReg:TsrRegNode;
begin
if (node=nil) then Exit;
Info:=Op.GetInfo(node.OpId);
if Info.result then //dst
begin
Assert(node.pDst<>nil,'AllocOp$1');
if (node.pDst<>nil) then
begin
AllocSpirvID(node.pDst.GetRef);
end;
end else
begin //no dst
if (node.pDst<>nil) then
begin
AllocSpirvID(node.pDst.GetRef);
end;
end;
if Info.rstype then //dst type
begin
if (node.pType=nil) then
begin
pReg:=node.pDst.specialize 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.ParamFirst;
While (Param<>nil) do
begin
AllocSpirvID(Param.Value.GetRef);
Param:=Param.Next;
end;
end;
procedure TSprvEmit_alloc.AllocOpBlock(pBlock:TsrOpBlock);
var
node:TSpirvOp;
begin
if (pBlock=nil) then Exit;
node:=pBlock.First;
While (node<>nil) do
begin
if node.IsType(ntOp) then
begin
AllocOpId(node);
end;
node:=flow_down_next_up(node);
end;
end;
end.