This commit is contained in:
Pavel 2022-06-27 16:20:39 +03:00
parent 389e164e5a
commit ff15a1e819
5 changed files with 180 additions and 56 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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];

View File

@ -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;