unit vPipelineLayoutManager; {$mode objfpc}{$H+} interface uses SysUtils, RWLock, g23tree, Vulkan, vPipeline; Function FetchPipelineLayout(const A:AvSetLayout; const B:AvPushConstantRange):TvPipelineLayout; implementation type TvPipelineLayoutCompare=class class function c(a,b:PvPipelineLayoutKey):Integer; static; end; _TvPipelineLayoutSet=specialize T23treeSet; TvPipelineLayoutSet=object(_TvPipelineLayoutSet) lock:TRWLock; Procedure Init; Procedure Lock_wr; Procedure Unlock; end; var FPipelineLayoutSet:TvPipelineLayoutSet; Procedure TvPipelineLayoutSet.Init; begin rwlock_init(lock); end; Procedure TvPipelineLayoutSet.Lock_wr; begin rwlock_wrlock(lock); end; Procedure TvPipelineLayoutSet.Unlock; begin rwlock_unlock(lock); end; function _Find(F:PvPipelineLayoutKey):TvPipelineLayout; var i:TvPipelineLayoutSet.Iterator; begin Result:=nil; i:=FPipelineLayoutSet.find(F); if (i.Item<>nil) then begin Result:=TvPipelineLayout(ptruint(i.Item^)-ptruint(@TvPipelineLayout(nil).key)); end; end; Function _Fetch(F:PvPipelineLayoutKey):TvPipelineLayout; var t:TvPipelineLayout; begin t:=_Find(F); if (t=nil) then begin t:=TvPipelineLayout.Create; t.key:=F^; if not t.Compile then begin FreeAndNil(t); end else begin FPipelineLayoutSet.Insert(@t.key); end; end; Result:=t; end; Function FetchPipelineLayout(const A:AvSetLayout; const B:AvPushConstantRange):TvPipelineLayout; var key:TvPipelineLayoutKey; begin key:=Default(TvPipelineLayoutKey); key.FLayouts :=A; key.FPushConsts:=B; FPipelineLayoutSet.Lock_wr; Result:=_Fetch(@key); FPipelineLayoutSet.Unlock; end; function ComparePtruint(buf1,buf2:PPtruint;count:PtrUint):Integer; begin Result:=0; While (count<>0) do begin Result:=Integer(buf1^>buf2^)-Integer(buf1^0) then Exit; Inc(buf1); Inc(buf2); Dec(count); end; end; function ComparePushRange(var a,b:TVkPushConstantRange):Integer; begin //1 stageFlags Result:=Integer(a.stageFlags>b.stageFlags)-Integer(a.stageFlags0) then Exit; //2 offset Result:=Integer(a.offset>b.offset)-Integer(a.offset0) then Exit; //3 size Result:=Integer(a.size>b.size)-Integer(a.size0) then For i:=0 to count-1 do begin Result:=ComparePushRange(buf1[i],buf2[i]); if (Result<>0) then Exit; end; end; class function TvPipelineLayoutCompare.c(a,b:PvPipelineLayoutKey):Integer; begin //1 Length(FLayouts) Result:=Integer(Length(a^.FLayouts)>Length(b^.FLayouts))-Integer(Length(a^.FLayouts)0) then Exit; //2 Length(FPushConsts) Result:=Integer(Length(a^.FPushConsts)>Length(b^.FPushConsts))-Integer(Length(a^.FPushConsts)0) then Exit; //3 FLayouts Result:=ComparePtruint(@a^.FLayouts[0],@b^.FLayouts[0],Length(a^.FLayouts)); if (Result<>0) then Exit; //4 FPushConsts Result:=ComparePushRanges(a^.FPushConsts,b^.FPushConsts,Length(a^.FPushConsts)); end; initialization FPipelineLayoutSet.Init; end.