fpPS4/vulkan/vSetsPoolManager.pas
2022-05-31 10:20:10 +03:00

206 lines
3.8 KiB
ObjectPascal

unit vSetsPoolManager;
{$mode objfpc}{$H+}
interface
uses
SysUtils,
RWLock,
LFQueue,
g23tree,
Vulkan,
vPipeline,
vCmdBuffer;
Function FetchDescriptorGroup(cmd:TvCustomCmdBuffer;Pipeline:TvPipelineLayout):TvDescriptorGroup;
implementation
type
TvSetsPoolUnbound=class;
TvDescriptorGroupNode=class(TvDescriptorGroup)
parent:TvSetsPoolUnbound;
pNext:Pointer;
Procedure Release(Sender:TObject);
end;
TvSetsPool2Compare=object
function c(a,b:TvSetsPool2):Integer; static;
end;
TvSetsPool2Set=specialize T23treeSet<TvSetsPool2,TvSetsPool2Compare>;
PvPipelineLayout=^TvPipelineLayout;
TvSetsPoolUnboundCompare=object
function c(a,b:PvPipelineLayout):Integer; static;
end;
TvSetsPoolUnbound=class
FPipeline:TvPipelineLayout;
FQueue:TIntrusiveMPSCQueue;
FPools:TvSetsPool2Set;
FLast:TvSetsPool2;
Constructor Create(Pipeline:TvPipelineLayout);
Procedure NewPool;
function Alloc:TvDescriptorGroupNode;
procedure PushNode(N:TvDescriptorGroupNode);
function PopNode:TvDescriptorGroupNode;
end;
_TvSetsPoolUnbounds=specialize T23treeSet<PvPipelineLayout,TvSetsPoolUnboundCompare>;
TvSetsPoolUnbounds=object(_TvSetsPoolUnbounds)
lock:TRWLock;
Procedure Init;
Procedure Lock_wr;
Procedure Unlock;
end;
var
FSetsPoolUnbounds:TvSetsPoolUnbounds;
Procedure TvSetsPoolUnbounds.Init;
begin
rwlock_init(lock);
end;
Procedure TvSetsPoolUnbounds.Lock_wr;
begin
rwlock_wrlock(lock);
end;
Procedure TvSetsPoolUnbounds.Unlock;
begin
rwlock_unlock(lock);
end;
function TvSetsPool2Compare.c(a,b:TvSetsPool2):Integer;
begin
Result:=Integer(Pointer(a)>Pointer(b))-Integer(Pointer(a)<Pointer(b));
end;
function TvSetsPoolUnboundCompare.c(a,b:PvPipelineLayout):Integer;
begin
Result:=Integer(Pointer(a^)>Pointer(b^))-Integer(Pointer(a^)<Pointer(b^));
end;
Constructor TvSetsPoolUnbound.Create(Pipeline:TvPipelineLayout);
begin
FPipeline:=Pipeline;
FQueue.Create;
end;
Procedure TvSetsPoolUnbound.NewPool;
var
N:TvSetsPool2;
begin
N:=TvSetsPool2.Create(FPipeline,2);
if N.Compile then
begin
FPools.Insert(N);
FLast:=N;
end else
begin
Assert(False,'NewPool');
N.Free;
end;
end;
function TvSetsPoolUnbound.Alloc:TvDescriptorGroupNode;
begin
Result:=PopNode;
if (Result<>nil) then Exit;
if (FLast=nil) then NewPool;
if FLast.IsFull then NewPool;
Result:=TvDescriptorGroupNode.Create;
Result.parent:=Self;
Result.FSets:=FLast.Alloc;
end;
procedure TvSetsPoolUnbound.PushNode(N:TvDescriptorGroupNode);
begin
FQueue.Push(@N.pNext);
end;
function TvSetsPoolUnbound.PopNode:TvDescriptorGroupNode;
var
Node:PPointer;
begin
Result:=nil;
Node:=nil;
if FQueue.Pop(Node) then
begin
Result:=TvDescriptorGroupNode(ptruint(Node)-ptruint(@TvDescriptorGroupNode(nil).pNext));
end;
end;
Procedure TvDescriptorGroupNode.Release(Sender:TObject);
begin
if (parent<>nil) then
begin
parent.PushNode(Self);
end;
end;
function _Find(Pipeline:TvPipelineLayout):TvSetsPoolUnbound;
var
i:TvSetsPoolUnbounds.Iterator;
begin
Result:=nil;
i:=FSetsPoolUnbounds.find(@Pipeline);
if (i.Item<>nil) then
begin
Result:=TvSetsPoolUnbound(ptruint(i.Item^)-ptruint(@TvSetsPoolUnbound(nil).FPipeline));
end;
end;
Function _Fetch(Pipeline:TvPipelineLayout):TvDescriptorGroupNode;
var
t:TvSetsPoolUnbound;
n:TvDescriptorGroupNode;
begin
Result:=nil;
t:=_Find(Pipeline);
if (t=nil) then
begin
t:=TvSetsPoolUnbound.Create(Pipeline);
FSetsPoolUnbounds.Insert(@t.FPipeline);
end;
n:=t.Alloc;
Result:=n;
end;
Function FetchDescriptorGroup(cmd:TvCustomCmdBuffer;Pipeline:TvPipelineLayout):TvDescriptorGroup;
begin
Result:=nil;
if (Pipeline=nil) then Exit;
if Pipeline.isSpace then Exit;
FSetsPoolUnbounds.Lock_wr;
Result:=_Fetch(Pipeline);
if (cmd<>nil) and (Result<>nil) then
begin
cmd.AddDependence(@TvDescriptorGroupNode(Result).Release);
end;
FSetsPoolUnbounds.Unlock;
end;
initialization
FSetsPoolUnbounds.Init;
end.