mirror of https://github.com/red-prig/fpPS4.git
1659 lines
44 KiB
Plaintext
1659 lines
44 KiB
Plaintext
unit emit_op;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
spirv,
|
|
srNode,
|
|
srType,
|
|
srTypes,
|
|
srConst,
|
|
srReg,
|
|
srOp,
|
|
srCFGLabel,
|
|
srOpInternal,
|
|
srOpUtils,
|
|
srCacheOp,
|
|
srInterface;
|
|
|
|
type
|
|
TEmitOp=class(TEmitInterface)
|
|
//
|
|
function _Op1(pLine:TspirvOp;OpId:DWORD;dst,src:TsrRegNode):TspirvOp;
|
|
function _Op2(pLine:TspirvOp;OpId:DWORD;dst,src0,src1:TsrRegNode):TspirvOp;
|
|
function _Op3(pLine:TspirvOp;OpId:DWORD;dst,src0,src1,src2:TsrRegNode):TspirvOp;
|
|
function _Op4(pLine:TspirvOp;OpId:DWORD;dst,src0,src1,src2,src3:TsrRegNode):TspirvOp;
|
|
//
|
|
function _OpGlsl1(pLine:TspirvOp;OpId:DWORD;dst,src:TsrRegNode):TspirvOp;
|
|
function _OpGlsl2(pLine:TspirvOp;OpId:DWORD;dst,src0,src1:TsrRegNode):TspirvOp;
|
|
function _OpGlsl3(pLine:TspirvOp;OpId:DWORD;dst,src0,src1,src2:TsrRegNode):TspirvOp;
|
|
//
|
|
function Op1(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src:TsrRegNode):TspirvOp;
|
|
function Op2(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1:TsrRegNode):TspirvOp;
|
|
function Op3(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2:TsrRegNode):TspirvOp;
|
|
function Op4(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2,src3:TsrRegNode):TspirvOp;
|
|
//
|
|
function OpGlsl1(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src:TsrRegNode):TspirvOp;
|
|
function OpGlsl2(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1:TsrRegNode):TspirvOp;
|
|
function OpGlsl3(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2:TsrRegNode):TspirvOp;
|
|
//
|
|
function OpBitcast(pLine:TspirvOp;dst,src:TsrRegNode):TspirvOp;
|
|
function OpBitcast(pLine:TspirvOp;pType:TsrType;dst,src:TsrNode):TspirvOp;
|
|
function OpBoolToInt(pLine:TspirvOp;dst,src:TsrRegNode):TspirvOp;
|
|
function OpIntToBool(pLine:TspirvOp;dst,src:TsrRegNode):TspirvOp;
|
|
function OpIntToBoolTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
//
|
|
function OpCast (nLine, dst,src:TsrNode):TsrNode; override;
|
|
function OpLoad (nLine,dtype,dst,src:TsrNode):TsrNode; override;
|
|
function OpStore(nLine, dst,src:TsrNode):TsrNode; override;
|
|
//
|
|
function OpLoad(pLine:TspirvOp;dst:TsrRegNode;src:TsrNode):TspirvOp;
|
|
function OpLoadTo(pType:TsrType;src:TsrNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
//
|
|
function OpLine(nLine:TsrNode;iLine,iColumn:DWORD):TsrNode;
|
|
//
|
|
function OpExtract(pLine:TspirvOp;dst,src:TsrRegNode;id:DWORD):TspirvOp;
|
|
function OpConstruct(pLine:TspirvOp;dst:TsrRegNode):TspirvOp;
|
|
function OpAccessChain(pLine:TspirvOp;vType:TsrType;dst,src:TsrNode):TspirvOp;
|
|
function OpAccessChainTo(vType:TsrType;src:TsrNode;idx0:TsrNode;ppLine:PPspirvOp=nil):TsrNode;
|
|
function OpCondMerge(pLine,pLabel:TspirvOp):TspirvOp;
|
|
function OpLoopMerge(pLine,pLabel0,pLabel1:TspirvOp):TspirvOp;
|
|
function OpBranch(pLine,pLabel:TspirvOp):TspirvOp;
|
|
function OpBranchCond(pLine,pLabel0,pLabel1:TspirvOp;src:TsrRegNode):TspirvOp;
|
|
function OpReturnValue(pLine:TspirvOp;src:TsrRegNode):TspirvOp;
|
|
//
|
|
function OpReturn(pLine:TspirvOp):TspirvOp;
|
|
function OpFunctionEnd(pLine:TspirvOp):TspirvOp;
|
|
function OpEmitVertex(pLine:TspirvOp):TspirvOp;
|
|
function OpEndPrimitive(pLine:TspirvOp):TspirvOp;
|
|
//
|
|
procedure OpFmaF32(dst:PsrRegSlot;src0,src1,src2:TsrRegNode);
|
|
procedure OpFmaI32(dst:PsrRegSlot;src0,src1,src2:TsrRegNode);
|
|
procedure OpFmaU32(dst:PsrRegSlot;src0,src1,src2:TsrRegNode);
|
|
//
|
|
procedure OpSelect(dst:PsrRegSlot;src0,src1,cond:TsrRegNode);
|
|
function OpSelectTo(src0,src1,cond:TsrRegNode):TsrRegNode;
|
|
//
|
|
procedure OpIAddCar(pLine:TspirvOp;dst,car,src0,src1:TsrRegNode);
|
|
procedure OpIAddExt(dst,car:PsrRegSlot;src0,src1:TsrRegNode;rtype:TsrDataType);
|
|
procedure OpIAddExt(dst,car,src0,src1:TsrRegNode);
|
|
//
|
|
procedure OpISubBor(pLine:TspirvOp;dst,bor,src0,src1:TsrRegNode);
|
|
procedure OpISubExt(dst,bor:PsrRegSlot;src0,src1:TsrRegNode;rtype:TsrDataType);
|
|
//
|
|
function OpAbsDiff(pLine:TspirvOp;dst,src0,src1:TsrRegNode):TspirvOp;
|
|
procedure OpWQM32(dst:PsrRegSlot;src:TsrRegNode);
|
|
//
|
|
procedure OpBFE_32(dst:PsrRegSlot;base,src0,src1:TsrRegNode);
|
|
procedure OpBFIB32(dst:PsrRegSlot;bitmsk,src0,src1:TsrRegNode);
|
|
//
|
|
function OpBFITo (src0,src1,src2,src3:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpBFUETo(src0,src1,src2:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
//
|
|
procedure OpPackAnc(dst:PsrRegSlot;prim,smid,rtid:TsrRegNode);
|
|
//
|
|
function OpSMinTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpSMaxTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpUMinTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpUMaxTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpFMinTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpFMaxTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpNMinTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpNMaxTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
//
|
|
procedure OpMED3I(dst:PsrRegSlot;src0,src1,src2:TsrRegNode);
|
|
procedure OpMED3U(dst:PsrRegSlot;src0,src1,src2:TsrRegNode);
|
|
procedure OpMED3F(dst:PsrRegSlot;src0,src1,src2:TsrRegNode);
|
|
//
|
|
function OpPackOfs(pLine:TspirvOp;rtype:TsrDataType;count:Byte;src:TsrRegNode):TsrRegNode;
|
|
function OpMakeCon(pLine:TspirvOp;dst:TsrRegNode;src:PPsrRegNode):TspirvOp;
|
|
function OpMakeVec(pLine:TspirvOp;rtype:TsrDataType;src:PPsrRegNode):TsrRegNode;
|
|
function OpMakeCub(pLine:TspirvOp;rtype:TsrDataType;src:PPsrRegNode):TsrRegNode;
|
|
function OpSampledImage(pLine:TspirvOp;Tgrp,Sgrp:TsrNode;dtype:TsrDataType;info:TsrTypeImageInfo):TsrRegNode;
|
|
//
|
|
procedure OpIAdd(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
procedure OpISub(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
procedure OpIMul(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
//
|
|
function OpShlTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpShlTo(src0:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpShrTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpShrTo(src0:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
//
|
|
function OpIAddTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpIAddTo(src0:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpISubTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpISubTo(src0:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpIMulTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpIMulTo(src0:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpIDivTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpIDivTo(src0:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpIModTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
//
|
|
function OpFAddTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpFSubTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpFMulTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpFDivTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
//
|
|
function OpFAddToS(src0:TsrRegNode;src1:Single;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpFMulToS(src0:TsrRegNode;src1:Single;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
//
|
|
function OpUToF(src:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpFToU(src:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpSToF(src:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpUToU(src:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpSToS(src:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpFToF(src:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
//
|
|
function OpFloorTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpPowTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
//
|
|
procedure OpNot (dst:PsrRegSlot;src:TsrRegNode);
|
|
procedure OpLogicalNot(dst:PsrRegSlot;src:TsrRegNode);
|
|
procedure OpBitwiseOr (dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
procedure OpBitwiseXor(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
procedure OpLogicalOr (dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
procedure OpBitwiseAnd(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
procedure OpLogicalAnd(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
//
|
|
function OpLogicalNotTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpNotTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpOrTo (src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpAndTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpAndTo(src0:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
//
|
|
function OpIsSSignTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpIEqualTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpINotEqualTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpEqualTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
function OpNotEqualTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
//
|
|
function OpBitCountTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
//
|
|
function OpImageSampleImplicitLod(pLine:TspirvOp;img:TsrNode;dst,coord:TsrRegNode):TspirvOp;
|
|
function OpImageSampleExplicitLod(pLine:TspirvOp;img:TsrNode;dst,coord:TsrRegNode):TspirvOp;
|
|
function OpImageSampleDrefImplicitLod(pLine:TspirvOp;img:TsrNode;dst,coord,pcf:TsrRegNode):TspirvOp;
|
|
function OpImageSampleDrefExplicitLod(pLine:TspirvOp;img:TsrNode;dst,coord,pcf:TsrRegNode):TspirvOp;
|
|
function OpImageGather(pLine:TspirvOp;img:TsrNode;dst,coord:TsrRegNode;id:Byte):TspirvOp;
|
|
function OpImageDrefGather(pLine:TspirvOp;img:TsrNode;dst,coord,pcf:TsrRegNode):TspirvOp;
|
|
function OpImageFetch(pLine:TspirvOp;Tgrp:TsrNode;dst,coord:TsrRegNode):TspirvOp;
|
|
function OpImageRead(pLine:TspirvOp;Tgrp:TsrNode;dst,idx:TsrRegNode):TspirvOp;
|
|
function OpImageWrite(pLine:TspirvOp;Tgrp:TsrNode;idx,src:TsrRegNode):TspirvOp;
|
|
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:TspirvOp);
|
|
begin
|
|
if (ppLine=nil) then Exit;
|
|
ppLine^:=pLine;
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp._Op1(pLine:TspirvOp;OpId:DWORD;dst,src:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
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:TspirvOp;OpId:DWORD;dst,src0,src1:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
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:TspirvOp;OpId:DWORD;dst,src0,src1,src2:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
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:TspirvOp;OpId:DWORD;dst,src0,src1,src2,src3:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
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:TspirvOp;OpId:DWORD;dst,src:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
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:TspirvOp;OpId:DWORD;dst,src0,src1:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
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:TspirvOp;OpId:DWORD;dst,src0,src1,src2:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
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:TsrRegNode):TspirvOp;
|
|
begin
|
|
Result:=_Op1(line,OpId,dst^.New(rtype),src);
|
|
end;
|
|
|
|
function TEmitOp.Op2(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1:TsrRegNode):TspirvOp;
|
|
begin
|
|
Result:=_Op2(line,OpId,dst^.New(rtype),src0,src1);
|
|
end;
|
|
|
|
function TEmitOp.Op3(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2:TsrRegNode):TspirvOp;
|
|
begin
|
|
Result:=_Op3(line,OpId,dst^.New(rtype),src0,src1,src2);
|
|
end;
|
|
|
|
function TEmitOp.Op4(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2,src3:TsrRegNode):TspirvOp;
|
|
begin
|
|
Result:=_Op4(line,OpId,dst^.New(rtype),src0,src1,src2,src3);
|
|
end;
|
|
|
|
function TEmitOp.OpGlsl1(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src:TsrRegNode):TspirvOp;
|
|
begin
|
|
Result:=_OpGlsl1(line,OpId,dst^.New(rtype),src);
|
|
end;
|
|
|
|
function TEmitOp.OpGlsl2(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1:TsrRegNode):TspirvOp;
|
|
begin
|
|
Result:=_OpGlsl2(line,OpId,dst^.New(rtype),src0,src1)
|
|
end;
|
|
|
|
function TEmitOp.OpGlsl3(OpId:DWORD;rtype:TsrDataType;dst:PsrRegSlot;src0,src1,src2:TsrRegNode):TspirvOp;
|
|
begin
|
|
Result:=_OpGlsl3(line,OpId,dst^.New(rtype),src0,src1,src2);
|
|
end;
|
|
|
|
function TEmitOp.OpBitcast(pLine:TspirvOp;dst,src:TsrRegNode):TspirvOp;
|
|
begin
|
|
Result:=_Op1(pLine,Op.OpBitcast,dst,src);
|
|
end;
|
|
|
|
function TEmitOp.OpBitcast(pLine:TspirvOp;pType:TsrType;dst,src:TsrNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpBitcast); //need first
|
|
node.pType:=pType;
|
|
node.pDst:=dst;
|
|
node.AddParam(src);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpBoolToInt(pLine:TspirvOp;dst,src:TsrRegNode):TspirvOp;
|
|
Var
|
|
src0,src1:TsrRegNode;
|
|
begin
|
|
src0:=NewImm_q(dst.dtype,0,pLine);
|
|
src1:=NewImm_q(dst.dtype,1,pLine);
|
|
|
|
Result:=_Op3(pLine,Op.OpSelect,dst,src,src1,src0);
|
|
end;
|
|
|
|
function TEmitOp.OpIntToBool(pLine:TspirvOp;dst,src:TsrRegNode):TspirvOp;
|
|
Var
|
|
src0:TsrRegNode;
|
|
begin
|
|
src0:=NewImm_q(src.dtype,0,pLine);
|
|
|
|
Result:=_Op2(pLine,Op.OpINotEqual,dst,src,src0);
|
|
end;
|
|
|
|
function TEmitOp.OpIntToBoolTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(dtBool);
|
|
_set_line(ppLine,_Op1(_get_line(ppLine),Op.OpINotEqual,Result,src));
|
|
end;
|
|
|
|
function TEmitOp.OpCast(nLine,dst,src:TsrNode):TsrNode;
|
|
var
|
|
rdst,rsrc,rtmp:TsrRegNode;
|
|
pLine:TspirvOp;
|
|
begin
|
|
pLine:=nLine.specialize AsType<ntOpCustom>;
|
|
rdst :=dst.specialize AsType<ntReg>;
|
|
rsrc :=src.specialize AsType<ntReg>;
|
|
|
|
Assert(pLine<>nil);
|
|
Assert(rdst<>nil);
|
|
Assert(rsrc<>nil);
|
|
|
|
if (rsrc.dtype=dtBool) then
|
|
begin
|
|
Case rdst.dtype of
|
|
dtInt32,
|
|
dtUint32:Result:=OpBoolToInt(pLine,rdst,rsrc);
|
|
else
|
|
begin
|
|
rtmp:=NewReg(dtUint32);
|
|
pLine :=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);
|
|
pLine :=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:TsrNode):TsrNode;
|
|
var
|
|
pLine:TspirvOp;
|
|
pType:TsrType;
|
|
node:TspirvOp;
|
|
begin
|
|
pLine:=nLine.specialize AsType<ntOpCustom>;
|
|
pType:=dtype.specialize 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:TsrNode):TsrNode;
|
|
Var
|
|
pLine:TspirvOp;
|
|
node:TspirvOp;
|
|
begin
|
|
pLine:=nLine.specialize AsType<ntOpCustom>;
|
|
Assert(dst<>nil);
|
|
Assert(src<>nil);
|
|
Assert(pLine<>nil);
|
|
node:=AddSpirvOp(pLine,Op.OpStore);
|
|
node.AddParam(dst); //write
|
|
node.AddParam(src);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpLoad(pLine:TspirvOp;dst:TsrRegNode;src:TsrNode):TspirvOp;
|
|
Var
|
|
dtype:TsrType;
|
|
begin
|
|
dtype:=TypeList.Fetch(dst.dtype);
|
|
Result:=OpLoad(pLine,dtype,dst,src);
|
|
end;
|
|
|
|
function TEmitOp.OpLoadTo(pType:TsrType;src:TsrNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(pType.dtype);
|
|
//
|
|
_set_line(ppLine,OpLoad(_get_line(ppLine),pType,Result,src));
|
|
end;
|
|
|
|
function TEmitOp.OpLine(nLine:TsrNode;iLine,iColumn:DWORD):TsrNode;
|
|
var
|
|
pLine:TspirvOp;
|
|
node:TspirvOp;
|
|
nFile:TsrNode;
|
|
begin
|
|
pLine:=nLine.specialize AsType<ntOpCustom>;
|
|
Assert(pLine<>nil);
|
|
nFile:=DebugInfoList.FileName;
|
|
node:=AddSpirvOp(pLine,Op.OpLine);
|
|
node.AddParam(nFile);
|
|
node.AddLiteral(iLine);
|
|
node.AddLiteral(iColumn);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpExtract(pLine:TspirvOp;dst,src:TsrRegNode;id:DWORD):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
Assert(src.dtype.isVector);
|
|
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:TspirvOp;dst:TsrRegNode):TspirvOp;
|
|
var
|
|
node:TspirvOp;
|
|
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:TspirvOp;vType:TsrType;dst,src:TsrNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpAccessChain);
|
|
Assert(vType<>nil);
|
|
node.pType:=TypeList.FetchPointer(vType,src.GetStorageClass);
|
|
node.pDst:=dst;
|
|
node.AddParam(src); //base
|
|
Result:=node;
|
|
//index add later
|
|
end;
|
|
|
|
function TEmitOp.OpAccessChainTo(vType:TsrType;src:TsrNode;idx0:TsrNode;ppLine:PPspirvOp=nil):TsrNode;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
Result:=NewRefNode;
|
|
//
|
|
node:=OpAccessChain(_get_line(ppLine),vType,Result,src);
|
|
node.AddParam(idx0);
|
|
_set_line(ppLine,node);
|
|
end;
|
|
|
|
function TEmitOp.OpCondMerge(pLine,pLabel:TspirvOp):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpSelectionMerge);
|
|
node.AddParam(pLabel.pDst);
|
|
node.AddLiteral(SelectionControl.None,'None');
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpLoopMerge(pLine,pLabel0,pLabel1:TspirvOp):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
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:TspirvOp):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpBranch);
|
|
node.AddParam(pLabel.pDst);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpBranchCond(pLine,pLabel0,pLabel1:TspirvOp;src:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpBranchConditional);
|
|
node.AddParam(src);
|
|
node.AddParam(pLabel0.pDst);
|
|
node.AddParam(pLabel1.pDst);
|
|
Result:=node;
|
|
end;
|
|
|
|
function TEmitOp.OpReturnValue(pLine:TspirvOp;src:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpReturnValue);
|
|
node.AddParam(src);
|
|
Result:=node;
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpReturn(pLine:TspirvOp):TspirvOp;
|
|
begin
|
|
Result:=AddSpirvOp(pLine,Op.OpReturn);
|
|
end;
|
|
|
|
function TEmitOp.OpFunctionEnd(pLine:TspirvOp):TspirvOp;
|
|
begin
|
|
Result:=AddSpirvOp(pLine,Op.OpFunctionEnd);
|
|
end;
|
|
|
|
function TEmitOp.OpEmitVertex(pLine:TspirvOp):TspirvOp;
|
|
begin
|
|
Result:=AddSpirvOp(pLine,Op.OpEmitVertex);
|
|
end;
|
|
|
|
function TEmitOp.OpEndPrimitive(pLine:TspirvOp):TspirvOp;
|
|
begin
|
|
Result:=AddSpirvOp(pLine,Op.OpEndPrimitive);
|
|
end;
|
|
|
|
//
|
|
|
|
procedure TEmitOp.OpFmaF32(dst:PsrRegSlot;src0,src1,src2:TsrRegNode);
|
|
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:TsrRegNode);
|
|
var
|
|
mul,sum:TsrRegNode;
|
|
begin
|
|
//vdst = vsrc0.i * vsrc1.i + vdst.i
|
|
mul:=NewReg(dtInt32);
|
|
sum:=dst^.New(dtInt32);
|
|
|
|
_Op2(line,Op.OpIMul,mul,src0,src1);
|
|
_Op2(line,Op.OpIAdd,sum,mul,src2);
|
|
end;
|
|
|
|
procedure TEmitOp.OpFmaU32(dst:PsrRegSlot;src0,src1,src2:TsrRegNode);
|
|
var
|
|
mul,sum:TsrRegNode;
|
|
begin
|
|
//vdst = vsrc0.u * vsrc1.u + vdst.u
|
|
mul:=NewReg(dtUInt32);
|
|
sum:=dst^.New(dtUInt32);
|
|
|
|
_Op2(line,Op.OpIMul,mul,src0,src1);
|
|
_Op2(line,Op.OpIAdd,sum,mul,src2);
|
|
end;
|
|
|
|
//
|
|
|
|
procedure TEmitOp.OpSelect(dst:PsrRegSlot;src0,src1,cond:TsrRegNode);
|
|
begin
|
|
Op3(Op.OpSelect,LazyType2(src0.dtype,src1.dtype),dst,cond,src1,src0);
|
|
end;
|
|
|
|
function TEmitOp.OpSelectTo(src0,src1,cond:TsrRegNode):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(LazyType2(src0.dtype,src1.dtype));
|
|
//
|
|
_Op3(line,Op.OpSelect,Result,cond,src1,src0);
|
|
end;
|
|
|
|
procedure TEmitOp.OpIAddCar(pLine:TspirvOp;dst,car,src0,src1:TsrRegNode);
|
|
Var
|
|
node:TspirvOp;
|
|
rsl:TsrRegNode;
|
|
rtype:TsrDataType;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpIAddCarry); //need first
|
|
node.AddParam(src0);
|
|
node.AddParam(src1);
|
|
|
|
rtype:=dst.dtype.AsStruct2;
|
|
Assert(rtype<>dtUnknow);
|
|
|
|
rsl:=NewReg(rtype);
|
|
|
|
node.pType:=TypeList.Fetch(rtype);
|
|
node.pDst:=rsl;
|
|
|
|
dst:=BitcastList.FetchDstr(rtype.Child,dst);
|
|
car:=BitcastList.FetchDstr(rtype.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:TsrRegNode;rtype:TsrDataType);
|
|
Var
|
|
node:TspirvOp;
|
|
rsl:TsrRegPair;
|
|
begin
|
|
Assert(rtype.Sign=0);
|
|
|
|
node:=AddSpirvOp(srOpInternal.OpIAddExt); //need first
|
|
node.AddParam(src0);
|
|
node.AddParam(src1);
|
|
|
|
rsl:=NewRegPair;
|
|
rsl.pWriter:=node;
|
|
node.pDst:=rsl;
|
|
|
|
rsl.pDst0:=dst^.New(rtype); //dtUint32,dtUint64
|
|
rsl.pDst1:=car^.New(rtype); //dtUint32,dtUint64
|
|
end;
|
|
|
|
procedure TEmitOp.OpIAddExt(dst,car,src0,src1:TsrRegNode);
|
|
Var
|
|
node:TspirvOp;
|
|
rsl:TsrRegPair;
|
|
begin
|
|
Assert(dst.dtype.Sign=0);
|
|
|
|
node:=AddSpirvOp(srOpInternal.OpIAddExt); //need first
|
|
node.AddParam(src0);
|
|
node.AddParam(src1);
|
|
|
|
rsl:=NewRegPair;
|
|
rsl.pWriter:=node;
|
|
node.pDst:=rsl;
|
|
|
|
rsl.pDst0:=dst; //dtUint32,dtUint64
|
|
rsl.pDst1:=car; //dtUint32,dtUint64
|
|
end;
|
|
|
|
procedure TEmitOp.OpISubBor(pLine:TspirvOp;dst,bor,src0,src1:TsrRegNode);
|
|
Var
|
|
node:TspirvOp;
|
|
rsl:TsrRegNode;
|
|
rtype:TsrDataType;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpISubBorrow); //need first
|
|
node.AddParam(src0);
|
|
node.AddParam(src1);
|
|
|
|
rtype:=dst.dtype.AsStruct2;
|
|
Assert(rtype<>dtUnknow);
|
|
|
|
rsl:=NewReg(rtype);
|
|
|
|
node.pType:=TypeList.Fetch(rtype);
|
|
node.pDst:=rsl;
|
|
|
|
dst:=BitcastList.FetchDstr(rtype.Child,dst);
|
|
bor:=BitcastList.FetchDstr(rtype.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:TsrRegNode;rtype:TsrDataType);
|
|
Var
|
|
node:TspirvOp;
|
|
rsl:TsrRegPair;
|
|
begin
|
|
Assert(rtype.Sign=0);
|
|
|
|
node:=AddSpirvOp(srOpInternal.OpISubExt); //need first
|
|
node.AddParam(src0);
|
|
node.AddParam(src1);
|
|
|
|
rsl:=NewRegPair;
|
|
rsl.pWriter:=node;
|
|
node.pDst:=rsl;
|
|
|
|
rsl.pDst0:=dst^.New(rtype); //dtUint32,dtUint64
|
|
rsl.pDst1:=bor^.New(rtype); //dtUint32,dtUint64
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpAbsDiff(pLine:TspirvOp;dst,src0,src1:TsrRegNode):TspirvOp;
|
|
begin
|
|
Result:=_Op2(pLine,srOpInternal.OpAbsDiff,dst,src0,src1);
|
|
end;
|
|
|
|
procedure TEmitOp.OpWQM32(dst:PsrRegSlot;src:TsrRegNode);
|
|
begin
|
|
Op1(srOpInternal.OpWQM32,dtUnknow,dst,src);
|
|
end;
|
|
|
|
procedure TEmitOp.OpBFE_32(dst:PsrRegSlot;base,src0,src1:TsrRegNode);
|
|
begin
|
|
Op3(srOpInternal.OpBFE_32,base.dtype,dst,base,src0,src1);
|
|
end;
|
|
|
|
procedure TEmitOp.OpBFIB32(dst:PsrRegSlot;bitmsk,src0,src1:TsrRegNode);
|
|
begin
|
|
Op3(srOpInternal.OpBFIB32,dtUint32,dst,bitmsk,src0,src1);
|
|
end;
|
|
|
|
function TEmitOp.OpBFITo(src0,src1,src2,src3:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0.dtype);
|
|
_set_line(ppLine,_Op4(_get_line(ppLine),Op.OpBitFieldInsert,Result,src0,src1,src2,src3));
|
|
end;
|
|
|
|
function TEmitOp.OpBFUETo(src0,src1,src2:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0.dtype);
|
|
_set_line(ppLine,_Op3(_get_line(ppLine),Op.OpBitFieldUExtract,Result,src0,src1,src2));
|
|
end;
|
|
|
|
//
|
|
|
|
procedure TEmitOp.OpPackAnc(dst:PsrRegSlot;prim,smid,rtid:TsrRegNode);
|
|
begin
|
|
Op3(srOpInternal.OpPackAnc,dtUint32,dst,prim,smid,rtid);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpSMinTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.SMin,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpSMaxTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.SMax,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpUMinTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.UMin,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpUMaxTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.UMax,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpFMinTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.FMin,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpFMaxTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.FMax,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpNMinTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(src0.dtype);
|
|
_set_line(ppLine,_OpGlsl2(_get_line(ppLine),GlslOp.NMin,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpNMaxTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
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:TsrRegNode);
|
|
var
|
|
min:TsrRegNode;
|
|
max:TsrRegNode;
|
|
mmx:TsrRegNode;
|
|
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:TsrRegNode);
|
|
var
|
|
min:TsrRegNode;
|
|
max:TsrRegNode;
|
|
mmx:TsrRegNode;
|
|
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:TsrRegNode);
|
|
var
|
|
min:TsrRegNode;
|
|
max:TsrRegNode;
|
|
mmx:TsrRegNode;
|
|
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:TspirvOp;rtype:TsrDataType;count:Byte;src:TsrRegNode):TsrRegNode;
|
|
Var
|
|
p:TsrCacheOp;
|
|
dst:TsrRegNode;
|
|
node:TspirvOp;
|
|
begin
|
|
Assert(count<>0);
|
|
Assert(src<>nil);
|
|
|
|
pLine:=GetMaxPlace(pLine,1,@src);
|
|
|
|
p:=CacheOpList.Fetch(pLine.Parent,srOpInternal.OpPackOfs,rtype,1,@src);
|
|
|
|
if (p.pDst=nil) then
|
|
begin
|
|
node:=AddSpirvOp(pLine,srOpInternal.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:=p.pDst;
|
|
end;
|
|
end;
|
|
|
|
function TEmitOp.OpMakeCon(pLine:TspirvOp;dst:TsrRegNode;src:PPsrRegNode):TspirvOp;
|
|
Var
|
|
p:TsrCacheOp;
|
|
node:TspirvOp;
|
|
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:TspirvOp;rtype:TsrDataType;src:PPsrRegNode):TsrRegNode;
|
|
Var
|
|
p:TsrCacheOp;
|
|
dst:TsrRegNode;
|
|
node:TspirvOp;
|
|
i:Byte;
|
|
begin
|
|
Assert(src<>nil);
|
|
|
|
pLine:=GetMaxPlace(pLine,rtype.Count,src);
|
|
|
|
p:=CacheOpList.Fetch(pLine.Parent,srOpInternal.OpMakeVec,rtype,rtype.Count,src);
|
|
|
|
if (p.pDst=nil) then
|
|
begin
|
|
node:=AddSpirvOp(pLine,srOpInternal.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:=p.pDst;
|
|
end;
|
|
end;
|
|
|
|
//x,y,face,slice
|
|
function TEmitOp.OpMakeCub(pLine:TspirvOp;rtype:TsrDataType;src:PPsrRegNode):TsrRegNode;
|
|
Var
|
|
p:TsrCacheOp;
|
|
dst:TsrRegNode;
|
|
node:TspirvOp;
|
|
i:Byte;
|
|
begin
|
|
Assert(src<>nil);
|
|
|
|
pLine:=GetMaxPlace(pLine,rtype.Count,src);
|
|
|
|
p:=CacheOpList.Fetch(pLine.Parent,srOpInternal.OpMakeCub,rtype,rtype.Count,src);
|
|
|
|
if (p.pDst=nil) then
|
|
begin
|
|
node:=AddSpirvOp(pLine,srOpInternal.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:=p.pDst;
|
|
end;
|
|
end;
|
|
|
|
Function FindByHalfSpace(node:TspirvOp;pDst:TsrNode):Boolean;
|
|
begin
|
|
Result:=False;
|
|
while (node<>nil) do
|
|
begin
|
|
if (node.pDst=pDst) then Exit(True);
|
|
//
|
|
if node.IsType(ntOpBlock) then
|
|
if IsReal(TsrOpBlock(node).Block.bType) then
|
|
begin
|
|
Exit(False);
|
|
end;
|
|
//
|
|
node:=flow_down_prev_up(node);
|
|
end;
|
|
end;
|
|
|
|
function TEmitOp.OpSampledImage(pLine:TspirvOp;Tgrp,Sgrp:TsrNode;dtype:TsrDataType;info:TsrTypeImageInfo):TsrRegNode;
|
|
Var
|
|
src:array[0..1] of TsrNode;
|
|
pType:TsrType;
|
|
p:TsrCacheOp;
|
|
dst:TsrRegNode;
|
|
node:TspirvOp;
|
|
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 that it is in the current half-space
|
|
begin
|
|
if FindByHalfSpace(pLine,p.pDst) then
|
|
begin
|
|
//use it
|
|
end else
|
|
begin
|
|
//reset
|
|
p.pDst:=nil;
|
|
end;
|
|
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:=p.pDst;
|
|
end;
|
|
end;
|
|
|
|
//
|
|
|
|
procedure TEmitOp.OpIAdd(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
begin
|
|
Op2(Op.OpIAdd,LazyIntType(src0.dtype,src1.dtype),dst,src0,src1);
|
|
end;
|
|
|
|
procedure TEmitOp.OpISub(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
begin
|
|
Op2(Op.OpISub,LazyIntType(src0.dtype,src1.dtype),dst,src0,src1);
|
|
end;
|
|
|
|
procedure TEmitOp.OpIMul(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
begin
|
|
Op2(Op.OpIMul,LazyIntType(src0.dtype,src1.dtype),dst,src0,src1);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpShlTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
Result:=NewReg(LazyIntType(src0.dtype,src1.dtype));
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpShiftLeftLogical,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpShlTo(src0:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1=0) then Exit(src0);
|
|
Result:=OpShlTo(src0,NewImm_q(src0.dtype,src1,_get_line(ppLine)),ppLine);
|
|
end;
|
|
|
|
function TEmitOp.OpShrTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
Result:=NewReg(LazyIntType(src0.dtype,src1.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:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1=0) then Exit(src0);
|
|
Result:=OpShrTo(src0,NewImm_q(src0.dtype,src1,_get_line(ppLine)),ppLine);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpIAddTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src0=nil) then Exit(src1);
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
Result:=NewReg(LazyIntType(src0.dtype,src1.dtype));
|
|
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpIAdd,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpIAddTo(src0:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1=0) then Exit(src0);
|
|
Result:=OpIAddTo(src0,NewImm_q(src0.dtype,src1,_get_line(ppLine)),ppLine);
|
|
end;
|
|
|
|
function TEmitOp.OpISubTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src0=nil) then Exit(src1);
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
Result:=NewReg(LazyIntType(src0.dtype,src1.dtype));
|
|
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpISub,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpISubTo(src0:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1=0) then Exit(src0);
|
|
Result:=OpISubTo(src0,NewImm_q(src0.dtype,src1,_get_line(ppLine)),ppLine);
|
|
end;
|
|
|
|
function TEmitOp.OpIMulTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src0=nil) then Exit(src1);
|
|
if (src1=nil) then Exit(src0);
|
|
|
|
Result:=NewReg(LazyIntType(src0.dtype,src1.dtype));
|
|
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpIMul,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpIMulTo(src0:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
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,NewImm_q(src0.dtype,src1,_get_line(ppLine)),ppLine);
|
|
end;
|
|
end;
|
|
|
|
function TEmitOp.OpIDivTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
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:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
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,NewImm_q(src0.dtype,src1,_get_line(ppLine)),ppLine);
|
|
end;
|
|
end;
|
|
|
|
function TEmitOp.OpIModTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
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.OpSMod,Result,src0,src1));
|
|
end else
|
|
begin
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpUMod,Result,src0,src1));
|
|
end;
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpFAddTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
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:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
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:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
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:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
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:TsrRegNode;src1:Single;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1=0) then Exit(src0);
|
|
Result:=OpFAddTo(src0,NewImm_s(src0.dtype,src1,_get_line(ppLine)),ppLine);
|
|
end;
|
|
|
|
function TEmitOp.OpFMulToS(src0:TsrRegNode;src1:Single;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src0=nil) or (src1=0) or (src1=1) then Exit(src0);
|
|
Result:=OpFMulTo(src0,NewImm_s(src0.dtype,src1,_get_line(ppLine)),ppLine);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpUToF(src:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src=nil) then Exit(src);
|
|
|
|
Result:=NewReg(rtype);
|
|
_Op1(_get_line(ppLine),Op.OpConvertUToF,Result,src);
|
|
end;
|
|
|
|
function TEmitOp.OpFToU(src:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src=nil) then Exit(src);
|
|
|
|
Result:=NewReg(rtype);
|
|
_Op1(_get_line(ppLine),Op.OpConvertFToU,Result,src);
|
|
end;
|
|
|
|
function TEmitOp.OpSToF(src:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src=nil) then Exit(src);
|
|
|
|
Result:=NewReg(rtype);
|
|
_Op1(_get_line(ppLine),Op.OpConvertSToF,Result,src);
|
|
end;
|
|
|
|
function TEmitOp.OpUToU(src:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src=nil) then Exit(src);
|
|
|
|
Result:=NewReg(rtype);
|
|
_Op1(_get_line(ppLine),Op.OpUConvert,Result,src);
|
|
end;
|
|
|
|
function TEmitOp.OpSToS(src:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src=nil) then Exit(src);
|
|
|
|
Result:=NewReg(rtype);
|
|
_Op1(_get_line(ppLine),Op.OpSConvert,Result,src);
|
|
end;
|
|
|
|
function TEmitOp.OpFToF(src:TsrRegNode;rtype:TsrDataType;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src=nil) then Exit(src);
|
|
|
|
Result:=NewReg(rtype);
|
|
_Op1(_get_line(ppLine),Op.OpFConvert,Result,src);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpFloorTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
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:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
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:TsrRegNode);
|
|
begin
|
|
Op1(Op.OpNot,dtUnknow,dst,src); //post type
|
|
end;
|
|
|
|
procedure TEmitOp.OpLogicalNot(dst:PsrRegSlot;src:TsrRegNode);
|
|
begin
|
|
Op1(Op.OpLogicalNot,dtBool,dst,src);
|
|
end;
|
|
|
|
procedure TEmitOp.OpBitwiseOr(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
begin
|
|
Op2(Op.OpBitwiseOr,dtUnknow,dst,src0,src1); //post type
|
|
end;
|
|
|
|
procedure TEmitOp.OpBitwiseXor(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
begin
|
|
Op2(Op.OpBitwiseXor,dtUint32,dst,src0,src1); //post need?
|
|
end;
|
|
|
|
procedure TEmitOp.OpLogicalOr(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
begin
|
|
Op2(Op.OpLogicalOr,dtBool,dst,src0,src1);
|
|
end;
|
|
|
|
procedure TEmitOp.OpBitwiseAnd(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
begin
|
|
Op2(Op.OpBitwiseAnd,dtUnknow,dst,src0,src1); //post type
|
|
end;
|
|
|
|
procedure TEmitOp.OpLogicalAnd(dst:PsrRegSlot;src0,src1:TsrRegNode);
|
|
begin
|
|
Op2(Op.OpLogicalAnd,dtBool,dst,src0,src1);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpLogicalNotTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(dtBool);
|
|
_set_line(ppLine,_Op1(_get_line(ppLine),Op.OpLogicalNot,Result,src)); //post type
|
|
end;
|
|
|
|
function TEmitOp.OpNotTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(dtUnknow);
|
|
_set_line(ppLine,_Op1(_get_line(ppLine),Op.OpNot,Result,src)); //post type
|
|
end;
|
|
|
|
function TEmitOp.OpOrTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(dtUnknow);
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpBitwiseOr,Result,src0,src1)); //post type
|
|
end;
|
|
|
|
function TEmitOp.OpAndTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(dtUnknow);
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpBitwiseAnd,Result,src0,src1)); //post type
|
|
end;
|
|
|
|
function TEmitOp.OpAndTo(src0:TsrRegNode;src1:QWORD;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
if (src0=nil) then Exit(src0);
|
|
Result:=OpAndTo(src0,NewImm_q(src0.dtype,src1,_get_line(ppLine)),ppLine);
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpIsSSignTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
var
|
|
zero:TsrRegNode;
|
|
begin
|
|
Result:=NewReg(dtBool);
|
|
zero :=NewImm_i(src.dtype,0,_get_line(ppLine));
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpSLessThan,Result,src,zero)); //(x<0)
|
|
end;
|
|
|
|
function TEmitOp.OpIEqualTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(dtBool);
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpIEqual,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpINotEqualTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(dtBool);
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpINotEqual,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpEqualTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(dtBool);
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpLogicalEqual,Result,src0,src1));
|
|
end;
|
|
|
|
function TEmitOp.OpNotEqualTo(src0,src1:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(dtBool);
|
|
_set_line(ppLine,_Op2(_get_line(ppLine),Op.OpLogicalNotEqual,Result,src0,src1));
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpBitCountTo(src:TsrRegNode;ppLine:PPspirvOp=nil):TsrRegNode;
|
|
begin
|
|
Result:=NewReg(src.dtype);
|
|
_set_line(ppLine,_Op1(_get_line(ppLine),Op.OpBitCount,Result,src));
|
|
end;
|
|
|
|
//
|
|
|
|
function TEmitOp.OpImageSampleImplicitLod(pLine:TspirvOp;img:TsrNode;dst,coord:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
Assert(dst.dtype.isVector,'dst must be vector');
|
|
|
|
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:TspirvOp;img:TsrNode;dst,coord:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
Assert(dst.dtype.isVector,'dst must be vector');
|
|
|
|
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:TspirvOp;img:TsrNode;dst,coord,pcf:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
Assert(dst.dtype.isScalar,'dst must be scalar');
|
|
|
|
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:TspirvOp;img:TsrNode;dst,coord,pcf:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
Assert(dst.dtype.isScalar,'dst must be scalar');
|
|
|
|
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:TspirvOp;img:TsrNode;dst,coord:TsrRegNode;id:Byte):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
comp:TsrRegNode;
|
|
begin
|
|
Assert(dst.dtype.isVector,'dst must be vector');
|
|
|
|
Case id of
|
|
0..3:;
|
|
else
|
|
Assert(False,'unknow id');
|
|
end;
|
|
|
|
comp:=NewImm_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:TspirvOp;img:TsrNode;dst,coord,pcf:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
Assert(dst.dtype.isVector,'dst must be vector');
|
|
|
|
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:TspirvOp;Tgrp:TsrNode;dst,coord:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
Assert(dst.dtype.isVector,'dst must be vector');
|
|
|
|
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:TspirvOp;Tgrp:TsrNode;dst,idx:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
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:TspirvOp;Tgrp:TsrNode;idx,src:TsrRegNode):TspirvOp;
|
|
Var
|
|
node:TspirvOp;
|
|
begin
|
|
node:=AddSpirvOp(pLine,Op.OpImageWrite); //need first
|
|
|
|
node.AddParam(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.
|
|
|