diff --git a/chip/ps4_videodrv.pas b/chip/ps4_videodrv.pas index e3cb8930..4f28ec1b 100644 --- a/chip/ps4_videodrv.pas +++ b/chip/ps4_videodrv.pas @@ -114,7 +114,15 @@ type Interrupt:Boolean; end; - TvMicroEngineType=(metCmdBuffer,metFlip,metEop); + PvMeWaitMemInfo=^TvMeWaitMemInfo; + TvMeWaitMemInfo=record + adr:Pointer; + ref:DWORD; + mask:DWORD; + cFunc:Byte; + end; + + TvMicroEngineType=(metCmdBuffer,metFlip,metEop,metWaitMem); PvMicroEngineNode=^TvMicroEngineNode; TvMicroEngineNode=record @@ -126,6 +134,7 @@ type 0:(CmdBuffer:TvCmdBuffer); 1:(FlipInfo:TvMeFlipInfo); 2:(EopInfo:TvMeEopInfo); + 3:(WaitMem:TvMeWaitMemInfo); end; TvMicroEngine=object @@ -136,6 +145,7 @@ type Procedure PushCmd(var Cmd:TvCmdBuffer); Procedure PushFlip(var qcInfo:TqcFlipInfo;FlipLData:DWORD;FlipLabel:PDWORD;Interrupt:Boolean); Procedure PushEop(adr:Pointer;data:QWORD;dataSel:Byte;Interrupt:Boolean); + Procedure PushWaitMem(adr:Pointer;ref,mask:DWORD;cFunc:Byte); end; var @@ -145,6 +155,8 @@ var GFXRing:TvCmdRing; GFXMicroEngine:TvMicroEngine; + FIdleEvent:PRTLEvent=nil; + GPU_REGS:TGPU_REGS; FCmdPool:TvCmdPool; @@ -250,6 +262,22 @@ begin Queue.Push(node); end; +Procedure TvMicroEngine.PushWaitMem(adr:Pointer;ref,mask:DWORD;cFunc:Byte); +var + node:PvMicroEngineNode; +begin + node:=AllocMem(SizeOf(TvMicroEngineNode)); + if (node=nil) then Exit; + + node^.mode :=metWaitMem; + node^.WaitMem.adr :=adr; + node^.WaitMem.ref :=ref; + node^.WaitMem.mask :=mask; + node^.WaitMem.cFunc:=cFunc; + + Queue.Push(node); +end; + procedure gfx_cp_parser(node:PvSubmitInfo); forward; function gfx_submit(CmdBuffer:TvCmdBuffer):Boolean; forward; function gfx_test(CmdBuffer:TvCmdBuffer):Boolean; forward; @@ -296,6 +324,25 @@ begin end; end; +Function me_test_mem(node:PvMeWaitMemInfo):Boolean; +var + val,ref:DWORD; +begin + val:=PDWORD(node^.adr)^ and node^.mask; + ref:=node^.ref; + Case node^.cFunc of + WAIT_REG_MEM_FUNC_ALWAYS :Result:=True; + WAIT_REG_MEM_FUNC_LESS :Result:=(valref); + WAIT_REG_MEM_FUNC_GREATER_EQUAL:Result:=(val>ref); + WAIT_REG_MEM_FUNC_GREATER :Result:=(val>=ref); + else + Assert(false); + end; +end; + Function me_node_test(node:PvMicroEngineNode):Boolean; begin Result:=True; @@ -306,7 +353,14 @@ begin begin Result:=gfx_test(node^.CmdBuffer); end; - else; + metFlip:Result:=True; + metEop :Result:=True; + metWaitMem: + begin + Result:=me_test_mem(@node^.WaitMem); + end; + else + Assert(false); end; end; @@ -329,6 +383,9 @@ begin begin Result:=me_eop(@node^.EopInfo); end; + metWaitMem:; + else + Assert(false); end; end; @@ -351,7 +408,7 @@ begin begin if not me_node_test(GFXMicroEngine.Current) then begin - time:=-1000000; + time:=-100000; NtDelayExecution(True,@time); Continue; end; @@ -366,6 +423,7 @@ begin if not work_do then begin + RTLEventSetEvent(FIdleEvent); time:=Int64(NT_INFINITE); NtDelayExecution(True,@time); end; @@ -383,6 +441,9 @@ begin GFXRing.Init; GFXMicroEngine.Init; + FIdleEvent:=RTLEventCreate; + RTLEventSetEvent(FIdleEvent); + t:=BeginThread(@GFX_thread); _gfx_handle:=t; @@ -521,14 +582,19 @@ begin node^.Flip:=Flip^; end; + RTLEventResetEvent(FIdleEvent); GFXRing.Queue.Push(node); NtQueueApcThread(_gfx_handle,@_apc_null,0,nil,0); end; procedure vSubmitDone; begin + if (FIdleEvent<>nil) then + begin + RTLEventWaitFor(FIdleEvent); + end; //Sleep(100); - Device.WaitIdle; + //Device.WaitIdle; end; @@ -819,20 +885,22 @@ begin end; procedure onWaitRegMem(pm4Hdr:PM4_TYPE_3_HEADER;Body:PPM4CMDWAITREGMEM); +var + adr:Pointer; begin {$ifdef ww} Case Body^.engine of - 0: //ME + WAIT_REG_MEM_ENGINE_ME: Case Body^.memSpace of - 0:Writeln(' waitOnRegister'); - 1:Writeln(' waitOnAddress'); + WAIT_REG_MEM_SPACE_REGISTER:Writeln(' waitOnRegister'); + WAIT_REG_MEM_SPACE_MEMORY :Writeln(' waitOnAddress'); else Assert(false); end; - 1: //PFP + WAIT_REG_MEM_ENGINE_PFP: Case Body^.memSpace of - 0:Writeln(' waitOnRegisterAndStall'); - 1:Writeln(' waitOnAddressAndStall'); + WAIT_REG_MEM_SPACE_REGISTER:Writeln(' waitOnRegisterAndStall'); + WAIT_REG_MEM_SPACE_MEMORY :Writeln(' waitOnAddressAndStall'); else Assert(false); end; @@ -840,6 +908,26 @@ begin Assert(false); end; {$endif} + + Case Body^.engine of + WAIT_REG_MEM_ENGINE_ME: + Case Body^.memSpace of + WAIT_REG_MEM_SPACE_MEMORY: + begin + + QWORD(adr):=QWORD(Body^.pollAddressLo) or (QWORD(Body^.pollAddressHi) shl $20); + + GFXMicroEngine.PushCmd(GFXRing.CmdBuffer); + GFXMicroEngine.PushWaitMem(adr,Body^.reference,Body^.mask,Body^.compareFunc); + + end; + else + Assert(false); + end; + else + Assert(false); + end; + end; procedure onPm40(pm4Hdr:PM4_TYPE_0_HEADER;Body:PDWORD); diff --git a/ps4_libscegnmdriver.pas b/ps4_libscegnmdriver.pas index 7f2f112d..33ee1bff 100644 --- a/ps4_libscegnmdriver.pas +++ b/ps4_libscegnmdriver.pas @@ -519,16 +519,15 @@ end; // called in waitUntilSafeForRendering function ps4_sceGnmInsertWaitFlipDone(cmdBuffer:PDWORD;numDwords:DWORD;videoOutHandle,displayBufferIndex:Integer):Integer; SysV_ABI_CDecl; var - addr:Pointer; + addr:PInt64; begin Result:=-1; if (numDwords<>7) then Exit; - //sceVideoOutGetBufferLabelAddress(videoOutHandle,&base); - //addr = base + (ulong)(uint)displayBufferIndex * 8; - _sig_lock; - addr:=_VideoOutGetBufferAdr(videoOutHandle,displayBufferIndex); - _sig_unlock; - if (addr=nil) then Exit; + + Result:=ps4_sceVideoOutGetBufferLabelAddress(videoOutHandle,@addr); + if (Result<>0) then Exit(-1); + + addr:=@addr[displayBufferIndex]; cmdBuffer[0]:=$c0053c00; //IT_WAIT_REG_MEM cmdBuffer[1]:=$13; diff --git a/ps4_libscevideoout.pas b/ps4_libscevideoout.pas index f14558a2..78cd5d39 100644 --- a/ps4_libscevideoout.pas +++ b/ps4_libscevideoout.pas @@ -214,7 +214,10 @@ const SCE_VIDEO_OUT_ERROR_UNKNOWN =-2144796418; // 0x802900FE */ SCE_VIDEO_OUT_ERROR_ENOMEM =-2144792564; // 0x8029100C */ -function _VideoOutGetBufferAdr(hVideo:Integer;bufferIndex:Integer):Pointer; +type + PPInt64=^PInt64; + +function ps4_sceVideoOutGetBufferLabelAddress(hVideo:Integer;ptr:PPInt64):Integer; SysV_ABI_CDecl; Procedure App_Run; @@ -234,6 +237,7 @@ implementation uses vFlip, sys_signal, + sys_kernel, sys_time, ps4_time, spinlock, @@ -377,6 +381,8 @@ type FcurrentBuffer:Longint; end; + FLabels:array[0..15] of Int64; + //(MAIN port: 1 to 16, AUX port: 1 to 8) FBuffers:record lock:Pointer; @@ -449,7 +455,7 @@ begin Acqure; Exit(n); end; - System.ThreadSwitch; + SwYieldExecution; until false; end; @@ -939,20 +945,24 @@ begin H.Release; end; -function _VideoOutGetBufferAdr(hVideo:Integer;bufferIndex:Integer):Pointer; +function ps4_sceVideoOutGetBufferLabelAddress(hVideo:Integer;ptr:PPInt64):Integer; SysV_ABI_CDecl; var H:TVideoOut; begin - Result:=nil; + if (ptr=nil) then Exit(SCE_VIDEO_OUT_ERROR_INVALID_ADDRESS); + + _sig_lock; H:=TVideoOut(FVideoOutMap.Acqure(hVideo)); - if (H=nil) then Exit; - if (bufferIndex>=0) and (bufferIndex0) then begin - time:=(1000000 div (FlipRate+1)); //+5 selected empirically - //time:=time-1300; - //time:=time-1300; + time:=(1000000 div (FlipRate{+1})); elap:=SwTimePassedUnits(FlipStatus.Ftsc_flips); - elap:=(elap+9) div 10; - - //elap:=elap+(elap div 100)*14; + elap:=((elap+9) div 10)+120; if (elap