diff --git a/chip/pm4_me.pas b/chip/pm4_me.pas index 1cc48a36..c79fa5e6 100644 --- a/chip/pm4_me.pas +++ b/chip/pm4_me.pas @@ -1165,7 +1165,7 @@ begin GP_KEY.SetBlendInfo(ctx.rt_info^.BLEND_INFO.logicOp,@ctx.rt_info^.BLEND_INFO.blendConstants); - GP_KEY.SetPrimType (TVkPrimitiveTopology(ctx.rt_info^.PRIM_TYPE)); + GP_KEY.SetPrimType (ctx.rt_info^.PRIM_TYPE,GP_KEY.FShaderGroup.FKey.FPrimtype); GP_KEY.SetPrimReset(ctx.rt_info^.PRIM_RESET); if (ctx.rt_info^.VP_COUNT<>0) then @@ -1751,7 +1751,7 @@ begin CP_KEY.FShaderGroup.ExportUnifBuilder(FUniformBuilder,dst); //htile heuristic - if (CP_KEY.FShaderGroup.FKey.FShaders[vShaderStageCs].FHash_gcn=$7DCE68F83F66B337) then + if (CP_KEY.FShaderGroup.FKey.FShaders[vShaderStageCs].IsCSClearShader) then begin Prepare_htile(ctx,FUniformBuilder); // diff --git a/chip/pm4_stream.pas b/chip/pm4_stream.pas index 27465550..9f94bbad 100644 --- a/chip/pm4_stream.pas +++ b/chip/pm4_stream.pas @@ -1364,25 +1364,6 @@ begin Init_Uniforms(node,FUniformBuilder); end; -function IsClearDepthShaders(const FShaders:AvShaderStage):Boolean; inline; -begin - Result:=False; - - if (FShaders[vShaderStageLs]=nil) and - (FShaders[vShaderStageHs]=nil) and - (FShaders[vShaderStageEs]=nil) and - (FShaders[vShaderStageGs]=nil) and - (FShaders[vShaderStageVs]<>nil) and - (FShaders[vShaderStagePs]<>nil) and - (FShaders[vShaderStageCs]=nil) then - - if (FShaders[vShaderStageVs].FHash_gcn=QWORD($00DF6E6331449451)) and - (FShaders[vShaderStagePs].FHash_gcn=QWORD($E9FF5D4699E5B9AD)) then - begin - Result:=True; - end; -end; - procedure t_pm4_stream.BuildDraw(ntype:t_pm4_node_type; var SG_REG:TSH_REG_GFX_GROUP; var CX_REG:TCONTEXT_REG_GROUP; diff --git a/fpPS4.lpi b/fpPS4.lpi index 0c8b64f0..19ee25e7 100644 --- a/fpPS4.lpi +++ b/fpPS4.lpi @@ -1312,6 +1312,10 @@ + + + + diff --git a/spirv/SprvEmit.pas b/spirv/SprvEmit.pas index 05e36059..48d99530 100644 --- a/spirv/SprvEmit.pas +++ b/spirv/SprvEmit.pas @@ -58,6 +58,8 @@ type NTY:TCOMPUTE_NUM_THREAD_Y; NTZ:TCOMPUTE_NUM_THREAD_Z); + Procedure InitCustomGs(); + procedure emit_spi; override; Procedure PostStage; @@ -558,6 +560,19 @@ begin AddCapability(Capability.Shader); end; +Procedure TSprvEmit.InitCustomGs(); +begin + FExecutionModel:=ExecutionModel.Geometry; + + FGeometryInfo.outputVertCount:=4; + FGeometryInfo.invocationCount:=1; + FGeometryInfo.InputMode :=ExecutionMode.Triangles; + FGeometryInfo.OutputMode :=ExecutionMode.OutputTriangleStrip; + + AddCapability(Capability.Shader); + AddCapability(Capability.Geometry); +end; + // procedure TSprvEmit.emit_spi; diff --git a/spirv/emit_alloc.pas b/spirv/emit_alloc.pas index ca3a0abc..544787bd 100644 --- a/spirv/emit_alloc.pas +++ b/spirv/emit_alloc.pas @@ -213,6 +213,19 @@ begin node^.AddLiteral(FLocalSize.y); node^.AddLiteral(FLocalSize.z); end; + + ExecutionModel.Geometry: + begin + node:=AddExecutionMode(ExecutionMode.OutputVertices); + node^.AddLiteral(FGeometryInfo.outputVertCount); + // + node:=AddExecutionMode(ExecutionMode.Invocations); + node^.AddLiteral(FGeometryInfo.invocationCount); + // + node:=AddExecutionMode(FGeometryInfo.InputMode); + node:=AddExecutionMode(FGeometryInfo.OutputMode); + end; + end; end; diff --git a/spirv/emit_bin.pas b/spirv/emit_bin.pas index 3cd7d29d..5a6f85a3 100644 --- a/spirv/emit_bin.pas +++ b/spirv/emit_bin.pas @@ -42,7 +42,7 @@ type TSVInstrBuffer=object Data:array of DWORD; COUNT:DWORD; - Procedure AllocData; + function FetchData(dcount:DWORD):PDWORD; Procedure NewOp(OpId:WORD); Procedure Reset; Procedure Flush(Stream:TStream); @@ -65,12 +65,19 @@ type implementation -Procedure TSVInstrBuffer.AllocData; +function TSVInstrBuffer.FetchData(dcount:DWORD):PDWORD; +var + i:DWORD; begin + i:=COUNT; + COUNT:=COUNT+dcount; + // if (Length(Data)0,'new op not created'); - I:=COUNT; - Inc(COUNT); - AllocData; - Data[i]:=P; + + FetchData(1)^:=DWORD(P); end; procedure TSVInstrBuffer.AddNode(node:PsrNode); var R:PsrRefId; - I,L,D:DWORD; + L,D:DWORD; + P:PDWORD; begin Assert(node<>nil); Assert(COUNT<>0,'new op not created'); @@ -123,22 +125,17 @@ begin R:=node^.GetRef; if (R<>nil) then begin - I:=COUNT; - Inc(COUNT); - AllocData; - Data[i]:=R^.ID; + FetchData(1)^:=R^.ID; end else begin L:=node^.GetData(nil); //get size D:=(L+(SizeOf(DWORD)-1)) div 4; //align Assert(D<>0,'AddNode:'+node^.ntype.ClassName); - I:=COUNT; - COUNT:=COUNT+D; - AllocData; + P:=FetchData(D); - FillDWord(Data[i],D,0); - node^.GetData(@Data[i]); + FillDWord(P^,D,0); + node^.GetData(P); end; end; @@ -222,14 +219,38 @@ begin While (node<>nil) do begin buf.NewOp(node^.OpId); - buf.AddNode(node); - if (node^.ItemCount<>0) then + if (node^.OpId=Op.OpConstant) then begin - For i:=0 to node^.ItemCount-1 do + //Array Const + if (node^.ItemCount>0) then begin - buf.AddNode(node^.GetItem(i)); + buf.AddNode(node^.GetItem(0)); end; + + buf.AddNode(node); + + if (node^.ItemCount>1) then + begin + For i:=1 to node^.ItemCount-1 do + begin + buf.AddNode(node^.GetItem(i)); + end; + end; + //Array Const + end else + begin + //Types + buf.AddNode(node); + + if (node^.ItemCount<>0) then + begin + For i:=0 to node^.ItemCount-1 do + begin + buf.AddNode(node^.GetItem(i)); + end; + end; + //Types end; buf.Flush(Stream); diff --git a/spirv/emit_fetch.pas b/spirv/emit_fetch.pas index 254f2382..98e7c9ee 100644 --- a/spirv/emit_fetch.pas +++ b/spirv/emit_fetch.pas @@ -79,6 +79,7 @@ type function FetchChain(grp:PsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrRegNode; function MakeChain(pSlot:PsrRegSlot;grp:PsrDataLayout;lvl_0:PsrChainLvl_0;lvl_1:PsrChainLvl_1):PsrRegNode; Procedure AddVecInput(dst:PsrRegSlot;vtype,rtype:TsrDataType;itype:TpsslInputType;id:Byte); + function AddPositionsInput(count:Byte):PsrVariable; function FetchUniform(src:PsrDataLayout;pType:PsrType):PsrNode; function FetchImage(src:PsrDataLayout;dtype:TsrDataType;info:TsrTypeImageInfo):PsrNode; function FetchSampler(src:PsrDataLayout):PsrNode; @@ -699,6 +700,18 @@ begin OpExtract(init_line,dst^.New(line,rtype),rsl,id); end; +function TEmitFetch.AddPositionsInput(count:Byte):PsrVariable; +var + i:PsrInput; + t:PsrType; +begin + t:=TypeList.FetchArray(TypeList.Fetch(dtVec4f),count); + + i:=InputList.Fetch(t,itPosition,0); + + Result:=i^.pVar; +end; + //// function TEmitFetch.FetchUniform(src:PsrDataLayout;pType:PsrType):PsrNode; diff --git a/spirv/emit_op.pas b/spirv/emit_op.pas index 72072a3e..320a3350 100644 --- a/spirv/emit_op.pas +++ b/spirv/emit_op.pas @@ -11,7 +11,6 @@ uses srTypes, srConst, srReg, - srLayout, srVariable, srOp, srCFGLabel, @@ -49,21 +48,29 @@ type function OpStore(nLine, dst,src:PsrNode):PsrNode; override; // function OpLoad(pLine:PspirvOp;dst:PsrRegNode;src:PsrNode):PSpirvOp; + function OpLoadTo(nLine:PspirvOp;pType:PsrType;src:PsrNode):PsrRegNode; // 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 OpAccessChain(pLine:PspirvOp;vType:PsrType;dst:PsrNode;src:PsrVariable):PSpirvOp; + function OpAccessChainTo(pLine:PspirvOp;vType:PsrType;src:PsrVariable;idx0:PsrNode):PsrNode; 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; // + function OpReturn(pLine:PspirvOp):PSpirvOp; + function OpFunctionEnd(pLine:PspirvOp):PSpirvOp; + function OpEmitVertex(pLine:PspirvOp):PSpirvOp; + function OpEndPrimitive(pLine:PspirvOp):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); + function OpSelectTo(src0,src1,cond:PsrRegNode):PsrRegNode; // procedure OpIAddCar(pLine:PspirvOp;dst,car,src0,src1:PsrRegNode); procedure OpIAddExt(dst,car:PsrRegSlot;src0,src1:PsrRegNode); @@ -117,6 +124,7 @@ type 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 OpIModTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; // function OpFAddTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; function OpFSubTo(src0,src1:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; @@ -420,6 +428,13 @@ begin Result:=PSpirvOp(OpLoad(pLine,dtype,dst,src)); end; +function TEmitOp.OpLoadTo(nLine:PspirvOp;pType:PsrType;src:PsrNode):PsrRegNode; +begin + Result:=NewReg(pType^.dtype); + // + OpLoad(line,pType,Result,src); +end; + function TEmitOp.OpExtract(pLine:PspirvOp;dst,src:PsrRegNode;id:DWORD):PSpirvOp; Var node:PSpirvOp; @@ -445,7 +460,7 @@ begin //child add later end; -function TEmitOp.OpAccessChain(pLine:PspirvOp;vType:PsrType;dst:PsrChain;src:PsrVariable):PSpirvOp; +function TEmitOp.OpAccessChain(pLine:PspirvOp;vType:PsrType;dst:PsrNode;src:PsrVariable):PSpirvOp; Var node:PSpirvOp; begin @@ -459,6 +474,16 @@ begin //index add later end; +function TEmitOp.OpAccessChainTo(pLine:PspirvOp;vType:PsrType;src:PsrVariable;idx0:PsrNode):PsrNode; +Var + node:PSpirvOp; +begin + Result:=NewRefNode; + // + node:=OpAccessChain(line,vType,Result,src); + node^.AddParam(idx0); +end; + function TEmitOp.OpCondMerge(pLine,pLabel:PspirvOp):PSpirvOp; Var node:PSpirvOp; @@ -511,6 +536,28 @@ end; // +function TEmitOp.OpReturn(pLine:PspirvOp):PSpirvOp; +begin + Result:=AddSpirvOp(pLine,Op.OpReturn); +end; + +function TEmitOp.OpFunctionEnd(pLine:PspirvOp):PSpirvOp; +begin + Result:=AddSpirvOp(pLine,Op.OpFunctionEnd); +end; + +function TEmitOp.OpEmitVertex(pLine:PspirvOp):PSpirvOp; +begin + Result:=AddSpirvOp(pLine,Op.OpEmitVertex); +end; + +function TEmitOp.OpEndPrimitive(pLine:PspirvOp):PSpirvOp; +begin + Result:=AddSpirvOp(pLine,Op.OpEndPrimitive); +end; + +// + procedure TEmitOp.OpFmaF32(dst:PsrRegSlot;src0,src1,src2:PsrRegNode); begin //vdst = vsrc0.f * vsrc1.f + vdst.f -> fma @@ -549,6 +596,13 @@ begin Op3(Op.OpSelect,LazyType2(src0^.dtype,src1^.dtype),dst,cond,src1,src0); end; +function TEmitOp.OpSelectTo(src0,src1,cond:PsrRegNode):PsrRegNode; +begin + Result:=NewReg(LazyType2(src0^.dtype,src1^.dtype)); + // + _Op3(line,Op.OpSelect,Result,cond,src1,src0); +end; + procedure TEmitOp.OpIAddCar(pLine:PspirvOp;dst,car,src0,src1:PsrRegNode); Var node:PSpirvOp; @@ -1150,6 +1204,20 @@ begin end; end; +function TEmitOp.OpIModTo(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.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:PsrRegNode;ppLine:PPspirvOp=nil):PsrRegNode; diff --git a/spirv/srInput.pas b/spirv/srInput.pas index 305ad0b5..a019d47e 100644 --- a/spirv/srInput.pas +++ b/spirv/srInput.pas @@ -11,6 +11,7 @@ uses ginodes, srNode, srType, + srTypes, srReg, srOp, srConst, @@ -59,7 +60,9 @@ type itSampleId, itLayer, - itSubgroupLocalInvocationId + itSubgroupLocalInvocationId, + + itPosition ); ntInput=class(ntDescriptor) @@ -95,6 +98,7 @@ type Procedure Init(Emit:TCustomEmit); inline; function Search(itype:TpsslInputType;id:Byte):PsrInput; function Fetch(rtype:TsrDataType;itype:TpsslInputType;id:Byte):PsrInput; + function Fetch(pType:PsrType;itype:TpsslInputType;id:Byte):PsrInput; Function First:PsrInput; Function Next(node:PsrInput):PsrInput; procedure Test; @@ -149,6 +153,15 @@ begin end; function TsrInputList.Fetch(rtype:TsrDataType;itype:TpsslInputType;id:Byte):PsrInput; +var + pTypeList:PsrTypeList; +begin + pTypeList:=FEmit.GetTypeList; + // + Result:=Fetch(pTypeList^.Fetch(rtype),itype,id); +end; + +function TsrInputList.Fetch(pType:PsrType;itype:TpsslInputType;id:Byte):PsrInput; var node:TsrInput; begin @@ -162,7 +175,7 @@ begin Result:=FEmit.Alloc(SizeOf(TsrInput)); Move(node,Result^,SizeOf(TsrInput)); // - Result^.InitType(rtype,FEmit); + Result^.pType:=pType; Result^.InitVar(FEmit); // FNTree.Insert(Result); @@ -300,6 +313,11 @@ begin // end; + itPosition: + begin + pDecorateList^.OpDecorate(pVar,Decoration.BuiltIn,BuiltIn.Position); + end; + else Assert(false,'AllocBinding:'+GetEnumName(TypeInfo(TpsslInputType),ord(node^.key.itype))); end; diff --git a/spirv/srInterface.pas b/spirv/srInterface.pas index a6c4d224..83a97dbe 100644 --- a/spirv/srInterface.pas +++ b/spirv/srInterface.pas @@ -38,6 +38,13 @@ type x,y,z:DWORD; end; + TGeometryInfo=record + outputVertCount:DWORD; //4 + invocationCount:DWORD; //1 + InputMode :DWORD; //Triangles + OutputMode :DWORD; //OutputTriangleStrip + end; + PPSInputCntl=^TPSInputCntl; TPSInputCntl=packed record OFFSET :Byte; @@ -51,6 +58,7 @@ type FEarlyFragmentTests:Boolean; FPSInputCntl:array[0..31] of TPSInputCntl; FLocalSize:TLocalSize; + FGeometryInfo:TGeometryInfo; Config:TsrConfig; // FSPI:TSPI; diff --git a/spirv/srOp.pas b/spirv/srOp.pas index 5d10e7c9..60b86aeb 100644 --- a/spirv/srOp.pas +++ b/spirv/srOp.pas @@ -510,7 +510,7 @@ begin Result:=False; if not can_clear then Exit; - Assert(read_count=0); + Assert(read_count=0,IntToStr(OpId)); if is_write_op(OpId) then begin diff --git a/vulkan/vBuffer.pas b/vulkan/vBuffer.pas index 48c3e1bf..a02155fb 100644 --- a/vulkan/vBuffer.pas +++ b/vulkan/vBuffer.pas @@ -144,6 +144,7 @@ begin if (FHandle<>VK_NULL_HANDLE) then begin vkDestroyBuffer(Device.FHandle,FHandle,nil); + FHandle:=VK_NULL_HANDLE; end; // UnBindMem(True); diff --git a/vulkan/vCmdBuffer.pas b/vulkan/vCmdBuffer.pas index 629d171f..36a7ded0 100644 --- a/vulkan/vCmdBuffer.pas +++ b/vulkan/vCmdBuffer.pas @@ -189,7 +189,8 @@ type FRender:TvRenderPassBeginInfo; - Femulate_primtype:Integer; + Femulate_primtype:SmallInt; + Fshader_primtype :SmallInt; FinstanceCount:DWORD; FINDEX_TYPE:TVkIndexType; @@ -423,6 +424,7 @@ begin end; Femulate_primtype:=GP.Key.emulate_primtype; + Fshader_primtype :=GP.Key.shader_primtype; BindPipeline(BP_GRAPHICS,GP.FHandle); BindLayout (BP_GRAPHICS,GP.Key.FShaderGroup.FLayout); @@ -1541,6 +1543,8 @@ begin end; DI_PT_QUADLIST: begin + InsertLabel('DI_PT_QUADLIST'); + Assert(FinstanceCount<=1,'instance DI_PT_QUADLIST'); Assert(indexOffset=0,'OFFSET DI_PT_QUADLIST'); h:=indexCount div 4; @@ -1590,6 +1594,7 @@ begin Case Femulate_primtype of 0: begin + Inc(cmd_count); vkCmdDraw( FCmdbuf, indexCount, //vertexCount @@ -1598,8 +1603,10 @@ begin 0); //firstInstance end; - DI_PT_RECTLIST : + DI_PT_RECTLIST: begin + InsertLabel('DI_PT_RECTLIST'); + Assert(FinstanceCount<=1,'instance DI_PT_RECTLIST'); { VK_EXT_primitive_topology_list_restart ??? @@ -1610,23 +1617,41 @@ begin //0 1 2 //0 2 3 - h:=indexCount div 3; - if (h>0) then h:=h-1; - For i:=0 to h do + if (Fshader_primtype=-1) then begin + + h:=indexCount div 3; + if (h>0) then h:=h-1; + For i:=0 to h do + begin + Inc(cmd_count); + vkCmdDraw( + FCmdbuf, + 4, //vertexCount + 1, //instanceCount + 0, //firstVertex + 0); //firstInstance + end; + + end else + begin + //geom shader emulate + Inc(cmd_count); vkCmdDraw( - FCmdbuf, - 4, //vertexCount - 1, //instanceCount - 0, //firstVertex - 0); //firstInstance + FCmdbuf, + indexCount, //vertexCount + FinstanceCount, //instanceCount + 0, //firstVertex + 0); //firstInstance end; end; //DI_PT_LINELOOP :; DI_PT_QUADLIST: begin + InsertLabel('DI_PT_QUADLIST'); + Assert(FinstanceCount<=1,'instance DI_PT_QUADLIST'); h:=indexCount div 4; if (h>0) then h:=h-1; diff --git a/vulkan/vImageTiling.pas b/vulkan/vImageTiling.pas index 4fb23a3e..354e8ee4 100644 --- a/vulkan/vImageTiling.pas +++ b/vulkan/vImageTiling.pas @@ -823,6 +823,9 @@ begin set_tiling_cbs(kTileModeDepth_2dThin_64 ,0,@Load_Linear,@Writeback_Linear,@GetLinearAlignSize); //@load_clear; set_tiling_cbs(kTileModeDepth_2dThin_64 ,1,@Load_Linear,@Writeback_Linear,@GetLinearAlignSize); //@load_clear; + set_tiling_cbs(kTileModeThin_2dThin ,0,@Load_Linear,@Writeback_Linear,@GetLinearAlignSize); //@load_clear; + set_tiling_cbs(kTileModeThin_2dThin ,1,@Load_Linear,@Writeback_Linear,@GetLinearAlignSize); //@load_clear; + // set_tiling_cbs(kTileModeDepth_1dThin ,0,@load_1dThin,nil,@Get1dThinSize); set_tiling_cbs(kTileModeDepth_1dThin ,1,@load_1dThin,nil,@Get1dThinSize); @@ -838,6 +841,47 @@ begin set_tiling_cbs(kTileModeDisplay_LinearAligned,1,@Load_Linear,@Writeback_Linear,@GetLinearAlignSize); end; +function get_tiling_name(i:Byte):RawByteString; +begin + case i of + // Depth modes (for depth buffers) + kTileModeDepth_2dThin_64 :Result:='Depth_2dThin_64'; + kTileModeDepth_2dThin_128 :Result:='Depth_2dThin_128'; + kTileModeDepth_2dThin_256 :Result:='Depth_2dThin_256'; + kTileModeDepth_2dThin_512 :Result:='Depth_2dThin_512'; + kTileModeDepth_2dThin_1K :Result:='Depth_2dThin_1K'; + kTileModeDepth_1dThin :Result:='Depth_1dThin'; + kTileModeDepth_2dThinPrt_256:Result:='Depth_2dThinPrt_256'; + kTileModeDepth_2dThinPrt_1K :Result:='Depth_2dThinPrt_1K'; + // Display modes + kTileModeDisplay_LinearAligned:Result:='LinearAligned'; + kTileModeDisplay_1dThin :Result:='Display_1dThin'; + kTileModeDisplay_2dThin :Result:='Display_2dThin'; + kTileModeDisplay_ThinPrt :Result:='Display_ThinPrt'; + kTileModeDisplay_2dThinPrt :Result:='Display_2dThinPrt'; + // Thin modes (for non-displayable 1D/2D/3D + kTileModeThin_1dThin :Result:='Thin_1dThin'; + kTileModeThin_2dThin :Result:='Thin_2dThin'; + kTileModeThin_3dThin :Result:='Thin_3dThin'; + kTileModeThin_ThinPrt :Result:='Thin_ThinPrt'; + kTileModeThin_2dThinPrt:Result:='Thin_2dThinPrt'; + kTileModeThin_3dThinPrt:Result:='Thin_3dThinPrt'; + // Thick modes (for 3D textures) + kTileModeThick_1dThick :Result:='Thick_1dThick'; + kTileModeThick_2dThick :Result:='Thick_2dThick'; + kTileModeThick_3dThick :Result:='Thick_3dThick'; + kTileModeThick_ThickPrt :Result:='Thick_ThickPrt'; + kTileModeThick_2dThickPrt:Result:='Thick_2dThickPrt'; + kTileModeThick_3dThickPrt:Result:='Thick_3dThickPrt'; + kTileModeThick_2dXThick :Result:='Thick_2dXThick'; + kTileModeThick_3dXThick :Result:='Thick_3dXThick'; + // Hugely inefficient linear display mode - + kTileModeDisplay_LinearGeneral:Result:='LinearGeneral'; + else + Result:=IntToStr(i); + end; +end; + procedure pm4_load_from(cmd:TvCustomCmdBuffer;image:TvCustomImage2;IMAGE_USAGE:Byte); var cb:t_load_from_cb; @@ -862,8 +906,8 @@ begin if (cb=nil) then begin - Writeln(stderr,'tiling:'+IntToStr(image.key.params.tiling.idx)+' alt:'+IntToStr(image.key.params.tiling.alt)); - Assert (false ,'tiling:'+IntToStr(image.key.params.tiling.idx)+' alt:'+IntToStr(image.key.params.tiling.alt)); + Writeln(stderr,'tiling:'+get_tiling_name(image.key.params.tiling.idx)+' alt:'+IntToStr(image.key.params.tiling.alt)); + Assert (false ,'tiling:'+get_tiling_name(image.key.params.tiling.idx)+' alt:'+IntToStr(image.key.params.tiling.alt)); end; cmd.EndRenderPass; @@ -900,8 +944,8 @@ begin if (cb=nil) then begin - Writeln(stderr,'tiling:'+IntToStr(image.key.params.tiling.idx)+' alt:'+IntToStr(image.key.params.tiling.alt)); - Assert (false ,'tiling:'+IntToStr(image.key.params.tiling.idx)+' alt:'+IntToStr(image.key.params.tiling.alt)); + Writeln(stderr,'tiling:'+get_tiling_name(image.key.params.tiling.idx)+' alt:'+IntToStr(image.key.params.tiling.alt)); + Assert (false ,'tiling:'+get_tiling_name(image.key.params.tiling.idx)+' alt:'+IntToStr(image.key.params.tiling.alt)); end; cmd.EndRenderPass; @@ -928,8 +972,8 @@ begin if (cb=nil) then begin - Writeln(stderr,'tiling:'+IntToStr(key.params.tiling.idx)+' alt:'+IntToStr(key.params.tiling.alt)); - Assert (false ,'tiling:'+IntToStr(key.params.tiling.idx)+' alt:'+IntToStr(key.params.tiling.alt)); + Writeln(stderr,'tiling:'+get_tiling_name(key.params.tiling.idx)+' alt:'+IntToStr(key.params.tiling.alt)); + Assert (false ,'tiling:'+get_tiling_name(key.params.tiling.idx)+' alt:'+IntToStr(key.params.tiling.alt)); end; Result:=cb(key); diff --git a/vulkan/vPipelineManager.pas b/vulkan/vPipelineManager.pas index b5d28d73..aa8183c9 100644 --- a/vulkan/vPipelineManager.pas +++ b/vulkan/vPipelineManager.pas @@ -49,11 +49,12 @@ type viewportCount :Byte; provokingVertex :Byte; - emulate_primtype:Byte; + emulate_primtype:ShortInt; + shader_primtype :ShortInt; Procedure Clear; Procedure SetVertexInput(const FAttrBuilder:TvAttrBuilder); - Procedure SetPrimType(t:TVkPrimitiveTopology); + Procedure SetPrimType(t,s:Integer); Procedure SetPrimReset(enable:TVkBool32); Procedure SetProvoking(t:TVkProvokingVertexModeEXT); Procedure AddVPort(const V:TVkViewport;const S:TVkRect2D); @@ -166,19 +167,28 @@ begin vertexInputInfo.VertexAttributeDescriptions :=FAttrBuilder.FAttrDescs; end; -Procedure TvGraphicsPipelineKey.SetPrimType(t:TVkPrimitiveTopology); +Procedure TvGraphicsPipelineKey.SetPrimType(t,s:Integer); begin Case ord(t) of ord(VK_PRIMITIVE_TOPOLOGY_POINT_LIST)..ord(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY): begin - inputAssembly.topology:=t; + inputAssembly.topology:=TVkPrimitiveTopology(t); emulate_primtype:=0; + shader_primtype :=-1; end; DI_PT_RECTLIST: begin - inputAssembly.topology:=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; emulate_primtype:=ord(t); + if (s<>-1) then + begin + inputAssembly.topology:=TVkPrimitiveTopology(s); + shader_primtype:=s; + end else + begin + inputAssembly.topology:=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + shader_primtype :=-1; + end; end; DI_PT_LINELOOP , DI_PT_QUADLIST , @@ -187,6 +197,7 @@ begin begin inputAssembly.topology:=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN; emulate_primtype:=ord(t); + shader_primtype :=-1; end; end; diff --git a/vulkan/vRectGS.pas b/vulkan/vRectGS.pas new file mode 100644 index 00000000..fa9e9591 --- /dev/null +++ b/vulkan/vRectGS.pas @@ -0,0 +1,185 @@ +unit vRectGS; + +{$mode ObjFPC}{$H+} + +interface + +uses + Classes, + + Vulkan, + + spirv, + srNode, + srType, + srTypes, + srReg, + srVariable, + srOutput, + + SprvEmit; + +function CompileRectangleGeometryShader():TMemoryStream; + +implementation + +function interpolate(SprvEmit:TSprvEmit; + rtype :TsrDataType; + barycentric,inputs:PPsrRegNode):PsrRegNode; +var + tmp:array[0..2] of PsrRegNode; + // + i:Byte; +begin + For i:=0 to 2 do + begin + tmp[i]:=SprvEmit.NewReg(rtype); + // + SprvEmit._Op2(SprvEmit.line,Op.OpVectorTimesScalar,tmp[i],inputs[i],barycentric[i]); + end; + // + Result:=SprvEmit.OpFAddTo(tmp[0],tmp[1]); + Result:=SprvEmit.OpFAddTo(Result,tmp[2]); +end; + +function CompileRectangleGeometryShader():TMemoryStream; +var + SprvEmit:TSprvEmit; + // + pVec4f :PsrType; + InputPos :PsrVariable; + OutputPos :PsrVariable; + pChain :PsrNode; + UintId :array[0..3] of PsrRegNode; + Positions :array[0..3] of PsrRegNode; + positionsX :array[0..2] of PsrRegNode; + positionsY :array[0..2] of PsrRegNode; + CoordEqualX:array[0..2] of PsrRegNode; + CoordEqualY:array[0..2] of PsrRegNode; + EdgeVertex :array[0..2] of PsrRegNode; + barycentric:array[0..2] of PsrRegNode; + xyEqual :PsrRegNode; + yxEqual :PsrRegNode; + pOneId :PsrRegNode; + pMinusOne :PsrRegNode; + pIndex :PsrRegNode; + // + i:Byte; +begin + Result:=nil; + SprvEmit:=TSprvEmit.Create; + + SprvEmit.InitCustomGs(); + + pVec4f :=SprvEmit.TypeList.Fetch(dtVec4f); + + InputPos :=SprvEmit.AddPositionsInput(3); + OutputPos:=SprvEmit.FetchOutput(etPos0,dtVec4f); + + //gen const id + For i:=0 to 3 do + begin + UintId[i]:=SprvEmit.NewReg_i(dtUint32,i); + end; + + //load positions + For i:=0 to 2 do + begin + pChain:=SprvEmit.OpAccessChainTo(SprvEmit.line,pVec4f,InputPos,UintId[i]); + // + Positions[i]:=SprvEmit.OpLoadTo(SprvEmit.line,pVec4f,pChain); + end; + + //extract + For i:=0 to 2 do + begin + positionsX[i]:=SprvEmit.NewReg(dtFloat32); + positionsY[i]:=SprvEmit.NewReg(dtFloat32); + // + SprvEmit.OpExtract(SprvEmit.line,positionsX[i],Positions[i],0); + SprvEmit.OpExtract(SprvEmit.line,positionsY[i],Positions[i],1); + end; + + //compare + For i:=0 to 2 do + begin + CoordEqualX[i]:=SprvEmit.NewReg(dtBool); + CoordEqualY[i]:=SprvEmit.NewReg(dtBool); + // + SprvEmit._Op2(SprvEmit.line,Op.OpFOrdEqual,CoordEqualX[i],positionsX[i],positionsX[(i + 1) mod 3]); + SprvEmit._Op2(SprvEmit.line,Op.OpFOrdEqual,CoordEqualY[i],positionsY[i],positionsY[(i + 1) mod 3]); + end; + + pOneId :=SprvEmit.NewReg_s(dtFloat32, 1); + pMinusOne:=SprvEmit.NewReg_s(dtFloat32,-1); + + //calc barycentric + For i:=0 to 2 do + begin + xyEqual:=SprvEmit.OpAndTo(CoordEqualX[i], CoordEqualY[(i + 2) mod 3]); + yxEqual:=SprvEmit.OpAndTo(CoordEqualY[i], CoordEqualX[(i + 2) mod 3]); + // + EdgeVertex[i]:=SprvEmit.OpOrTo(xyEqual,yxEqual); + // + barycentric[i]:=SprvEmit.OpSelectTo(pOneId,pMinusOne,EdgeVertex[i]); + end; + + //calc last pos + Positions[3]:=interpolate(SprvEmit,dtVec4f,@barycentric,@Positions); + + //select first index + pIndex:=SprvEmit.OpSelectTo(UintId[0], UintId[1], EdgeVertex[1]); + pIndex:=SprvEmit.OpSelectTo(pIndex , UintId[2], EdgeVertex[2]); + + //Send vertex by index + For i:=0 to 2 do + begin + pChain:=SprvEmit.OpAccessChainTo(SprvEmit.line,pVec4f,InputPos,pIndex); + // + Positions[i]:=SprvEmit.OpLoadTo(SprvEmit.line,pVec4f,pChain); + // + + SprvEmit.OpStore(SprvEmit.line,OutputPos,Positions[i]); + + //emit input attr + + //end vertex + SprvEmit.OpEmitVertex(SprvEmit.line); + + if (i<>2) then + begin + //next index + pIndex:=SprvEmit.OpIAddTo(pIndex,UintId[1]); + pIndex:=SprvEmit.OpIModTo(pIndex,UintId[3]); + end; + end; //for + + //send last vertex + SprvEmit.OpStore(SprvEmit.line,OutputPos,Positions[3]); + + //emit input attr + + //end vertex + SprvEmit.OpEmitVertex(SprvEmit.line); + + //end prim + SprvEmit.OpEndPrimitive(SprvEmit.line); + + //end function + SprvEmit.OpReturn(SprvEmit.line); + SprvEmit.OpFunctionEnd(SprvEmit.line); + + //ending stage + SprvEmit.PostStage; + SprvEmit.AllocStage; + + //SprvEmit.Print; + + Result:=TMemoryStream.Create; + SprvEmit.SaveToStream(Result); + + SprvEmit.Free; +end; + +end. + diff --git a/vulkan/vRegs2Vulkan.pas b/vulkan/vRegs2Vulkan.pas index 8a3adf05..4f6a2f5d 100644 --- a/vulkan/vRegs2Vulkan.pas +++ b/vulkan/vRegs2Vulkan.pas @@ -108,7 +108,7 @@ type Function GET_MULTISAMPLE:TVkPipelineMultisampleStateCreateInfo; function GET_PRIM_RESET:TVkBool32; - function GET_PRIM_TYPE :TVkPrimitiveTopology; + function GET_PRIM_TYPE :Integer; function GET_INDEX_TYPE:TVkIndexType; function get_reg(i:word):DWORD; @@ -1483,26 +1483,26 @@ begin end; end; -function TGPU_REGS.GET_PRIM_TYPE:TVkPrimitiveTopology; +function TGPU_REGS.GET_PRIM_TYPE:Integer; begin case UC_REG^.VGT_PRIMITIVE_TYPE.PRIM_TYPE of - DI_PT_POINTLIST :Result:=VK_PRIMITIVE_TOPOLOGY_POINT_LIST ; - DI_PT_LINELIST :Result:=VK_PRIMITIVE_TOPOLOGY_LINE_LIST ; - DI_PT_LINESTRIP :Result:=VK_PRIMITIVE_TOPOLOGY_LINE_STRIP ; - DI_PT_TRILIST :Result:=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST ; - DI_PT_TRIFAN :Result:=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN ; - DI_PT_TRISTRIP :Result:=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP ; - DI_PT_PATCH :Result:=VK_PRIMITIVE_TOPOLOGY_PATCH_LIST ; - DI_PT_LINELIST_ADJ :Result:=VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY ; - DI_PT_LINESTRIP_ADJ:Result:=VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY ; - DI_PT_TRILIST_ADJ :Result:=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY ; - DI_PT_TRISTRIP_ADJ :Result:=VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY; + DI_PT_POINTLIST :Result:=ord(VK_PRIMITIVE_TOPOLOGY_POINT_LIST) ; + DI_PT_LINELIST :Result:=ord(VK_PRIMITIVE_TOPOLOGY_LINE_LIST) ; + DI_PT_LINESTRIP :Result:=ord(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP) ; + DI_PT_TRILIST :Result:=ord(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST) ; + DI_PT_TRIFAN :Result:=ord(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) ; + DI_PT_TRISTRIP :Result:=ord(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP) ; + DI_PT_PATCH :Result:=ord(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST) ; + DI_PT_LINELIST_ADJ :Result:=ord(VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY) ; + DI_PT_LINESTRIP_ADJ:Result:=ord(VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY) ; + DI_PT_TRILIST_ADJ :Result:=ord(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY) ; + DI_PT_TRISTRIP_ADJ :Result:=ord(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY); DI_PT_RECTLIST , DI_PT_LINELOOP , DI_PT_QUADLIST , DI_PT_QUADSTRIP , - DI_PT_POLYGON :Result:=TVkPrimitiveTopology(UC_REG^.VGT_PRIMITIVE_TYPE.PRIM_TYPE); //need to emulate + DI_PT_POLYGON :Result:=UC_REG^.VGT_PRIMITIVE_TYPE.PRIM_TYPE; //need to emulate else Assert(False,'unknow prim type:0x'+HexStr(UC_REG^.VGT_PRIMITIVE_TYPE.PRIM_TYPE,1)); @@ -1946,10 +1946,8 @@ begin Result.params.mipLevels:=PT^.last_level+1; end; - //Assert(Result.params.mipLevels=1,'TODO'); - //Result.params.mipLevels:=1; ///// - Result.params.arrayLayers:=1; + Result.params.pitch :=Result.params.width; //TODO: Calculate padding by tilling mode Result.params.pad_width :=Result.params.width; diff --git a/vulkan/vShader.pas b/vulkan/vShader.pas index 819abf1e..0ac382a3 100644 --- a/vulkan/vShader.pas +++ b/vulkan/vShader.pas @@ -54,6 +54,7 @@ type procedure LoadFromStream(Stream:TStream); procedure LoadFromFile(const FileName:RawByteString); procedure LoadFromResource(const FileName:RawByteString); + procedure SetObjectName(const name:RawByteString); end; /// @@ -178,6 +179,11 @@ begin Stream.Free; end; +procedure TvShader.SetObjectName(const name:RawByteString); +begin + DebugReport.SetObjectName(VK_OBJECT_TYPE_SHADER_MODULE,FHandle,PChar(name)); +end; + type PSPIRVHeader=^TSPIRVHeader; TSPIRVHeader=packed record diff --git a/vulkan/vShaderExt.pas b/vulkan/vShaderExt.pas index c4d8ae5e..374961c5 100644 --- a/vulkan/vShaderExt.pas +++ b/vulkan/vShaderExt.pas @@ -109,6 +109,8 @@ type INPUT_CNTL :A_INPUT_CNTL; end; + FGeomRectList:TvShaderExt; + procedure ClearInfo; override; Destructor Destroy; override; function parser:CvShaderParser; override; @@ -133,6 +135,8 @@ type Procedure SetInstance (VGPR_COMP_CNT:Byte;STEP_RATE_0,STEP_RATE_1:DWORD); Procedure SET_SHADER_CONTROL(const SHADER_CONTROL:TDB_SHADER_CONTROL); Procedure SET_INPUT_CNTL (const INPUT_CNTL:A_INPUT_CNTL;NUM_INTERP:Byte); + function IsCSClearShader:Boolean; + function IsVSRectListShader:Boolean; end; TBufBindExt=packed record @@ -179,6 +183,7 @@ type PvShadersKey=^TvShadersKey; TvShadersKey=object FShaders:AvShaderStage; + FPrimtype:Integer; Procedure SetLSShader(Shader:TvShaderExt); Procedure SetHSShader(Shader:TvShaderExt); Procedure SetESShader(Shader:TvShaderExt); @@ -253,6 +258,8 @@ type function GetSharpByPatch(pUserData,pImmData:Pointer;const addr:ADataLayout):Pointer; +function IsClearDepthShaders(const FShaders:AvShaderStage):Boolean; inline; + implementation uses @@ -772,6 +779,38 @@ begin Move(INPUT_CNTL,FParams.INPUT_CNTL,SizeOf(TSPI_PS_INPUT_CNTL_0)*NUM_INTERP); end; +function TvShaderExt.IsCSClearShader:Boolean; +begin + if (self=nil) then Exit(False); + + Result:=(FHash_gcn=$7DCE68F83F66B337); +end; + +function TvShaderExt.IsVSRectListShader:Boolean; +begin + if (self=nil) then Exit(False); + + Result:=(FHash_gcn=$00DF6E6331449451); +end; + +function IsClearDepthShaders(const FShaders:AvShaderStage):Boolean; inline; +begin + Result:=False; + + if (FShaders[vShaderStageLs]=nil) and + (FShaders[vShaderStageHs]=nil) and + (FShaders[vShaderStageEs]=nil) and + (FShaders[vShaderStageGs]=nil) and + (FShaders[vShaderStageVs]<>nil) and + (FShaders[vShaderStagePs]<>nil) and + (FShaders[vShaderStageCs]=nil) then + + if (FShaders[vShaderStageVs].FHash_gcn=QWORD($00DF6E6331449451)) and + (FShaders[vShaderStagePs].FHash_gcn=QWORD($E9FF5D4699E5B9AD)) then + begin + Result:=True; + end; +end; /// diff --git a/vulkan/vShaderManager.pas b/vulkan/vShaderManager.pas index a618d037..e711c9ca 100644 --- a/vulkan/vShaderManager.pas +++ b/vulkan/vShaderManager.pas @@ -7,6 +7,7 @@ interface uses SysUtils, Classes, + Vulkan, murmurhash, g23tree, ps4_pssl, @@ -15,6 +16,7 @@ uses vRegs2Vulkan, shader_dump, + si_ci_vi_merged_enum, si_ci_vi_merged_registers, vDevice, @@ -91,6 +93,8 @@ function GetDumpSpvName(FStage:TvShaderStage;hash:QWORD):RawByteString; implementation uses + vRectGS, + // kern_rwlock, kern_dmem; @@ -555,6 +559,11 @@ begin //set hash FShader.FHash_spv:=FHash_spv; + //setname + FShader.SetObjectName(LowerCase(STAGE_NAME[FStage])+ + '_gcn:0x'+HexStr(FShader.FHash_gcn,16)+ + '_spv:0x'+HexStr(FShader.FHash_spv,16)); + //free spv data M.Free; @@ -671,6 +680,43 @@ begin FShaderGroupSet.Unlock_wr; end; +procedure EmitShaderGroupExtension(var GPU_REGS:TGPU_REGS;F:PvShadersKey); +Var + M:TMemoryStream; + VS:TvShaderExt; + GS:TvShaderExt; +begin + VS:=F^.FShaders[vShaderStageVs]; + + if (VS<>nil) and + (not VS.IsVSRectListShader) and + (ord(GPU_REGS.GET_PRIM_TYPE)=DI_PT_RECTLIST) then + begin + Assert(F^.FShaders[vShaderStageGs]=nil,'Geometry shader is already present'); + + GS:=VS.FGeomRectList; + + if (GS=nil) then + begin + M:=CompileRectangleGeometryShader(); + //M.SaveToFile('rect_geom.spv'); + + GS:=TvShaderExt.Create; + GS.LoadFromStream(M); + + GS.SetObjectName('GS_RECT'); + + M.Free; + + VS.FGeomRectList:=GS; + end; + + F^.FShaders[vShaderStageGs]:=GS; + F^.FPrimtype:=ord(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST); + // + end; +end; + function FetchShaderGroupRT(var GPU_REGS:TGPU_REGS;pc:PPushConstAllocator):TvShaderGroup; var FShadersKey:TvShadersKey; @@ -678,6 +724,7 @@ var FDescSetId:Integer; begin FShadersKey:=Default(TvShadersKey); + FShadersKey.FPrimtype:=-1; FDescSetId:=0; @@ -691,6 +738,8 @@ begin end; end; + EmitShaderGroupExtension(GPU_REGS,@FShadersKey); + Result:=FetchShaderGroup(@FShadersKey); end; @@ -699,6 +748,7 @@ var FShadersKey:TvShadersKey; begin FShadersKey:=Default(TvShadersKey); + FShadersKey.FPrimtype:=-1; FShadersKey.FShaders[vShaderStageCs]:=FetchShader(vShaderStageCs,0,GPU_REGS,pc);