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; Interrupt:Boolean;
end; 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; PvMicroEngineNode=^TvMicroEngineNode;
TvMicroEngineNode=record TvMicroEngineNode=record
@ -126,6 +134,7 @@ type
0:(CmdBuffer:TvCmdBuffer); 0:(CmdBuffer:TvCmdBuffer);
1:(FlipInfo:TvMeFlipInfo); 1:(FlipInfo:TvMeFlipInfo);
2:(EopInfo:TvMeEopInfo); 2:(EopInfo:TvMeEopInfo);
3:(WaitMem:TvMeWaitMemInfo);
end; end;
TvMicroEngine=object TvMicroEngine=object
@ -136,6 +145,7 @@ type
Procedure PushCmd(var Cmd:TvCmdBuffer); Procedure PushCmd(var Cmd:TvCmdBuffer);
Procedure PushFlip(var qcInfo:TqcFlipInfo;FlipLData:DWORD;FlipLabel:PDWORD;Interrupt:Boolean); Procedure PushFlip(var qcInfo:TqcFlipInfo;FlipLData:DWORD;FlipLabel:PDWORD;Interrupt:Boolean);
Procedure PushEop(adr:Pointer;data:QWORD;dataSel:Byte;Interrupt:Boolean); Procedure PushEop(adr:Pointer;data:QWORD;dataSel:Byte;Interrupt:Boolean);
Procedure PushWaitMem(adr:Pointer;ref,mask:DWORD;cFunc:Byte);
end; end;
var var
@ -145,6 +155,8 @@ var
GFXRing:TvCmdRing; GFXRing:TvCmdRing;
GFXMicroEngine:TvMicroEngine; GFXMicroEngine:TvMicroEngine;
FIdleEvent:PRTLEvent=nil;
GPU_REGS:TGPU_REGS; GPU_REGS:TGPU_REGS;
FCmdPool:TvCmdPool; FCmdPool:TvCmdPool;
@ -250,6 +262,22 @@ begin
Queue.Push(node); Queue.Push(node);
end; 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; procedure gfx_cp_parser(node:PvSubmitInfo); forward;
function gfx_submit(CmdBuffer:TvCmdBuffer):Boolean; forward; function gfx_submit(CmdBuffer:TvCmdBuffer):Boolean; forward;
function gfx_test(CmdBuffer:TvCmdBuffer):Boolean; forward; function gfx_test(CmdBuffer:TvCmdBuffer):Boolean; forward;
@ -296,6 +324,25 @@ begin
end; end;
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; Function me_node_test(node:PvMicroEngineNode):Boolean;
begin begin
Result:=True; Result:=True;
@ -306,7 +353,14 @@ begin
begin begin
Result:=gfx_test(node^.CmdBuffer); Result:=gfx_test(node^.CmdBuffer);
end; end;
else; metFlip:Result:=True;
metEop :Result:=True;
metWaitMem:
begin
Result:=me_test_mem(@node^.WaitMem);
end;
else
Assert(false);
end; end;
end; end;
@ -329,6 +383,9 @@ begin
begin begin
Result:=me_eop(@node^.EopInfo); Result:=me_eop(@node^.EopInfo);
end; end;
metWaitMem:;
else
Assert(false);
end; end;
end; end;
@ -351,7 +408,7 @@ begin
begin begin
if not me_node_test(GFXMicroEngine.Current) then if not me_node_test(GFXMicroEngine.Current) then
begin begin
time:=-1000000; time:=-100000;
NtDelayExecution(True,@time); NtDelayExecution(True,@time);
Continue; Continue;
end; end;
@ -366,6 +423,7 @@ begin
if not work_do then if not work_do then
begin begin
RTLEventSetEvent(FIdleEvent);
time:=Int64(NT_INFINITE); time:=Int64(NT_INFINITE);
NtDelayExecution(True,@time); NtDelayExecution(True,@time);
end; end;
@ -383,6 +441,9 @@ begin
GFXRing.Init; GFXRing.Init;
GFXMicroEngine.Init; GFXMicroEngine.Init;
FIdleEvent:=RTLEventCreate;
RTLEventSetEvent(FIdleEvent);
t:=BeginThread(@GFX_thread); t:=BeginThread(@GFX_thread);
_gfx_handle:=t; _gfx_handle:=t;
@ -521,14 +582,19 @@ begin
node^.Flip:=Flip^; node^.Flip:=Flip^;
end; end;
RTLEventResetEvent(FIdleEvent);
GFXRing.Queue.Push(node); GFXRing.Queue.Push(node);
NtQueueApcThread(_gfx_handle,@_apc_null,0,nil,0); NtQueueApcThread(_gfx_handle,@_apc_null,0,nil,0);
end; end;
procedure vSubmitDone; procedure vSubmitDone;
begin begin
if (FIdleEvent<>nil) then
begin
RTLEventWaitFor(FIdleEvent);
end;
//Sleep(100); //Sleep(100);
Device.WaitIdle; //Device.WaitIdle;
end; end;
@ -819,20 +885,22 @@ begin
end; end;
procedure onWaitRegMem(pm4Hdr:PM4_TYPE_3_HEADER;Body:PPM4CMDWAITREGMEM); procedure onWaitRegMem(pm4Hdr:PM4_TYPE_3_HEADER;Body:PPM4CMDWAITREGMEM);
var
adr:Pointer;
begin begin
{$ifdef ww} {$ifdef ww}
Case Body^.engine of Case Body^.engine of
0: //ME WAIT_REG_MEM_ENGINE_ME:
Case Body^.memSpace of Case Body^.memSpace of
0:Writeln(' waitOnRegister'); WAIT_REG_MEM_SPACE_REGISTER:Writeln(' waitOnRegister');
1:Writeln(' waitOnAddress'); WAIT_REG_MEM_SPACE_MEMORY :Writeln(' waitOnAddress');
else else
Assert(false); Assert(false);
end; end;
1: //PFP WAIT_REG_MEM_ENGINE_PFP:
Case Body^.memSpace of Case Body^.memSpace of
0:Writeln(' waitOnRegisterAndStall'); WAIT_REG_MEM_SPACE_REGISTER:Writeln(' waitOnRegisterAndStall');
1:Writeln(' waitOnAddressAndStall'); WAIT_REG_MEM_SPACE_MEMORY :Writeln(' waitOnAddressAndStall');
else else
Assert(false); Assert(false);
end; end;
@ -840,6 +908,26 @@ begin
Assert(false); Assert(false);
end; end;
{$endif} {$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; end;
procedure onPm40(pm4Hdr:PM4_TYPE_0_HEADER;Body:PDWORD); procedure onPm40(pm4Hdr:PM4_TYPE_0_HEADER;Body:PDWORD);

View File

@ -519,16 +519,15 @@ end;
// called in waitUntilSafeForRendering // called in waitUntilSafeForRendering
function ps4_sceGnmInsertWaitFlipDone(cmdBuffer:PDWORD;numDwords:DWORD;videoOutHandle,displayBufferIndex:Integer):Integer; SysV_ABI_CDecl; function ps4_sceGnmInsertWaitFlipDone(cmdBuffer:PDWORD;numDwords:DWORD;videoOutHandle,displayBufferIndex:Integer):Integer; SysV_ABI_CDecl;
var var
addr:Pointer; addr:PInt64;
begin begin
Result:=-1; Result:=-1;
if (numDwords<>7) then Exit; if (numDwords<>7) then Exit;
//sceVideoOutGetBufferLabelAddress(videoOutHandle,&base);
//addr = base + (ulong)(uint)displayBufferIndex * 8; Result:=ps4_sceVideoOutGetBufferLabelAddress(videoOutHandle,@addr);
_sig_lock; if (Result<>0) then Exit(-1);
addr:=_VideoOutGetBufferAdr(videoOutHandle,displayBufferIndex);
_sig_unlock; addr:=@addr[displayBufferIndex];
if (addr=nil) then Exit;
cmdBuffer[0]:=$c0053c00; //IT_WAIT_REG_MEM cmdBuffer[0]:=$c0053c00; //IT_WAIT_REG_MEM
cmdBuffer[1]:=$13; cmdBuffer[1]:=$13;

View File

@ -214,7 +214,10 @@ const
SCE_VIDEO_OUT_ERROR_UNKNOWN =-2144796418; // 0x802900FE */ SCE_VIDEO_OUT_ERROR_UNKNOWN =-2144796418; // 0x802900FE */
SCE_VIDEO_OUT_ERROR_ENOMEM =-2144792564; // 0x8029100C */ 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; Procedure App_Run;
@ -234,6 +237,7 @@ implementation
uses uses
vFlip, vFlip,
sys_signal, sys_signal,
sys_kernel,
sys_time, sys_time,
ps4_time, ps4_time,
spinlock, spinlock,
@ -377,6 +381,8 @@ type
FcurrentBuffer:Longint; FcurrentBuffer:Longint;
end; end;
FLabels:array[0..15] of Int64;
//(MAIN port: 1 to 16, AUX port: 1 to 8) //(MAIN port: 1 to 16, AUX port: 1 to 8)
FBuffers:record FBuffers:record
lock:Pointer; lock:Pointer;
@ -449,7 +455,7 @@ begin
Acqure; Acqure;
Exit(n); Exit(n);
end; end;
System.ThreadSwitch; SwYieldExecution;
until false; until false;
end; end;
@ -939,20 +945,24 @@ begin
H.Release; H.Release;
end; end;
function _VideoOutGetBufferAdr(hVideo:Integer;bufferIndex:Integer):Pointer; function ps4_sceVideoOutGetBufferLabelAddress(hVideo:Integer;ptr:PPInt64):Integer; SysV_ABI_CDecl;
var var
H:TVideoOut; H:TVideoOut;
begin begin
Result:=nil; if (ptr=nil) then Exit(SCE_VIDEO_OUT_ERROR_INVALID_ADDRESS);
_sig_lock;
H:=TVideoOut(FVideoOutMap.Acqure(hVideo)); H:=TVideoOut(FVideoOutMap.Acqure(hVideo));
if (H=nil) then Exit; _sig_unlock;
if (bufferIndex>=0) and (bufferIndex<SCE_VIDEO_OUT_BUFFER_NUM_MAX) then
begin if (H=nil) then Exit(SCE_VIDEO_OUT_ERROR_INVALID_HANDLE);
spin_lock(H.FBuffers.lock); ptr^:=@H.FLabels;
Result:=H.FBuffers.addr[bufferIndex];
spin_unlock(H.FBuffers.lock); _sig_lock;
end;
H.Release; H.Release;
_sig_unlock;
Result:=0;
end; end;
function _on_after(node:PKEventNode;data:Pointer):Boolean; function _on_after(node:PKEventNode;data:Pointer):Boolean;
@ -1038,6 +1048,7 @@ begin
//ps4_usleep(150); //ps4_usleep(150);
end else end else
begin begin
spin_lock(FBuffers.lock); spin_lock(FBuffers.lock);
addr:=FBuffers.addr[bufferIndex]; addr:=FBuffers.addr[bufferIndex];
attr:=FBuffers.attr[bufferIndex]; attr:=FBuffers.attr[bufferIndex];
@ -1076,18 +1087,17 @@ begin
//post_event_flip(flipArg); //post_event_flip(flipArg);
end; end;
node^.wait:=1;
free_node(node);
//FlipRate:=20; //FlipRate:=20;
if (flipMode=SCE_VIDEO_OUT_FLIP_MODE_VSYNC) then if (flipMode=SCE_VIDEO_OUT_FLIP_MODE_VSYNC) then
if (FlipRate<>0) then if (FlipRate<>0) then
begin begin
time:=(1000000 div (FlipRate+1)); //+5 selected empirically time:=(1000000 div (FlipRate{+1}));
//time:=time-1300;
//time:=time-1300;
elap:=SwTimePassedUnits(FlipStatus.Ftsc_flips); elap:=SwTimePassedUnits(FlipStatus.Ftsc_flips);
elap:=(elap+9) div 10; elap:=((elap+9) div 10)+120;
//elap:=elap+(elap div 100)*14;
if (elap<time) then if (elap<time) then
begin begin
@ -1106,13 +1116,13 @@ begin
//t2:=(t2+9) div 10; //t2:=(t2+9) div 10;
//Writeln('elap=',elap,' time=',time,' usleep=',t2); //Writeln('elap=',elap,' time=',time,' usleep=',t2);
if (FGpuFlip<>nil) then if (FGpuFlip<>nil) and (bufferIndex<>SCE_VIDEO_OUT_BUFFER_INDEX_BLANK) then
begin begin
FGpuFlip.IsComplite(FlipStatus.FcurrentBuffer); //FGpuFlip.IsComplite(bufferIndex);
//While (not FGpuFlip.IsComplite(FcurrentBuffer)) do While (not FGpuFlip.IsComplite(bufferIndex)) do
//begin begin
// ps4_usleep(150); ps4_usleep(150);
//end; end;
end; end;
end; end;
@ -1122,6 +1132,8 @@ begin
post_event_vblank(flipArg); post_event_vblank(flipArg);
end else end else
begin begin
System.InterlockedDecrement64(FLabels[bufferIndex]);
post_event_flip(flipArg); post_event_flip(flipArg);
post_event_vblank(flipArg); post_event_vblank(flipArg);
end; end;
@ -1155,8 +1167,8 @@ begin
end; end;
end; end;
node^.wait:=1; //node^.wait:=1;
free_node(node); //free_node(node);
end; end;
@ -1179,9 +1191,7 @@ begin
_sig_unlock; _sig_unlock;
if (H=nil) then Exit(SCE_VIDEO_OUT_ERROR_INVALID_HANDLE); if (H=nil) then Exit(SCE_VIDEO_OUT_ERROR_INVALID_HANDLE);
_sig_lock;
node:=H.alloc_node; node:=H.alloc_node;
_sig_unlock;
if (node=nil) then if (node=nil) then
begin begin
@ -1189,6 +1199,11 @@ begin
Exit(SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL); Exit(SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL);
end; end;
if (bufferIndex<>SCE_VIDEO_OUT_BUFFER_INDEX_BLANK) then
begin
System.InterlockedIncrement64(H.FLabels[bufferIndex]);
end;
node^.Parent:=@H.sceVideoOutSubmitFlip; node^.Parent:=@H.sceVideoOutSubmitFlip;
node^.u.bufferIndex:=bufferIndex; node^.u.bufferIndex:=bufferIndex;
node^.u.flipMode :=flipMode; node^.u.flipMode :=flipMode;
@ -1242,6 +1257,11 @@ begin
Exit(SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL); Exit(SCE_VIDEO_OUT_ERROR_FLIP_QUEUE_FULL);
end; end;
if (Flip^.bufferIndex<>SCE_VIDEO_OUT_BUFFER_INDEX_BLANK) then
begin
System.InterlockedIncrement64(H.FLabels[Flip^.bufferIndex]);
end;
node^.Parent:=@H.sceVideoOutSubmitFlip; node^.Parent:=@H.sceVideoOutSubmitFlip;
node^.u.bufferIndex:=Flip^.bufferIndex; node^.u.bufferIndex:=Flip^.bufferIndex;
node^.u.flipMode :=Flip^.flipMode; node^.u.flipMode :=Flip^.flipMode;

View File

@ -618,23 +618,35 @@ begin
buf:=@FBuffers[FcurrentBuffer]; buf:=@FBuffers[FcurrentBuffer];
if (Ffilp_shader=nil) then Exit; if (Ffilp_shader=nil) then
if not buf^.IsPrepare then Exit;
if (FSwapChain=nil) then recreateSwapChain;
if (FSwapChain.FHandle=VK_NULL_HANDLE) then
begin begin
recreateSwapChain; buf^.cmdbuf.ret:=1;
if (FSwapChain.FHandle=VK_NULL_HANDLE) then Exit; Exit;
end; end;
if not FSetLayout.Compile then Exit; if (not buf^.IsPrepare) or
if not FLayout.Compile then Exit; (not FSetLayout.Compile) or
if not FPipelineFlip.Compile then Exit; (not FLayout.Compile) or
if not FSetsPool.Compile then Exit; (not FPipelineFlip.Compile) or
(not FSetsPool.Compile) then
begin
buf^.cmdbuf.ret:=2;
Exit;
end;
repeat 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; FixCurrentFrame;
imageAvailableSemaphore:=FimageAvailableSemaphore[FcurrentFrame]; imageAvailableSemaphore:=FimageAvailableSemaphore[FcurrentFrame];
renderFinishedSemaphore:=FrenderFinishedSemaphore[FcurrentFrame]; renderFinishedSemaphore:=FrenderFinishedSemaphore[FcurrentFrame];
@ -655,6 +667,7 @@ begin
Exit; Exit;
end; end;
end; end;
until false; until false;
SwapImage:=FSwapChain.FImages[imageIndex]; SwapImage:=FSwapChain.FImages[imageIndex];

View File

@ -436,6 +436,8 @@ begin
if (cmd=nil) then Exit; if (cmd=nil) then Exit;
if (not cmd.BeginCmdBuffer) then Exit; if (not cmd.BeginCmdBuffer) then Exit;
rwlock_wrlock(lock);
if Barrier.Push(cmd.cmdbuf, if Barrier.Push(cmd.cmdbuf,
FHandle, FHandle,
GetSubresRange, GetSubresRange,
@ -445,6 +447,8 @@ begin
begin begin
Inc(cmd.cmd_count); Inc(cmd.cmd_count);
end; end;
rwlock_unlock(lock);
end; end;
procedure TvHostImage2.PushBarrier(cmd:TvCustomCmdBuffer; procedure TvHostImage2.PushBarrier(cmd:TvCustomCmdBuffer;