mirror of
https://github.com/red-prig/fpPS4.git
synced 2024-11-23 14:29:53 +00:00
1503 lines
39 KiB
ObjectPascal
1503 lines
39 KiB
ObjectPascal
unit emit_op;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
spirv,
|
|
srNode,
|
|
srType,
|
|
srTypes,
|
|
srConst,
|
|
srReg,
|
|
srLayout,
|
|
srVariable,
|
|
srOp,
|
|
srCFGLabel,
|
|
srOpUtils,
|
|
srCacheOp,
|
|
srInterface;
|
|
|
|
type
|
|
TEmitOp=class(TEmitInterface)
|
|
//
|
|
function _Op1(pLine:PspirvOp;OpId:DWORD;dst,src:PsrRegNode):PSpirvOp;
|
|
function _Op2(pLine:PspirvOp;OpId:DWORD;dst,src0,src1:PsrRegNode):PSpirvOp;
|
|
function _Op3(pLine:PspirvOp;OpId:DWORD;dst,src0,src1,src2:PsrRegNode):PSpirvOp;
|
|
function _Op4(pLine:PspirvOp;OpId:DWORD;dst,src0,src1,src2,src3:PsrRegNode):PSpirvOp;
|
|
//
|
|
function _OpGlsl1(pLine:PspirvOp;OpId:DWORD;dst,src:PsrRegNode):PSpirvOp;
|
|
function _OpGlsl2(pLine:PspirvOp;OpId:DWORD;dst,src0,src1:PsrRegNode):PSpirvOp;
|
|
function _OpGlsl3(pLine:PspirvOp;OpId:DWORD;dst,src0,src1,src2:PsrRegNode):PSpirvOp;
|
|
//
|
|
function Op1(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src:PsrRegNode):PSpirvOp;
|
|
function Op2(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1:PsrRegNode):PSpirvOp;
|
|
function Op3(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2:PsrRegNode):PSpirvOp;
|
|
function Op4(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2,src3:PsrRegNode):PSpirvOp;
|
|
//
|
|
function OpGlsl1(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src:PsrRegNode):PSpirvOp;
|
|
function OpGlsl2(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1:PsrRegNode):PSpirvOp;
|
|
function OpGlsl3(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2:PsrRegNode):PSpirvOp;
|
|
//
|
|
function OpBitcast(pLine:PspirvOp;dst,src:PsrRegNode):PSpirvOp;
|
|
function OpBoolToInt(pLine:PspirvOp;dst,src:PsrRegNode):PSpirvOp;
|
|
function OpIntToBool(pLine:PspirvOp;dst,src:PsrRegNode):PSpirvOp;
|
|
//
|
|
function OpCast (nLine, dst,src:PsrNode):PsrNode; override;
|
|
function OpLoad (nLine,dtype,dst,src:PsrNode):PsrNode; override;
|
|
function OpStore(nLine, dst,src:PsrNode):PsrNode; override;
|
|
//
|
|
function OpLoad(pLine:PspirvOp;dst:PsrRegNode;src:PsrNode):PSpirvOp;
|
|
//
|
|
function OpExtract(pLine:PspirvOp;dst,src:PsrRegNode;id:DWORD):PSpirvOp;
|
|
function OpConstruct(pLine:PspirvOp;dst:PsrRegNode):PSpirvOp;
|
|
function OpAccessChain(pLine:PspirvOp;vType:PsrType;dst:PsrChain;src:PsrVariable):PSpirvOp;
|
|
function OpCondMerge(pLine,pLabel:PspirvOp):PSpirvOp;
|
|
function OpLoopMerge(pLine,pLabel0,pLabel1:PspirvOp):PSpirvOp;
|
|
function OpBranch(pLine,pLabel:PspirvOp):PSpirvOp;
|
|
function OpBranchCond(pLine,pLabel0,pLabel1:PspirvOp;src:PsrRegNode):PSpirvOp;
|
|
function OpReturnValue(pLine:PspirvOp;src:PsrRegNode):PSpirvOp;
|
|
//
|
|
procedure OpFmaF32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode);
|
|
procedure OpFmaI32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode);
|
|
procedure OpFmaU32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode);
|
|
//
|
|
procedure OpSelect(dst:PsrRegSlot;src0,src1,cond:PsrRegNode);
|
|
//
|
|
procedure OpIAddCar(pLine:PspirvOp;dst,car,src0,src1:PsrRegNode);
|
|
procedure OpIAddExt(dst,car:PsrRegSlot;src0,src1:PsrRegNode);
|
|
//
|
|
procedure OpISubBor(pLine:PspirvOp;dst,bor,src0,src1:PsrRegNode);
|
|
procedure OpISubExt(dst,bor:PsrRegSlot;src0,src1:PsrRegNode);
|
|
//
|
|
function OpAbsDiff(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp;
|
|
procedure OpWQM32(dst:PsrRegSlot;src:PsrRegNode);
|
|
//
|
|
procedure OpBFEU32(dst:PsrRegSlot;base,src0,src1:PsrRegNode);
|
|
procedure OpBFIB32(dst:PsrRegSlot;bitmsk,src0,src1:PsrRegNode);
|
|
//
|
|
function OpBFITo(src0,src1,src2,src3:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
//
|
|
procedure OpPackAnc(dst:PsrRegSlot;prim,smid,rtid:PsrRegNode);
|
|
//
|
|
function OpSMinTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpSMaxTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpUMinTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpUMaxTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpFMinTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpFMaxTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpNMinTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpNMaxTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
//
|
|
procedure OpMED3I(dst:PsrRegSlot;src0,src1,src2:PsrRegNode);
|
|
procedure OpMED3U(dst:PsrRegSlot;src0,src1,src2:PsrRegNode);
|
|
procedure OpMED3F(dst:PsrRegSlot;src0,src1,src2:PsrRegNode);
|
|
//
|
|
function OpPackOfs(pLine:PspirvOp;rtype:TsrDataType;count:Byte;src:PsrRegNode):PsrRegNode;
|
|
function OpMakeCon(pLine:PspirvOp;dst:PsrRegNode;src:PPsrRegNode):PSpirvOp;
|
|
function OpMakeVec(pLine:PspirvOp;rtype:TsrDataType;src:PPsrRegNode):PsrRegNode;
|
|
function OpMakeCub(pLine:PspirvOp;rtype:TsrDataType;src:PPsrRegNode):PsrRegNode;
|
|
function OpSampledImage(pLine:PspirvOp;Tgrp,Sgrp:PsrNode;dtype:TsrDataType;info:TsrTypeImageInfo):PsrRegNode;
|
|
//
|
|
procedure OpIAdd(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
procedure OpISub(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
procedure OpIMul(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
//
|
|
function OpShlTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpShlTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpShrTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpShrTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
//
|
|
function OpIAddTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpIAddTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpISubTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpISubTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpIMulTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpIMulTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpIDivTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpIDivTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
//
|
|
function OpFAddTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpFSubTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpFMulTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpFDivTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
//
|
|
function OpFAddToS(src0:PsrRegNode;src1:Single;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpFMulToS(src0:PsrRegNode;src1:Single;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
//
|
|
function OpUToF(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpSToF(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpUToU(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpSToS(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpFToF(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
//
|
|
function OpFloorTo(src:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpPowTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
//
|
|
procedure OpNot(dst:PsrRegSlot;src:PsrRegNode);
|
|
procedure OpLogicalNot(dst:PsrRegSlot;src:PsrRegNode);
|
|
procedure OpBitwiseOr(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
procedure OpBitwiseXor(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
procedure OpLogicalOr(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
procedure OpBitwiseAnd(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
procedure OpLogicalAnd(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
//
|
|
function OpNotTo(src:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpOrTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpAndTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
function OpAndTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
//
|
|
function OpBitCountTo(src:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
//
|
|
function OpImageSampleImplicitLod(pLine:PspirvOp;img:PsrNode;dst,coord:PsrRegNode):PSpirvOp;
|
|
function OpImageSampleExplicitLod(pLine:PspirvOp;img:PsrNode;dst,coord:PsrRegNode):PSpirvOp;
|
|
function OpImageSampleDrefImplicitLod(pLine:PspirvOp;img:PsrNode;dst,coord,pcf:PsrRegNode):PSpirvOp;
|
|
function OpImageSampleDrefExplicitLod(pLine:PspirvOp;img:PsrNode;dst,coord,pcf:PsrRegNode):PSpirvOp;
|
|
function OpImageGather(pLine:PspirvOp;img:PsrNode;dst,coord:PsrRegNode;id:Byte):PSpirvOp;
|
|
function OpImageDrefGather(pLine:PspirvOp;img:PsrNode;dst,coord,pcf:PsrRegNode):PSpirvOp;
|
|
function OpImageFetch(pLine:PspirvOp;Tgrp:PsrNode;dst,coord:PsrRegNode):PSpirvOp;
|
|
function OpImageRead(pLine:PspirvOp;Tgrp:PsrNode;dst,idx:PsrRegNode):PspirvOp;
|
|
function OpImageWrite(pLine:PspirvOp;Tgrp:PsrNode;idx,src:PsrRegNode):PspirvOp;
|
|
end;
|
|
|
|
function isPowerOfTwo(x:QWORD):Boolean; inline;
|
|
function fastIntLog2(i:QWORD):QWORD; inline;
|
|
|
|
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;
|
|
|
|
procedure _set_line(ppLine:PPspirvOp;pLine:PspirvOp);
|
|
begin
|
|
if (ppLine=nil) then Exit;
|
|
ppLine^:=pLine;
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp._Op1(pLine:PspirvOp;OpId:DWORD;dst,src:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,OpId); //need first
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
node^.AddParam(src);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp._Op2(pLine:PspirvOp;OpId:DWORD;dst,src0,src1:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,OpId); //need first
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
node^.AddParam(src0);
|
|
node^.AddParam(src1);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp._Op3(pLine:PspirvOp;OpId:DWORD;dst,src0,src1,src2:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,OpId); //need first
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
node^.AddParam(src0);
|
|
node^.AddParam(src1);
|
|
node^.AddParam(src2);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp._Op4(pLine:PspirvOp;OpId:DWORD;dst,src0,src1,src2,src3:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,OpId); //need first
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
node^.AddParam(src0);
|
|
node^.AddParam(src1);
|
|
node^.AddParam(src2);
|
|
node^.AddParam(src3);
|
|
Result:=node;
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp._OpGlsl1(pLine:PspirvOp;OpId:DWORD;dst,src:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSGlslOp(pLine,OpId); //need first
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
node^.AddParam(src);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp._OpGlsl2(pLine:PspirvOp;OpId:DWORD;dst,src0,src1:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSGlslOp(pLine,OpId); //need first
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
node^.AddParam(src0);
|
|
node^.AddParam(src1);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp._OpGlsl3(pLine:PspirvOp;OpId:DWORD;dst,src0,src1,src2:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSGlslOp(pLine,OpId); //need first
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
node^.AddParam(src0);
|
|
node^.AddParam(src1);
|
|
node^.AddParam(src2);
|
|
Result:=node;
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.Op1(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src:PsrRegNode):PSpirvOp;
|
|
begin
|
|
Result:=_Op1(line,OpId,dst^.New(line,rtype),src);
|
|
end;
|
|
|
|
function TEmitOp.Op2(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1:PsrRegNode):PSpirvOp;
|
|
begin
|
|
Result:=_Op2(line,OpId,dst^.New(line,rtype),src0,src1);
|
|
end;
|
|
|
|
function TEmitOp.Op3(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2:PsrRegNode):PSpirvOp;
|
|
begin
|
|
Result:=_Op3(line,OpId,dst^.New(line,rtype),src0,src1,src2);
|
|
end;
|
|
|
|
function TEmitOp.Op4(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2,src3:PsrRegNode):PSpirvOp;
|
|
begin
|
|
Result:=_Op4(line,OpId,dst^.New(line,rtype),src0,src1,src2,src3);
|
|
end;
|
|
|
|
function TEmitOp.OpGlsl1(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src:PsrRegNode):PSpirvOp;
|
|
begin
|
|
Result:=_OpGlsl1(line,OpId,dst^.New(line,rtype),src);
|
|
end;
|
|
|
|
function TEmitOp.OpGlsl2(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1:PsrRegNode):PSpirvOp;
|
|
begin
|
|
Result:=_OpGlsl2(line,OpId,dst^.New(line,rtype),src0,src1)
|
|
end;
|
|
|
|
function TEmitOp.OpGlsl3(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2:PsrRegNode):PSpirvOp;
|
|
begin
|
|
Result:=_OpGlsl3(line,OpId,dst^.New(line,rtype),src0,src1,src2);
|
|
end;
|
|
|
|
function TEmitOp.OpBitcast(pLine:PspirvOp;dst,src:PsrRegNode):PSpirvOp;
|
|
begin
|
|
Result:=_Op1(pLine,Op.OpBitcast,dst,src);
|
|
end;
|
|
|
|
function TEmitOp.OpBoolToInt(pLine:PspirvOp;dst,src:PsrRegNode):PSpirvOp;
|
|
Var
|
|
src0,src1:PsrRegNode;
|
|
begin
|
|
src0:=NewReg_q(dst^.dtype,0,@pLine);
|
|
src1:=NewReg_q(dst^.dtype,1,@pLine);
|
|
|
|
Result:=_Op3(pLine,Op.OpSelect,dst,src,src1,src0);
|
|
end;
|
|
|
|
function TEmitOp.OpIntToBool(pLine:PspirvOp;dst,src:PsrRegNode):PSpirvOp;
|
|
Var
|
|
src0:PsrRegNode;
|
|
begin
|
|
src0:=NewReg_q(src^.dtype,0,@pLine);
|
|
|
|
Result:=_Op2(pLine,Op.OpINotEqual,dst,src,src0);
|
|
end;
|
|
|
|
function TEmitOp.OpCast(nLine,dst,src:PsrNode):PsrNode;
|
|
var
|
|
rdst,rsrc,rtmp:PsrRegNode;
|
|
pLine:PspirvOp;
|
|
begin
|
|
pLine:=nLine^.AsType(ntOpCustom);
|
|
rdst := dst^.AsType(ntReg);
|
|
rsrc := src^.AsType(ntReg);
|
|
|
|
Assert(pLine<>nil);
|
|
Assert(dst<>nil);
|
|
Assert(src<>nil);
|
|
|
|
if (rsrc^.dtype=dtBool) then
|
|
begin
|
|
Case rdst^.dtype of
|
|
dtInt32,
|
|
dtUint32:Result:=OpBoolToInt(pLine,rdst,rsrc);
|
|
else
|
|
begin
|
|
rtmp:=NewReg(dtUint32);
|
|
OpBoolToInt(pLine,rtmp,rsrc);
|
|
Result:=OpBitcast(pLine,rdst,rtmp);
|
|
end;
|
|
end;
|
|
end else
|
|
if (rdst^.dtype=dtBool) then
|
|
begin
|
|
Case rsrc^.dtype of
|
|
dtInt32,
|
|
dtUint32:Result:=OpIntToBool(pLine,rdst,rsrc);
|
|
else
|
|
begin
|
|
rtmp:=NewReg(dtUint32);
|
|
OpBitcast(pLine,rtmp,rsrc);
|
|
Result:=OpIntToBool(pLine,rdst,rtmp);
|
|
end;
|
|
end;
|
|
end else
|
|
begin
|
|
Result:=OpBitcast(pLine,rdst,rsrc);
|
|
end;
|
|
end;
|
|
|
|
function TEmitOp.OpLoad(nLine,dtype,dst,src:PsrNode):PsrNode;
|
|
var
|
|
pLine:PspirvOp;
|
|
pType:PsrType;
|
|
node:PSpirvOp;
|
|
begin
|
|
pLine:=nLine^.AsType(ntOpCustom);
|
|
pType:=dtype^.AsType(ntType);
|
|
Assert(dst<>nil);
|
|
Assert(src<>nil);
|
|
Assert(pLine<>nil);
|
|
//Assert(pType<>nil);
|
|
node:=AddSpirvOp(pLine,Op.OpLoad);
|
|
node^.pType:=pType;
|
|
node^.pDst :=dst;
|
|
node^.AddParam(src);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpStore(nLine,dst,src:PsrNode):PsrNode;
|
|
Var
|
|
pLine:PspirvOp;
|
|
node:PSpirvOp;
|
|
begin
|
|
pLine:=nLine^.AsType(ntOpCustom);
|
|
Assert(dst<>nil);
|
|
Assert(src<>nil);
|
|
Assert(pLine<>nil);
|
|
node:=AddSpirvOp(pLine,Op.OpStore);
|
|
node^.pDst:=dst; //write
|
|
node^.AddParam(src);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpLoad(pLine:PspirvOp;dst:PsrRegNode;src:PsrNode):PSpirvOp;
|
|
Var
|
|
dtype:PsrType;
|
|
begin
|
|
dtype:=TypeList.Fetch(dst^.dtype);
|
|
Result:=PSpirvOp(OpLoad(pLine,dtype,dst,src));
|
|
end;
|
|
|
|
function TEmitOp.OpExtract(pLine:PspirvOp;dst,src:PsrRegNode;id:DWORD):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpCompositeExtract);
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
node^.AddParam(src);
|
|
node^.AddLiteral(id);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpConstruct(pLine:PspirvOp;dst:PsrRegNode):PSpirvOp;
|
|
var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpCompositeConstruct);
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
Assert(node^.pType<>nil);
|
|
node^.pDst:=dst;
|
|
Result:=node;
|
|
//child add later
|
|
end;
|
|
|
|
function TEmitOp.OpAccessChain(pLine:PspirvOp;vType:PsrType;dst:PsrChain;src:PsrVariable):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpAccessChain);
|
|
Assert(vType<>nil);
|
|
node^.pType:=TypeList.FetchPointer(vType,src^.GetStorageClass);
|
|
node^.pDst:=dst;
|
|
node^.AddParam(src); //base
|
|
//dst^.pLine:=node;
|
|
Result:=node;
|
|
//index add later
|
|
end;
|
|
|
|
function TEmitOp.OpCondMerge(pLine,pLabel:PspirvOp):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpSelectionMerge);
|
|
node^.AddParam(pLabel^.pDst);
|
|
node^.AddLiteral(SelectionControl.None,'None');
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpLoopMerge(pLine,pLabel0,pLabel1:PspirvOp):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpLoopMerge);
|
|
node^.AddParam(pLabel0^.pDst);
|
|
node^.AddParam(pLabel1^.pDst);
|
|
node^.AddLiteral(LoopControl.None,'None');
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpBranch(pLine,pLabel:PspirvOp):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpBranch);
|
|
node^.AddParam(pLabel^.pDst);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpBranchCond(pLine,pLabel0,pLabel1:PspirvOp;src:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpBranchConditional);
|
|
node^.AddParam(src);
|
|
node^.AddParam(pLabel0^.pDst);
|
|
node^.AddParam(pLabel1^.pDst);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpReturnValue(pLine:PspirvOp;src:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpReturnValue);
|
|
node^.AddParam(src);
|
|
Result:=node;
|
|
end;
|
|
|
|
//
|
|
|
|
procedure TEmitOp.OpFmaF32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode);
|
|
begin
|
|
//vdst = vsrc0.f * vsrc1.f + vdst.f -> fma
|
|
//NoContraction decoration
|
|
OpGlsl3(GlslOp.Fma,dtFloat32,dst,src0,src1,src2);
|
|
end;
|
|
|
|
procedure TEmitOp.OpFmaI32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode);
|
|
var
|
|
mul,sum:PsrRegNode;
|
|
begin
|
|
//vdst = vsrc0.i * vsrc1.i + vdst.i
|
|
mul:=NewReg(dtInt32);
|
|
sum:=dst^.New(line,dtInt32);
|
|
|
|
_Op2(line,Op.OpIMul,mul,src0,src1);
|
|
_Op2(line,Op.OpIAdd,sum,mul,src2);
|
|
end;
|
|
|
|
procedure TEmitOp.OpFmaU32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode);
|
|
var
|
|
mul,sum:PsrRegNode;
|
|
begin
|
|
//vdst = vsrc0.u * vsrc1.u + vdst.u
|
|
mul:=NewReg(dtUInt32);
|
|
sum:=dst^.New(line,dtUInt32);
|
|
|
|
_Op2(line,Op.OpIMul,mul,src0,src1);
|
|
_Op2(line,Op.OpIAdd,sum,mul,src2);
|
|
end;
|
|
|
|
//
|
|
|
|
procedure TEmitOp.OpSelect(dst:PsrRegSlot;src0,src1,cond:PsrRegNode);
|
|
begin
|
|
Op3(Op.OpSelect,LazyType2(src0^.dtype,src1^.dtype),dst,cond,src1,src0);
|
|
end;
|
|
|
|
procedure TEmitOp.OpIAddCar(pLine:PspirvOp;dst,car,src0,src1:PsrRegNode);
|
|
Var
|
|
node:PSpirvOp;
|
|
rsl:PsrRegNode;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpIAddCarry); //need first
|
|
node^.AddParam(src0);
|
|
node^.AddParam(src1);
|
|
|
|
rsl:=NewReg(dtStruct2u);
|
|
|
|
node^.pType:=TypeList.Fetch(dtStruct2u);
|
|
node^.pDst:=rsl;
|
|
|
|
dst:=BitcastList.FetchDstr(TsrDataType(dtStruct2u).Child,dst);
|
|
car:=BitcastList.FetchDstr(TsrDataType(dtStruct2u).Child,car);
|
|
|
|
pLine:=node;
|
|
pLine:=OpExtract(pLine,dst,rsl,0);
|
|
pLine:=OpExtract(pLine,car,rsl,1);
|
|
end;
|
|
|
|
procedure TEmitOp.OpIAddExt(dst,car:PsrRegSlot;src0,src1:PsrRegNode);
|
|
Var
|
|
node:PSpirvOp;
|
|
rsl:PsrRegPair;
|
|
begin
|
|
node:=AddSpirvOp(srOpUtils.OpIAddExt); //need first
|
|
node^.AddParam(src0);
|
|
node^.AddParam(src1);
|
|
|
|
rsl:=NewRegPair;
|
|
rsl^.pWriter:=node;
|
|
node^.pDst:=rsl;
|
|
|
|
rsl^.pDst0:=dst^.New(line,dtUint32);
|
|
rsl^.pDst1:=car^.New(line,dtUint32);
|
|
end;
|
|
|
|
procedure TEmitOp.OpISubBor(pLine:PspirvOp;dst,bor,src0,src1:PsrRegNode);
|
|
Var
|
|
node:PSpirvOp;
|
|
rsl:PsrRegNode;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpISubBorrow); //need first
|
|
node^.AddParam(src0);
|
|
node^.AddParam(src1);
|
|
|
|
rsl:=NewReg(dtStruct2u);
|
|
|
|
node^.pType:=TypeList.Fetch(dtStruct2u);
|
|
node^.pDst:=rsl;
|
|
|
|
dst:=BitcastList.FetchDstr(TsrDataType(dtStruct2u).Child,dst);
|
|
bor:=BitcastList.FetchDstr(TsrDataType(dtStruct2u).Child,bor);
|
|
|
|
pLine:=node;
|
|
pLine:=OpExtract(pLine,dst,rsl,0);
|
|
pLine:=OpExtract(pLine,bor,rsl,1);
|
|
end;
|
|
|
|
procedure TEmitOp.OpISubExt(dst,bor:PsrRegSlot;src0,src1:PsrRegNode);
|
|
Var
|
|
node:PSpirvOp;
|
|
rsl:PsrRegPair;
|
|
begin
|
|
node:=AddSpirvOp(srOpUtils.OpISubExt); //need first
|
|
node^.AddParam(src0);
|
|
node^.AddParam(src1);
|
|
|
|
rsl:=NewRegPair;
|
|
rsl^.pWriter:=node;
|
|
node^.pDst:=rsl;
|
|
|
|
rsl^.pDst0:=dst^.New(line,dtUint32);
|
|
rsl^.pDst1:=bor^.New(line,dtUint32);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpAbsDiff(pLine:PspirvOp;dst,src0,src1:PsrRegNode):PSpirvOp;
|
|
begin
|
|
Result:=_Op2(pLine,srOpUtils.OpAbsDiff,dst,src0,src1);
|
|
end;
|
|
|
|
procedure TEmitOp.OpWQM32(dst:PsrRegSlot;src:PsrRegNode);
|
|
begin
|
|
Op1(srOpUtils.OpWQM32,dtUnknow,dst,src);
|
|
end;
|
|
|
|
procedure TEmitOp.OpBFEU32(dst:PsrRegSlot;base,src0,src1:PsrRegNode);
|
|
begin
|
|
Op3(srOpUtils.OpBFEU32,dtUint32,dst,base,src0,src1);
|
|
end;
|
|
|
|
procedure TEmitOp.OpBFIB32(dst:PsrRegSlot;bitmsk,src0,src1:PsrRegNode);
|
|
begin
|
|
Op3(srOpUtils.OpBFIB32,dtUint32,dst,bitmsk,src0,src1);
|
|
end;
|
|
|
|
function TEmitOp.OpBFITo(src0,src1,src2,src3:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_Op4(_get_line(ppLine),Op.OpBitFieldInsert,Result,src0,src1,src2,src3));
|
|
end;
|
|
|
|
//
|
|
|
|
procedure TEmitOp.OpPackAnc(dst:PsrRegSlot;prim,smid,rtid:PsrRegNode);
|
|
begin
|
|
Op3(srOpUtils.OpPackAnc,dtUint32,dst,prim,smid,rtid);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpSMinTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.SMin,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpSMaxTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.SMax,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpUMinTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.UMin,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpUMaxTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.UMax,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpFMinTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.FMin,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpFMaxTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.FMax,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpNMinTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.NMin,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpNMaxTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.NMax,Result,src0,src1));
|
|
end;
|
|
|
|
procedure TEmitOp.OpMED3I(dst:PsrRegSlot;src0,src1,src2:PsrRegNode);
|
|
var
|
|
min:PsrRegNode;
|
|
max:PsrRegNode;
|
|
mmx:PsrRegNode;
|
|
begin
|
|
min:=OpSMinTo(src0,src1); //min(s0,s1)
|
|
max:=OpSMaxTo(src0,src1); //max(s0,s1)
|
|
mmx:=OpSMinTo(max ,src2); //min(max(s0,s1),s2)
|
|
|
|
OpGlsl2(GlslOp.SMax,src0^.dtype,dst,min,mmx); //max(min(s0,s1),min(max(s0,s1),s2))
|
|
end;
|
|
|
|
procedure TEmitOp.OpMED3U(dst:PsrRegSlot;src0,src1,src2:PsrRegNode);
|
|
var
|
|
min:PsrRegNode;
|
|
max:PsrRegNode;
|
|
mmx:PsrRegNode;
|
|
begin
|
|
min:=OpUMinTo(src0,src1); //min(s0,s1)
|
|
max:=OpUMaxTo(src0,src1); //max(s0,s1)
|
|
mmx:=OpUMinTo(max ,src2); //min(max(s0,s1),s2)
|
|
|
|
OpGlsl2(GlslOp.UMax,src0^.dtype,dst,min,mmx); //max(min(s0,s1),min(max(s0,s1),s2))
|
|
end;
|
|
|
|
procedure TEmitOp.OpMED3F(dst:PsrRegSlot;src0,src1,src2:PsrRegNode);
|
|
var
|
|
min:PsrRegNode;
|
|
max:PsrRegNode;
|
|
mmx:PsrRegNode;
|
|
begin
|
|
min:=OpFMinTo(src0,src1); //min(s0,s1)
|
|
max:=OpNMaxTo(src0,src1); //max(s0,s1)
|
|
mmx:=OpFMinTo(max ,src2); //min(max(s0,s1),s2)
|
|
|
|
OpGlsl2(GlslOp.NMax,src0^.dtype,dst,min,mmx); //max(min(s0,s1),min(max(s0,s1),s2))
|
|
end;
|
|
|
|
function TEmitOp.OpPackOfs(pLine:PspirvOp;rtype:TsrDataType;count:Byte;src:PsrRegNode):PsrRegNode;
|
|
Var
|
|
p:PsrCacheOp;
|
|
dst:PsrRegNode;
|
|
node:PSpirvOp;
|
|
begin
|
|
Assert(count<>0);
|
|
Assert(src<>nil);
|
|
|
|
pLine:=GetMaxPlace(pLine,1,@src);
|
|
|
|
p:=CacheOpList.Fetch(pLine^.Parent,srOpUtils.OpPackOfs,rtype,1,@src);
|
|
|
|
if (p^.pDst=nil) then
|
|
begin
|
|
node:=AddSpirvOp(pLine,srOpUtils.OpPackOfs); //need first
|
|
|
|
dst:=NewReg(rtype);
|
|
|
|
node^.pDst:=dst;
|
|
node^.AddLiteral(count);
|
|
node^.AddParam(src);
|
|
|
|
p^.pDst:=dst; //save
|
|
Result:=dst;
|
|
end else
|
|
begin
|
|
Result:=PsrRegNode(p^.pDst);
|
|
end;
|
|
end;
|
|
|
|
function TEmitOp.OpMakeCon(pLine:PspirvOp;dst:PsrRegNode;src:PPsrRegNode):PSpirvOp;
|
|
Var
|
|
p:PsrCacheOp;
|
|
node:PSpirvOp;
|
|
rtype:TsrDataType;
|
|
i:Byte;
|
|
begin
|
|
Result:=pLine;
|
|
Assert(src<>nil);
|
|
|
|
rtype:=dst^.dtype;
|
|
|
|
pLine:=GetMaxPlace(pLine,rtype.Count,src);
|
|
|
|
p:=CacheOpList.Fetch(pLine^.Parent,Op.OpCompositeConstruct,rtype,rtype.Count,src);
|
|
|
|
if (p^.pDst=nil) then
|
|
begin
|
|
node:=OpConstruct(pLine,dst);
|
|
For i:=0 to rtype.Count-1 do
|
|
begin
|
|
node^.AddParam(src[i]);
|
|
end;
|
|
p^.pDst:=dst; //save
|
|
Result:=node;
|
|
end else
|
|
begin
|
|
dst^.pWriter:=p^.pDst;
|
|
end;
|
|
end;
|
|
|
|
function TEmitOp.OpMakeVec(pLine:PspirvOp;rtype:TsrDataType;src:PPsrRegNode):PsrRegNode;
|
|
Var
|
|
p:PsrCacheOp;
|
|
dst:PsrRegNode;
|
|
node:PSpirvOp;
|
|
i:Byte;
|
|
begin
|
|
Assert(src<>nil);
|
|
|
|
pLine:=GetMaxPlace(pLine,rtype.Count,src);
|
|
|
|
p:=CacheOpList.Fetch(pLine^.Parent,srOpUtils.OpMakeVec,rtype,rtype.Count,src);
|
|
|
|
if (p^.pDst=nil) then
|
|
begin
|
|
node:=AddSpirvOp(pLine,srOpUtils.OpMakeVec); //need first
|
|
|
|
dst:=NewReg(rtype);
|
|
|
|
node^.pDst:=dst;
|
|
|
|
For i:=0 to rtype.Count-1 do
|
|
begin
|
|
node^.AddParam(src[i]);
|
|
end;
|
|
|
|
p^.pDst:=dst; //save
|
|
Result:=dst;
|
|
end else
|
|
begin
|
|
Result:=PsrRegNode(p^.pDst);
|
|
end;
|
|
end;
|
|
|
|
//x,y,face,slice
|
|
function TEmitOp.OpMakeCub(pLine:PspirvOp;rtype:TsrDataType;src:PPsrRegNode):PsrRegNode;
|
|
Var
|
|
p:PsrCacheOp;
|
|
dst:PsrRegNode;
|
|
node:PSpirvOp;
|
|
i:Byte;
|
|
begin
|
|
Assert(src<>nil);
|
|
|
|
pLine:=GetMaxPlace(pLine,rtype.Count,src);
|
|
|
|
p:=CacheOpList.Fetch(pLine^.Parent,srOpUtils.OpMakeCub,rtype,rtype.Count,src);
|
|
|
|
if (p^.pDst=nil) then
|
|
begin
|
|
node:=AddSpirvOp(pLine,srOpUtils.OpMakeCub); //need first
|
|
|
|
dst:=NewReg(rtype);
|
|
|
|
node^.pDst:=dst;
|
|
|
|
For i:=0 to rtype.Count-1 do
|
|
begin
|
|
node^.AddParam(src[i]);
|
|
end;
|
|
|
|
p^.pDst:=dst; //save
|
|
Result:=dst;
|
|
end else
|
|
begin
|
|
Result:=PsrRegNode(p^.pDst);
|
|
end;
|
|
end;
|
|
|
|
function TEmitOp.OpSampledImage(pLine:PspirvOp;Tgrp,Sgrp:PsrNode;dtype:TsrDataType;info:TsrTypeImageInfo):PsrRegNode;
|
|
Var
|
|
src:array[0..1] of PsrNode;
|
|
pType:PsrType;
|
|
p:PsrCacheOp;
|
|
dst:PsrRegNode;
|
|
node:PSpirvOp;
|
|
tmp:PSpirvOp;
|
|
label
|
|
_prev;
|
|
begin
|
|
src[0]:=Tgrp;
|
|
src[1]:=Sgrp;
|
|
|
|
Assert(pLine<>nil);
|
|
|
|
p:=CacheOpList.Fetch(pLine^.Parent,Op.OpSampledImage,dtTypeSampledImage,2,@src);
|
|
|
|
if (p^.pDst<>nil) then //check before break block
|
|
begin
|
|
node:=pLine;
|
|
repeat
|
|
|
|
if (node^.pDst=p^.pDst) then
|
|
begin
|
|
Break; //end
|
|
end;
|
|
|
|
if node^.IsType(ntOpBlock) then
|
|
begin
|
|
tmp:=nil;
|
|
if (PsrOpBlock(node)^.Block.bType in [btCond,btLoop]) then
|
|
begin
|
|
p^.pDst:=nil; //reset
|
|
Break;
|
|
end else
|
|
begin
|
|
tmp:=node^.Last;
|
|
end;
|
|
if (tmp<>nil) then
|
|
begin
|
|
node:=tmp;
|
|
Continue;
|
|
end;
|
|
end;
|
|
|
|
_prev:
|
|
|
|
tmp:=node^.Prev;
|
|
|
|
if (tmp=nil) then
|
|
begin
|
|
if (node^.Parent=nil) or
|
|
(node^.Parent=pLine^.Parent) then
|
|
begin
|
|
Break; //end
|
|
end else
|
|
begin
|
|
node:=node^.Parent;
|
|
Goto _prev;
|
|
end;
|
|
end else
|
|
begin
|
|
node:=tmp;
|
|
end;
|
|
|
|
until false;
|
|
end;
|
|
|
|
if (p^.pDst=nil) then
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpSampledImage); //need first
|
|
|
|
dst:=NewReg(dtTypeSampledImage);
|
|
|
|
pType:=TypeList.Fetch(dtype);
|
|
pType:=TypeList.FetchImage(pType,info);
|
|
pType:=TypeList.FetchSampledImage(pType);
|
|
|
|
node^.pType:=pType;
|
|
node^.pDst:=dst;
|
|
|
|
node^.AddParam(Tgrp);
|
|
node^.AddParam(Sgrp);
|
|
|
|
p^.pDst:=dst; //save
|
|
Result:=dst;
|
|
end else
|
|
begin
|
|
Result:=PsrRegNode(p^.pDst);
|
|
end;
|
|
end;
|
|
|
|
//
|
|
|
|
procedure TEmitOp.OpIAdd(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
begin
|
|
if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then
|
|
begin
|
|
Op2(Op.OpIAdd,dtInt32,dst,src0,src1);
|
|
end else
|
|
begin
|
|
Op2(Op.OpIAdd,dtUInt32,dst,src0,src1);
|
|
end;
|
|
end;
|
|
|
|
procedure TEmitOp.OpISub(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
begin
|
|
if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then
|
|
begin
|
|
Op2(Op.OpISub,dtInt32,dst,src0,src1);
|
|
end else
|
|
begin
|
|
Op2(Op.OpISub,dtUInt32,dst,src0,src1);
|
|
end;
|
|
end;
|
|
|
|
procedure TEmitOp.OpIMul(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
begin
|
|
if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then
|
|
begin
|
|
Op2(Op.OpIMul,dtInt32,dst,src0,src1);
|
|
end else
|
|
begin
|
|
Op2(Op.OpIMul,dtUInt32,dst,src0,src1);
|
|
end;
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpShlTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpShiftLeftLogical,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpShlTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1=0) then Exit(src0);
|
|
Result:=OpShlTo(src0,NewReg_q(src0^.dtype,src1,ppLine),ppLine);
|
|
end;
|
|
|
|
function TEmitOp.OpShrTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
Result:=NewReg(src0^.dtype);
|
|
if (src0^.dtype.Sign<>0) then
|
|
begin
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpShiftRightArithmetic,Result,src0,src1));
|
|
end else
|
|
begin
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpShiftRightLogical ,Result,src0,src1));
|
|
end;
|
|
end;
|
|
|
|
function TEmitOp.OpShrTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1=0) then Exit(src0);
|
|
Result:=OpShrTo(src0,NewReg_q(src0^.dtype,src1,ppLine),ppLine);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpIAddTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) then Exit(src1);
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then
|
|
begin
|
|
Result:=NewReg(dtInt32);
|
|
end else
|
|
begin
|
|
Result:=NewReg(dtUInt32);
|
|
end;
|
|
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpIAdd,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpIAddTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1=0) then Exit(src0);
|
|
Result:=OpIAddTo(src0,NewReg_q(src0^.dtype,src1,ppLine),ppLine);
|
|
end;
|
|
|
|
function TEmitOp.OpISubTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) then Exit(src1);
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then
|
|
begin
|
|
Result:=NewReg(dtInt32);
|
|
end else
|
|
begin
|
|
Result:=NewReg(dtUInt32);
|
|
end;
|
|
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpISub,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpISubTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1=0) then Exit(src0);
|
|
Result:=OpISubTo(src0,NewReg_q(src0^.dtype,src1,ppLine),ppLine);
|
|
end;
|
|
|
|
function TEmitOp.OpIMulTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) then Exit(src1);
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
if (src0^.dtype=dtInt32) or (src1^.dtype=dtInt32) then
|
|
begin
|
|
Result:=NewReg(dtInt32);
|
|
end else
|
|
begin
|
|
Result:=NewReg(dtUInt32);
|
|
end;
|
|
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpIMul,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpIMulTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1<=1) then Exit(src0);
|
|
|
|
if isPowerOfTwo(src1) then
|
|
begin
|
|
src1:=fastIntLog2(src1);
|
|
Result:=OpShlTo (src0,src1,ppLine);
|
|
end else
|
|
begin
|
|
Result:=OpIMulTo(src0,src1,ppLine);
|
|
end;
|
|
end;
|
|
|
|
function TEmitOp.OpIDivTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
Result:=NewReg(src0^.dtype);
|
|
if (src0^.dtype.Sign<>0) then
|
|
begin
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpSDiv,Result,src0,src1));
|
|
end else
|
|
begin
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpUDiv,Result,src0,src1));
|
|
end;
|
|
end;
|
|
|
|
function TEmitOp.OpIDivTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1<=1) then Exit(src0);
|
|
|
|
if isPowerOfTwo(src1) then
|
|
begin
|
|
src1:=fastIntLog2(src1);
|
|
Result:=OpShrTo (src0,src1,ppLine);
|
|
end else
|
|
begin
|
|
Result:=OpIDivTo(src0,src1,ppLine);
|
|
end;
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpFAddTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) then Exit(src1);
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpFAdd,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpFSubTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) then Exit(src1);
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpFSub,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpFMulTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) then Exit(src1);
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpFMul,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpFDivTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpFDiv,Result,src0,src1));
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpFAddToS(src0:PsrRegNode;src1:Single;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1=0) then Exit(src0);
|
|
Result:=OpFAddTo(src0,NewReg_s(src0^.dtype,src1,ppLine),ppLine);
|
|
end;
|
|
|
|
function TEmitOp.OpFMulToS(src0:PsrRegNode;src1:Single;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1=0) or (src1=1) then Exit(src0);
|
|
Result:=OpFMulTo(src0,NewReg_s(src0^.dtype,src1,ppLine),ppLine);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpUToF(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src=nil) then Exit(src);
|
|
|
|
Result:=NewReg(rtype);
|
|
_Op1(_get_line(ppLine),Op.OpConvertUToF,Result,src);
|
|
end;
|
|
|
|
function TEmitOp.OpSToF(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src=nil) then Exit(src);
|
|
|
|
Result:=NewReg(rtype);
|
|
_Op1(_get_line(ppLine),Op.OpConvertSToF,Result,src);
|
|
end;
|
|
|
|
function TEmitOp.OpUToU(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src=nil) then Exit(src);
|
|
|
|
Result:=NewReg(rtype);
|
|
_Op1(_get_line(ppLine),Op.OpUConvert,Result,src);
|
|
end;
|
|
|
|
function TEmitOp.OpSToS(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src=nil) then Exit(src);
|
|
|
|
Result:=NewReg(rtype);
|
|
_Op1(_get_line(ppLine),Op.OpSConvert,Result,src);
|
|
end;
|
|
|
|
function TEmitOp.OpFToF(src:PsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src=nil) then Exit(src);
|
|
|
|
Result:=NewReg(rtype);
|
|
_Op1(_get_line(ppLine),Op.OpFConvert,Result,src);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpFloorTo(src:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src=nil) then Exit(src);
|
|
|
|
Result:=NewReg(src^.dtype);
|
|
_OpGlsl1(_get_line(ppLine),GlslOp.Floor,Result,src)
|
|
end;
|
|
|
|
function TEmitOp.OpPowTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src1=nil) then Exit(nil);
|
|
|
|
Result:=NewReg(src0^.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.Pow,Result,src0,src1));
|
|
end;
|
|
|
|
//
|
|
|
|
procedure TEmitOp.OpNot(dst:PsrRegSlot;src:PsrRegNode);
|
|
begin
|
|
Op1(Op.OpNot,dtUnknow,dst,src); //post type
|
|
end;
|
|
|
|
procedure TEmitOp.OpLogicalNot(dst:PsrRegSlot;src:PsrRegNode);
|
|
begin
|
|
Op1(Op.OpLogicalNot,dtBool,dst,src);
|
|
end;
|
|
|
|
procedure TEmitOp.OpBitwiseOr(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
begin
|
|
Op2(Op.OpBitwiseOr,dtUnknow,dst,src0,src1); //post type
|
|
end;
|
|
|
|
procedure TEmitOp.OpBitwiseXor(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
begin
|
|
Op2(Op.OpBitwiseXor,dtUint32,dst,src0,src1); //post need?
|
|
end;
|
|
|
|
procedure TEmitOp.OpLogicalOr(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
begin
|
|
Op2(Op.OpLogicalOr,dtBool,dst,src0,src1);
|
|
end;
|
|
|
|
procedure TEmitOp.OpBitwiseAnd(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
begin
|
|
Op2(Op.OpBitwiseAnd,dtUnknow,dst,src0,src1); //post type
|
|
end;
|
|
|
|
procedure TEmitOp.OpLogicalAnd(dst:PsrRegSlot;src0,src1:PsrRegNode);
|
|
begin
|
|
Op2(Op.OpLogicalAnd,dtBool,dst,src0,src1);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpNotTo(src:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
Result:=NewReg(dtUnknow);
|
|
_set_line(ppLine,_Op1(_get_line(ppLine),Op.OpNot,Result,src)); //post type
|
|
end;
|
|
|
|
function TEmitOp.OpOrTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
Result:=NewReg(dtUnknow);
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpBitwiseOr,Result,src0,src1)); //post type
|
|
end;
|
|
|
|
function TEmitOp.OpAndTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
Result:=NewReg(dtUnknow);
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpBitwiseAnd,Result,src0,src1)); //post type
|
|
end;
|
|
|
|
function TEmitOp.OpAndTo(src0:PsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
if (src0=nil) then Exit(src0);
|
|
Result:=OpAndTo(src0,NewReg_q(src0^.dtype,src1,ppLine),ppLine);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpBitCountTo(src:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode;
|
|
begin
|
|
Result:=NewReg(src^.dtype);
|
|
_set_line(ppLine,_Op1(_get_line(ppLine),Op.OpBitCount,Result,src));
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpImageSampleImplicitLod(pLine:PspirvOp;img:PsrNode;dst,coord:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpImageSampleImplicitLod); //need first
|
|
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
|
|
node^.AddParam(img); //Sampled Image
|
|
node^.AddParam(coord); //Coordinate
|
|
//Image Operands
|
|
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpImageSampleExplicitLod(pLine:PspirvOp;img:PsrNode;dst,coord:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpImageSampleExplicitLod); //need first
|
|
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
|
|
node^.AddParam(img); //Sampled Image
|
|
node^.AddParam(coord); //Coordinate
|
|
//Image Operands
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpImageSampleDrefImplicitLod(pLine:PspirvOp;img:PsrNode;dst,coord,pcf:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpImageSampleDrefImplicitLod); //need first
|
|
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
|
|
node^.AddParam(img); //Sampled Image
|
|
node^.AddParam(coord); //Coordinate
|
|
node^.AddParam(pcf); //Dref
|
|
//Image Operands
|
|
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpImageSampleDrefExplicitLod(pLine:PspirvOp;img:PsrNode;dst,coord,pcf:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpImageSampleDrefExplicitLod); //need first
|
|
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
|
|
node^.AddParam(img); //Sampled Image
|
|
node^.AddParam(coord); //Coordinate
|
|
node^.AddParam(pcf); //Dref
|
|
//Image Operands
|
|
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpImageGather(pLine:PspirvOp;img:PsrNode;dst,coord:PsrRegNode;id:Byte):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
comp:PsrRegNode;
|
|
begin
|
|
Case id of
|
|
0..3:;
|
|
else
|
|
Assert(False);
|
|
end;
|
|
|
|
comp:=NewReg_i(dtUint32,id);
|
|
|
|
node:=AddSpirvOp(pLine,Op.OpImageGather); //need first
|
|
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
|
|
node^.AddParam(img); //Sampled Image
|
|
node^.AddParam(coord); //Coordinate
|
|
node^.AddParam(comp); //Component
|
|
//Image Operands
|
|
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpImageDrefGather(pLine:PspirvOp;img:PsrNode;dst,coord,pcf:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpImageDrefGather); //need first
|
|
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
|
|
node^.AddParam(img); //Sampled Image
|
|
node^.AddParam(coord); //Coordinate
|
|
node^.AddParam(pcf); //Dref
|
|
//Image Operands
|
|
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpImageFetch(pLine:PspirvOp;Tgrp:PsrNode;dst,coord:PsrRegNode):PSpirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpImageFetch); //need first
|
|
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
|
|
node^.AddParam(Tgrp);
|
|
node^.AddParam(coord);
|
|
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpImageRead(pLine:PspirvOp;Tgrp:PsrNode;dst,idx:PsrRegNode):PspirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpImageRead); //need first
|
|
|
|
node^.pType:=TypeList.Fetch(dst^.dtype);
|
|
node^.pDst:=dst;
|
|
|
|
node^.AddParam(Tgrp);
|
|
|
|
if (idx<>nil) then
|
|
begin
|
|
node^.AddParam(idx);
|
|
end else
|
|
begin
|
|
node^.AddParam(ConstList.Fetch_i(dtUint32,0));
|
|
end;
|
|
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpImageWrite(pLine:PspirvOp;Tgrp:PsrNode;idx,src:PsrRegNode):PspirvOp;
|
|
Var
|
|
node:PSpirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpImageWrite); //need first
|
|
node^.pDst:=Tgrp; //write
|
|
|
|
if (idx<>nil) then
|
|
begin
|
|
node^.AddParam(idx);
|
|
end else
|
|
begin
|
|
node^.AddParam(ConstList.Fetch_i(dtUint32,0));
|
|
end;
|
|
|
|
node^.AddParam(src);
|
|
|
|
Result:=node;
|
|
end;
|
|
|
|
|
|
end.
|
|
|