FPPS4/vulkan/vSetsPoolManager.pas

207 lines
3.8 KiB
Plaintext

unit vSetsPoolManager;
{$mode objfpc}{$H+}
interface
uses
SysUtils,
LFQueue,
g23tree,
Vulkan,
vPipeline,
vSetsPool,
vDescriptorSet,
vDependence;
Function FetchDescriptorGroup(cmd:TvDependenciesObject;Layout:TvPipelineLayout):TvDescriptorGroup;
implementation
uses
kern_rwlock;
type
TvSetsPoolUnbound=class;
TvDescriptorGroupNode=class(TvDescriptorGroup)
parent:TvSetsPoolUnbound;
pNext :Pointer;
function Drop(Sender:TObject):Boolean; override;
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
FLayout:TvPipelineLayout;
FQueue :TIntrusiveMPSCQueue;
FPools :TvSetsPool2Set;
FLast :TvSetsPool2;
Constructor Create(Layout:TvPipelineLayout);
Procedure NewPool;
function Alloc:TvDescriptorGroupNode;
procedure PushNode(N:TvDescriptorGroupNode);
function PopNode:TvDescriptorGroupNode;
end;
_TvSetsPoolUnbounds=specialize T23treeSet<PvPipelineLayout,TvSetsPoolUnboundCompare>;
TvSetsPoolUnbounds=object(_TvSetsPoolUnbounds)
lock:Pointer;
Procedure Lock_wr;
Procedure Unlock_wr;
end;
var
FSetsPoolUnbounds:TvSetsPoolUnbounds;
Procedure TvSetsPoolUnbounds.Lock_wr;
begin
rw_wlock(lock);
end;
Procedure TvSetsPoolUnbounds.Unlock_wr;
begin
rw_wunlock(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(Layout:TvPipelineLayout);
begin
FLayout:=Layout;
FQueue.Create;
end;
Procedure TvSetsPoolUnbound.NewPool;
var
N:TvSetsPool2;
begin
N:=TvSetsPool2.Create(FLayout,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.FLayout:=FLayout;
Result.FSets :=FLast.Alloc;
//
Result.Acquire(nil);
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;
function TvDescriptorGroupNode.Drop(Sender:TObject):Boolean;
begin
Result:=True;
if System.InterlockedDecrement(FHold)=0 then
begin
if (parent<>nil) then
begin
parent.PushNode(Self);
end;
Result:=Release(Sender);
end;
end;
function _Find(Layout:TvPipelineLayout):TvSetsPoolUnbound;
var
i:TvSetsPoolUnbounds.Iterator;
begin
Result:=nil;
i:=FSetsPoolUnbounds.find(@Layout);
if (i.Item<>nil) then
begin
Result:=TvSetsPoolUnbound(ptruint(i.Item^)-ptruint(@TvSetsPoolUnbound(nil).FLayout));
end;
end;
Function _Fetch(Layout:TvPipelineLayout):TvDescriptorGroupNode;
var
t:TvSetsPoolUnbound;
n:TvDescriptorGroupNode;
begin
Result:=nil;
t:=_Find(Layout);
if (t=nil) then
begin
t:=TvSetsPoolUnbound.Create(Layout);
FSetsPoolUnbounds.Insert(@t.FLayout);
end;
n:=t.Alloc;
Result:=n;
end;
Function FetchDescriptorGroup(cmd:TvDependenciesObject;Layout:TvPipelineLayout):TvDescriptorGroup;
begin
Result:=nil;
if (Layout=nil) then Exit;
if Layout.isSpace then Exit;
FSetsPoolUnbounds.Lock_wr;
Result:=_Fetch(Layout);
cmd.RefTo(Result);
FSetsPoolUnbounds.Unlock_wr;
end;
end.