mirror of https://github.com/red-prig/fpPS4.git
This commit is contained in:
parent
389e164e5a
commit
ff15a1e819
|
@ -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:=(val<ref);
|
||||
WAIT_REG_MEM_FUNC_LESS_EQUAL :Result:=(val<=ref);
|
||||
WAIT_REG_MEM_FUNC_EQUAL :Result:=(val=ref);
|
||||
WAIT_REG_MEM_FUNC_NOT_EQUAL :Result:=(val<>ref);
|
||||
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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 (bufferIndex<SCE_VIDEO_OUT_BUFFER_NUM_MAX) then
|
||||
begin
|
||||
spin_lock(H.FBuffers.lock);
|
||||
Result:=H.FBuffers.addr[bufferIndex];
|
||||
spin_unlock(H.FBuffers.lock);
|
||||
end;
|
||||
_sig_unlock;
|
||||
|
||||
if (H=nil) then Exit(SCE_VIDEO_OUT_ERROR_INVALID_HANDLE);
|
||||
ptr^:=@H.FLabels;
|
||||
|
||||
_sig_lock;
|
||||
H.Release;
|
||||
_sig_unlock;
|
||||
|
||||
Result:=0;
|
||||
end;
|
||||
|
||||
function _on_after(node:PKEventNode;data:Pointer):Boolean;
|
||||
|
@ -1038,6 +1048,7 @@ begin
|
|||
//ps4_usleep(150);
|
||||
end else
|
||||
begin
|
||||
|
||||
spin_lock(FBuffers.lock);
|
||||
addr:=FBuffers.addr[bufferIndex];
|
||||
attr:=FBuffers.attr[bufferIndex];
|
||||
|
@ -1076,18 +1087,17 @@ begin
|
|||
//post_event_flip(flipArg);
|
||||
end;
|
||||
|
||||
node^.wait:=1;
|
||||
free_node(node);
|
||||
|
||||
//FlipRate:=20;
|
||||
if (flipMode=SCE_VIDEO_OUT_FLIP_MODE_VSYNC) then
|
||||
if (FlipRate<>0) 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<time) then
|
||||
begin
|
||||
|
@ -1106,13 +1116,13 @@ begin
|
|||
//t2:=(t2+9) div 10;
|
||||
//Writeln('elap=',elap,' time=',time,' usleep=',t2);
|
||||
|
||||
if (FGpuFlip<>nil) then
|
||||
if (FGpuFlip<>nil) and (bufferIndex<>SCE_VIDEO_OUT_BUFFER_INDEX_BLANK) then
|
||||
begin
|
||||
FGpuFlip.IsComplite(FlipStatus.FcurrentBuffer);
|
||||
//While (not FGpuFlip.IsComplite(FcurrentBuffer)) do
|
||||
//begin
|
||||
// ps4_usleep(150);
|
||||
//end;
|
||||
//FGpuFlip.IsComplite(bufferIndex);
|
||||
While (not FGpuFlip.IsComplite(bufferIndex)) do
|
||||
begin
|
||||
ps4_usleep(150);
|
||||
end;
|
||||
end;
|
||||
|
||||
end;
|
||||
|
@ -1122,6 +1132,8 @@ begin
|
|||
post_event_vblank(flipArg);
|
||||
end else
|
||||
begin
|
||||
System.InterlockedDecrement64(FLabels[bufferIndex]);
|
||||
|
||||
post_event_flip(flipArg);
|
||||
post_event_vblank(flipArg);
|
||||
end;
|
||||
|
@ -1155,8 +1167,8 @@ begin
|
|||
end;
|
||||
end;
|
||||
|
||||
node^.wait:=1;
|
||||
free_node(node);
|
||||
//node^.wait:=1;
|
||||
//free_node(node);
|
||||
|
||||
end;
|
||||
|
||||
|
@ -1179,9 +1191,7 @@ begin
|
|||
_sig_unlock;
|
||||
if (H=nil) then Exit(SCE_VIDEO_OUT_ERROR_INVALID_HANDLE);
|
||||
|
||||
_sig_lock;
|
||||
node:=H.alloc_node;
|
||||
_sig_unlock;
|
||||
|
||||
if (node=nil) then
|
||||
begin
|
||||
|
@ -1189,6 +1199,11 @@ begin
|
|||
Exit(SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL);
|
||||
end;
|
||||
|
||||
if (bufferIndex<>SCE_VIDEO_OUT_BUFFER_INDEX_BLANK) then
|
||||
begin
|
||||
System.InterlockedIncrement64(H.FLabels[bufferIndex]);
|
||||
end;
|
||||
|
||||
node^.Parent:=@H.sceVideoOutSubmitFlip;
|
||||
node^.u.bufferIndex:=bufferIndex;
|
||||
node^.u.flipMode :=flipMode;
|
||||
|
@ -1242,6 +1257,11 @@ begin
|
|||
Exit(SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL);
|
||||
end;
|
||||
|
||||
if (Flip^.bufferIndex<>SCE_VIDEO_OUT_BUFFER_INDEX_BLANK) then
|
||||
begin
|
||||
System.InterlockedIncrement64(H.FLabels[Flip^.bufferIndex]);
|
||||
end;
|
||||
|
||||
node^.Parent:=@H.sceVideoOutSubmitFlip;
|
||||
node^.u.bufferIndex:=Flip^.bufferIndex;
|
||||
node^.u.flipMode :=Flip^.flipMode;
|
||||
|
|
|
@ -618,23 +618,35 @@ begin
|
|||
|
||||
buf:=@FBuffers[FcurrentBuffer];
|
||||
|
||||
if (Ffilp_shader=nil) then Exit;
|
||||
|
||||
if not buf^.IsPrepare then Exit;
|
||||
|
||||
if (FSwapChain=nil) then recreateSwapChain;
|
||||
if (FSwapChain.FHandle=VK_NULL_HANDLE) then
|
||||
if (Ffilp_shader=nil) then
|
||||
begin
|
||||
recreateSwapChain;
|
||||
if (FSwapChain.FHandle=VK_NULL_HANDLE) then Exit;
|
||||
buf^.cmdbuf.ret:=1;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
if not FSetLayout.Compile then Exit;
|
||||
if not FLayout.Compile then Exit;
|
||||
if not FPipelineFlip.Compile then Exit;
|
||||
if not FSetsPool.Compile then Exit;
|
||||
if (not buf^.IsPrepare) or
|
||||
(not FSetLayout.Compile) or
|
||||
(not FLayout.Compile) or
|
||||
(not FPipelineFlip.Compile) or
|
||||
(not FSetsPool.Compile) then
|
||||
begin
|
||||
buf^.cmdbuf.ret:=2;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
repeat
|
||||
|
||||
if (FSwapChain=nil) then recreateSwapChain;
|
||||
if (FSwapChain.FHandle=VK_NULL_HANDLE) then
|
||||
begin
|
||||
recreateSwapChain;
|
||||
if (FSwapChain.FHandle=VK_NULL_HANDLE) then
|
||||
begin
|
||||
buf^.cmdbuf.ret:=3;
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
FixCurrentFrame;
|
||||
imageAvailableSemaphore:=FimageAvailableSemaphore[FcurrentFrame];
|
||||
renderFinishedSemaphore:=FrenderFinishedSemaphore[FcurrentFrame];
|
||||
|
@ -655,6 +667,7 @@ begin
|
|||
Exit;
|
||||
end;
|
||||
end;
|
||||
|
||||
until false;
|
||||
SwapImage:=FSwapChain.FImages[imageIndex];
|
||||
|
||||
|
|
|
@ -436,6 +436,8 @@ begin
|
|||
if (cmd=nil) then Exit;
|
||||
if (not cmd.BeginCmdBuffer) then Exit;
|
||||
|
||||
rwlock_wrlock(lock);
|
||||
|
||||
if Barrier.Push(cmd.cmdbuf,
|
||||
FHandle,
|
||||
GetSubresRange,
|
||||
|
@ -445,6 +447,8 @@ begin
|
|||
begin
|
||||
Inc(cmd.cmd_count);
|
||||
end;
|
||||
|
||||
rwlock_unlock(lock);
|
||||
end;
|
||||
|
||||
procedure TvHostImage2.PushBarrier(cmd:TvCustomCmdBuffer;
|
||||
|
|
Loading…
Reference in New Issue