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; 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; 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^))-Integer(Pointer(a^)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.