unit vPipeline; {$mode objfpc}{$H+} interface uses g23tree, Vulkan, vDevice, vShader; type AVkDescriptorSetLayoutBinding=array of TVkDescriptorSetLayoutBinding; PvSetLayoutKey=^TvSetLayoutKey; TvSetLayoutKey=record FStage:TVkShaderStageFlags; FFlags:TVkUInt32; FBinds:AVkDescriptorSetLayoutBinding; end; TvSetLayout=class FHandle:TVkDescriptorSetLayout; FEdit,FCompile:ptruint; key:TvSetLayoutKey; Procedure SetUsePushDescriptor(b:Boolean); function GetUsePushDescriptor:Boolean; Destructor Destroy; override; Procedure Add(aBind:TVkUInt32;dType:TVkDescriptorType;Flags:TVkShaderStageFlags;count:TVkUInt32=1); Procedure SetBinds(const A:AVkDescriptorSetLayoutBinding); Function IsSpace:Boolean; inline; procedure Clear; function Compile:Boolean; function IsEdit:Boolean; end; AvSetLayout=array of TvSetLayout; AvPushConstantRange=array of TVkPushConstantRange; PvPipelineLayoutKey=^TvPipelineLayoutKey; TvPipelineLayoutKey=record FLayouts :AvSetLayout; FPushConsts:AvPushConstantRange; end; TvPipelineLayout=class FHandle:TVkPipelineLayout; FEdit,FCompile:ptruint; FBinds:ptruint; key:TvPipelineLayoutKey; Destructor Destroy; override; Procedure AddLayout(F:TvSetLayout); Procedure SetLayouts(const A:AvSetLayout); Procedure AddPushConst(offset,size:TVkUInt32;Flags:TVkShaderStageFlags); Procedure SetPushConst(const A:AvPushConstantRange); Function isSpace:Boolean; procedure Clear; function Compile:Boolean; function IsEdit:Boolean; end; TvPipeline=class FHandle:TVkPipeline; FEdit,FCompile:ptruint; Destructor Destroy; override; end; TvRenderPass=class FHandle:TVkRenderPass; Destructor Destroy; override; end; TvComputePipeline=class(TvPipeline) FLayout:TvPipelineLayout; FComputeShader:TvShader; procedure SetLayout(Layout:TvPipelineLayout); Procedure SetShader(Shader:TvShader); function Compile:Boolean; function IsEdit:Boolean; end; TvSetsPool=class; TvDescriptorSet=class FParent:TvSetsPool; FLayout:TvSetLayout; FHandle:TVkDescriptorSet; procedure _AllocDesc; procedure _FreeDesc; Destructor Destroy; override; Procedure BindBuf(aBind,aElem:TVkUInt32;dtype:TVkDescriptorType;buffer:TVkBuffer;offset,range:TVkDeviceSize); Procedure BindSTI(aBind,aElem:TVkUInt32;img:TVkImageView;Layout:TVkImageLayout); end; _TvSetLayoutKey=object Layout:TvSetLayout; fcount:TVkUInt32; function c(const a,b:_TvSetLayoutKey):Integer; static; end; _TvSetLayoutSet=specialize T23treeSet<_TvSetLayoutKey,_TvSetLayoutKey>; _TvDescriptorSetCompare=object function c(const a,b:TvDescriptorSet):Integer; static; end; _TvDescriptorSetSet=specialize T23treeSet; TvCountsGroup=array[0..14] of TVkUInt32; AvDescriptorPoolSize=array of TVkDescriptorPoolSize; TvSetsPool=class FHandle:TVkDescriptorPool; FEdit,FCompile:ptruint; FmaxSets:TVkUInt32; FLayouts:_TvSetLayoutSet; FSets:_TvDescriptorSetSet; Destructor Destroy; override; function _FindLayout(L:TvSetLayout):Boolean; procedure ClearLayouts; Procedure AddLayout(L:TvSetLayout;count:TVkUInt32=1); Procedure AddFormPipelineLayout(L:TvPipelineLayout;count:TVkUInt32=1); function Alloc(L:TvSetLayout):TvDescriptorSet; function Compile:Boolean; function IsEdit:Boolean; end; /////// TvDescriptorSet2=object FHandle:TVkDescriptorSet; Function IsValid:Boolean; Procedure BindBuf(aBind,aElem:TVkUInt32;dtype:TVkDescriptorType;buffer:TVkBuffer;offset,range:TVkDeviceSize); Procedure BindSTI(aBind,aElem:TVkUInt32;img:TVkImageView;Layout:TVkImageLayout); Procedure BindImg(aBind,aElem:TVkUInt32;img:TVkImageView;Layout:TVkImageLayout); Procedure BindSmp(aBind,aElem:TVkUInt32;smp:TVkSampler); end; AvDescriptorSet2=Array of TvDescriptorSet2; TvDescriptorGroup=class //lock:Ptruint; FSets:AvDescriptorSet2; //Procedure Release; end; AvDescriptorGroup=Array of TvDescriptorGroup; //PvSetsPoolKey=^TvSetsPoolKey; //TvSetsPoolKey=record // FPipeline:TvPipelineLayout; // FNumber :PtrUint; //end; TvSetsPool2=class FHandle:TVkDescriptorPool; //key:TvSetsPoolKey; FPipeline:TvPipelineLayout; FmaxGroup:TVkUInt32; FmaxSets :TVkUInt32; FAlcGroup:TVkUInt32; //FGroups :AvDescriptorGroup; Constructor Create(Pipeline:TvPipelineLayout;maxGroup:TVkUInt32); Destructor Destroy; override; function Compile:Boolean; function Alloc(L:TvSetLayout):TvDescriptorSet2; //function Alloc:TvDescriptorGroup; function IsFull:Boolean; function Alloc:AvDescriptorSet2; end; implementation function _TvSetLayoutKey.c(const a,b:_TvSetLayoutKey):Integer; begin Result:=CompareByte(a.Layout,b.Layout,SizeOf(TvSetLayout)); end; function _TvDescriptorSetCompare.c(const a,b:TvDescriptorSet):Integer; begin Result:=CompareByte(a,b,SizeOf(TvDescriptorSet)); end; Procedure TvSetLayout.Add(aBind:TVkUInt32;dType:TVkDescriptorType;Flags:TVkShaderStageFlags;count:TVkUInt32=1); var i:Integer; begin i:=Length(key.FBinds); SetLength(key.FBinds,i+1); key.FBinds[i]:=Default(TVkDescriptorSetLayoutBinding); key.FBinds[i].binding:=aBind; key.FBinds[i].descriptorType:=dType; key.FBinds[i].descriptorCount:=count; key.FBinds[i].stageFlags:=Flags; Inc(FEdit); end; Procedure TvSetLayout.SetBinds(const A:AVkDescriptorSetLayoutBinding); begin key.FBinds:=A; Inc(FEdit); end; Function TvSetLayout.IsSpace:Boolean; inline; begin Result:=Length(key.FBinds)=0; end; Procedure TvSetLayout.Clear; begin SetLength(key.FBinds,0); key.FFlags:=0; Inc(FEdit); end; function TvSetLayout.Compile:Boolean; var cinfo:TVkDescriptorSetLayoutCreateInfo; r:TVkResult; begin Result:=False; if (FHandle<>VK_NULL_HANDLE) then begin if (FEdit=FCompile) then Exit(true); vkDestroyDescriptorSetLayout(Device.FHandle,FHandle,nil); FHandle:=VK_NULL_HANDLE; end; cinfo:=Default(TVkDescriptorSetLayoutCreateInfo); cinfo.sType:=VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; cinfo.flags:=key.FFlags; cinfo.bindingCount:=Length(key.FBinds); if (cinfo.bindingCount<>0) then begin cinfo.pBindings:=@key.FBinds[0]; end; r:=vkCreateDescriptorSetLayout(Device.FHandle,@cinfo,nil,@FHandle); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkCreateDescriptorSetLayout:',r); Exit; end; FCompile:=FEdit; Result:=True; end; Destructor TvSetLayout.Destroy; begin if (FHandle<>VK_NULL_HANDLE) then vkDestroyDescriptorSetLayout(Device.FHandle,FHandle,nil); end; function TvSetLayout.IsEdit:Boolean; begin Result:=FEdit<>FCompile; end; Procedure TvSetLayout.SetUsePushDescriptor(b:Boolean); begin Case b of True: if (key.FFlags<>ord(VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR)) then begin key.FFlags:=ord(VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR); Inc(FEdit); end; False: if (key.FFlags=ord(VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR)) then begin key.FFlags:=0; Inc(FEdit); end; end; end; function TvSetLayout.GetUsePushDescriptor:Boolean; begin Result:=(key.FFlags=ord(VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR)); end; Destructor TvPipelineLayout.Destroy; begin if (FHandle<>VK_NULL_HANDLE) then vkDestroyPipelineLayout(Device.FHandle,FHandle,nil); end; Procedure TvPipelineLayout.AddLayout(F:TvSetLayout); var i:Integer; begin if (F=nil) then Exit; i:=Length(key.FLayouts); SetLength(key.FLayouts,i+1); key.FLayouts[i]:=F; Inc(FEdit); end; Procedure TvPipelineLayout.SetLayouts(const A:AvSetLayout); begin key.FLayouts:=A; Inc(FEdit); end; Procedure TvPipelineLayout.AddPushConst(offset,size:TVkUInt32;Flags:TVkShaderStageFlags); var i:Integer; begin i:=Length(key.FPushConsts); SetLength(key.FPushConsts,i+1); key.FPushConsts[i].stageFlags:=Flags; key.FPushConsts[i].offset :=offset; key.FPushConsts[i].size :=size; Inc(FEdit); end; Procedure TvPipelineLayout.SetPushConst(const A:AvPushConstantRange); begin key.FPushConsts:=A; Inc(FEdit); end; Function TvPipelineLayout.isSpace:Boolean; begin Result:=FBinds=0; end; procedure TvPipelineLayout.Clear; begin SetLength(key.FLayouts,0); SetLength(key.FPushConsts,0); FBinds:=0; Inc(FEdit); end; function TvPipelineLayout.Compile:Boolean; var cinfo:TVkPipelineLayoutCreateInfo; r:TVkResult; _data_set:array of TVkDescriptorSetLayout; i:Integer; begin Result:=false; if (FHandle<>VK_NULL_HANDLE) then begin if (not IsEdit) then Exit(true); vkDestroyPipelineLayout(Device.FHandle,FHandle,nil); FHandle:=VK_NULL_HANDLE; end; FBinds:=0; if (Length(key.FLayouts)<>0) then begin _data_set:=nil; SetLength(_data_set,Length(key.FLayouts)); For i:=0 to High(key.FLayouts) do begin if not key.FLayouts[i].Compile then Exit; _data_set[i]:=key.FLayouts[i].FHandle; FBinds:=FBinds+Length(key.FLayouts[i].key.FBinds); end; end; cinfo:=Default(TVkPipelineLayoutCreateInfo); cinfo.sType :=VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; cinfo.setLayoutCount:=Length(_data_set); if (cinfo.setLayoutCount<>0) then begin cinfo.pSetLayouts:=@_data_set[0]; end; cinfo.pushConstantRangeCount:=Length(key.FPushConsts); if (cinfo.pushConstantRangeCount<>0) then begin cinfo.pPushConstantRanges:=@key.FPushConsts[0]; end; r:=vkCreatePipelineLayout(Device.FHandle,@cinfo,nil,@FHandle); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkCreatePipelineLayout:',r); Exit; end; FCompile:=FEdit; Result:=True; end; function TvPipelineLayout.IsEdit:Boolean; var i:Integer; begin Result:=FEdit<>FCompile; if not Result then if (Length(key.FLayouts)<>0) then For i:=0 to High(key.FLayouts) do if key.FLayouts[i].IsEdit then Exit(true); end; Destructor TvPipeline.Destroy; begin if (FHandle<>VK_NULL_HANDLE) then vkDestroyPipeline(Device.FHandle,FHandle,nil); end; Destructor TvRenderPass.Destroy; begin if (FHandle<>VK_NULL_HANDLE) then vkDestroyRenderPass(Device.FHandle,FHandle,nil); end; procedure TvComputePipeline.SetLayout(Layout:TvPipelineLayout); begin if (FLayout<>Layout) then begin Inc(FEdit); FLayout:=Layout; Compile; end; end; Procedure TvComputePipeline.SetShader(Shader:TvShader); begin if (FComputeShader<>Shader) then begin Inc(FEdit); if (Shader=nil) then begin FComputeShader:=nil; end else if (Shader.FStage=VK_SHADER_STAGE_COMPUTE_BIT) then begin FComputeShader:=Shader; Compile; end; end; end; function TvComputePipeline.Compile:Boolean; var cinfo:TVkComputePipelineCreateInfo; r:TVkResult; begin Result:=False; if (FLayout=nil) or (FComputeShader=nil) then Exit; if (FHandle<>VK_NULL_HANDLE) then begin if (not IsEdit) then Exit(true); vkDestroyPipeline(Device.FHandle,FHandle,nil); FHandle:=VK_NULL_HANDLE; end; if not FLayout.Compile then Exit; cinfo:=Default(TVkComputePipelineCreateInfo); cinfo.sType:=VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; cinfo.stage.sType:=VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; cinfo.stage.stage:=VK_SHADER_STAGE_COMPUTE_BIT; cinfo.stage.module:=FComputeShader.FHandle; cinfo.stage.pName:=PChar(FComputeShader.FEntry); cinfo.layout:=FLayout.FHandle; r:=vkCreateComputePipelines(Device.FHandle,VK_NULL_HANDLE,1,@cinfo,nil,@FHandle); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkCreateComputePipelines:',r); Exit; end; FCompile:=FEdit; Result:=True; end; function TvComputePipeline.IsEdit:Boolean; begin Result:=(FEdit<>FCompile); if (not Result) and (FLayout<>nil) then Result:=Result or FLayout.IsEdit; end; Destructor TvSetsPool.Destroy; var It:_TvDescriptorSetSet.Iterator; begin It:=FSets.cbegin; if (It.Item<>nil) then repeat It.Item^.FHandle:=VK_NULL_HANDLE; until not It.Next; if (FHandle<>VK_NULL_HANDLE) then vkDestroyDescriptorPool(Device.FHandle,FHandle,nil); FSets.Free; FLayouts.Free; end; function _GetTypeById(i:Byte):TVkDescriptorType; begin Result:=VK_DESCRIPTOR_TYPE_SAMPLER; Case i of 0:Result:=VK_DESCRIPTOR_TYPE_SAMPLER ; 1:Result:=VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ; 2:Result:=VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ; 3:Result:=VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ; 4:Result:=VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ; 5:Result:=VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER ; 6:Result:=VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER ; 7:Result:=VK_DESCRIPTOR_TYPE_STORAGE_BUFFER ; 8:Result:=VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ; 9:Result:=VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC ; 10:Result:=VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT ; 11:Result:=VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT ; 12:Result:=VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR; 13:Result:=VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV ; 14:Result:=VK_DESCRIPTOR_TYPE_MUTABLE_VALVE ; else; end; end; function _GetIdByType(i:TVkDescriptorType):Byte; begin Result:=0; Case i of VK_DESCRIPTOR_TYPE_SAMPLER :Result:=0; VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER :Result:=1; VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE :Result:=2; VK_DESCRIPTOR_TYPE_STORAGE_IMAGE :Result:=3; VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER :Result:=4; VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER :Result:=5; VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER :Result:=6; VK_DESCRIPTOR_TYPE_STORAGE_BUFFER :Result:=7; VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC :Result:=8; VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC :Result:=9; VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT :Result:=10; VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT :Result:=11; VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:Result:=12; VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV :Result:=13; VK_DESCRIPTOR_TYPE_MUTABLE_VALVE :Result:=14; else; end; end; function TvSetsPool.Compile:Boolean; var i,b,L:Integer; It:_TvSetLayoutSet.Iterator; Ik:_TvSetLayoutKey; Id:_TvDescriptorSetSet.Iterator; FCounts:TvCountsGroup; FSizes:AvDescriptorPoolSize; cinfo:TVkDescriptorPoolCreateInfo; r:TVkResult; begin Result:=False; if (FHandle<>VK_NULL_HANDLE) and (not IsEdit) then Exit(true); if (FLayouts.Size=0) then Exit; FSizes:=Default(AvDescriptorPoolSize); FmaxSets:=0; FCounts:=Default(TvCountsGroup); It:=FLayouts.cbegin; repeat Ik:=It.Item^; if (Ik.Layout<>nil) and (Ik.fcount<>0) then if (Length(Ik.Layout.key.FBinds)<>0) then begin FmaxSets:=FmaxSets+Ik.fcount; For i:=0 to Ik.fcount-1 do For b:=0 to High(Ik.Layout.key.FBinds) do with Ik.Layout.key.FBinds[b] do begin Inc(FCounts[_GetIdByType(descriptorType)],descriptorCount); end; end; until not It.Next; For i:=0 to 14 do if (FCounts[i]<>0) then begin L:=Length(FSizes); SetLength(FSizes,L+1); FSizes[L].type_ :=_GetTypeById(i); FSizes[L].descriptorCount:=FCounts[i]; end; if (Length(FSizes)=0) then Exit; Id:=FSets.cbegin; if (Id.Item<>nil) then repeat Id.Item^.FHandle:=VK_NULL_HANDLE; until not Id.Next; if (FHandle<>VK_NULL_HANDLE) then begin vkDestroyDescriptorPool(Device.FHandle,FHandle,nil); FHandle:=VK_NULL_HANDLE; end; It:=FLayouts.cbegin; repeat Ik:=It.Item^; if (Ik.Layout<>nil) and (Ik.fcount<>0) then begin if not Ik.Layout.Compile then Exit; end; until not It.Next; cinfo:=Default(TVkDescriptorPoolCreateInfo); cinfo.sType :=VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; cinfo.flags :=ord(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT); cinfo.poolSizeCount:=Length(FSizes); cinfo.pPoolSizes :=@FSizes[0]; cinfo.maxSets :=FmaxSets; r:=vkCreateDescriptorPool(Device.FHandle,@cinfo,nil,@FHandle); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkCreateDescriptorPool:',r); Exit; end; i:=0; Id:=FSets.cbegin; if (Id.Item<>nil) then repeat Id.Item^._AllocDesc; Inc(i); if (i>=FmaxSets) then Break; until not Id.Next; FCompile:=FEdit; Result:=True; end; function TvSetsPool.IsEdit:Boolean; var It:_TvSetLayoutSet.Iterator; Ik:_TvSetLayoutKey; begin Result:=False; if (FEdit<>FCompile) then Exit(True); It:=FLayouts.cbegin; if (It.Item=nil) then Exit; repeat Ik:=It.Item^; if (Ik.Layout<>nil) and (Ik.fcount<>0) then if Ik.Layout.IsEdit then Exit(True); until not It.Next; end; procedure TvSetsPool.ClearLayouts; begin FLayouts.Free; Inc(FEdit); end; function TvSetsPool._FindLayout(L:TvSetLayout):Boolean; var Ik:_TvSetLayoutKey; begin Ik.Layout:=L; Ik.fcount:=0; Result:=FLayouts.Contains(Ik); end; Procedure TvSetsPool.AddLayout(L:TvSetLayout;count:TVkUInt32); var It:_TvSetLayoutSet.Iterator; Ik:_TvSetLayoutKey; begin if (L=nil) then Exit; if (count=0) then count:=1; Ik.Layout:=L; Ik.fcount:=count; It:=FLayouts.find(Ik); if (It.Item<>nil) then begin It.Item^.fcount:=It.Item^.fcount+count; end else begin FLayouts.Insert(Ik); end; Inc(FEdit); end; Procedure TvSetsPool.AddFormPipelineLayout(L:TvPipelineLayout;count:TVkUInt32); var i:Integer; begin if (L=nil) then Exit; if (Length(L.key.FLayouts)<>0) then For i:=0 to High(L.key.FLayouts) do begin AddLayout(L.key.FLayouts[i],count); end; end; function TvSetsPool.Alloc(L:TvSetLayout):TvDescriptorSet; var ainfo:TVkDescriptorSetAllocateInfo; FResult:TVkDescriptorSet; r:TVkResult; begin Result:=nil; if (L=nil) then Exit; if not _FindLayout(L) then Exit; if not Compile then Exit; if (FSets.Size>=FmaxSets) then Exit; ainfo:=Default(TVkDescriptorSetAllocateInfo); ainfo.sType :=VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; ainfo.descriptorPool :=FHandle; ainfo.descriptorSetCount:=1; ainfo.pSetLayouts:=@L.FHandle; r:=vkAllocateDescriptorSets(Device.FHandle,@ainfo,@FResult); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkAllocateDescriptorSets:',r); Exit; end; Result:=TvDescriptorSet.Create; Result.FParent:=Self; Result.FLayout:=L; Result.FHandle:=FResult; FSets.Insert(Result); end; procedure TvDescriptorSet._AllocDesc; var ainfo:TVkDescriptorSetAllocateInfo; r:TVkResult; begin if (FParent<>nil) and (FLayout<>nil) then if (FHandle=VK_NULL_HANDLE) and (FParent.FHandle<>VK_NULL_HANDLE) then begin ainfo:=Default(TVkDescriptorSetAllocateInfo); ainfo.sType :=VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; ainfo.descriptorPool :=FParent.FHandle; ainfo.descriptorSetCount:=1; ainfo.pSetLayouts:=@FLayout.FHandle; r:=vkAllocateDescriptorSets(Device.FHandle,@ainfo,@FHandle); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkAllocateDescriptorSets:',r); Exit; end; end; end; procedure TvDescriptorSet._FreeDesc; var r:TVkResult; begin if (FParent<>nil) then if (FHandle<>VK_NULL_HANDLE) and (FParent.FHandle<>VK_NULL_HANDLE) then begin r:=vkFreeDescriptorSets(Device.FHandle,FParent.FHandle,1,@FHandle); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkFreeDescriptorSets:',r); end; end; FHandle:=VK_NULL_HANDLE; end; Destructor TvDescriptorSet.Destroy; begin if (FParent<>nil) then begin _FreeDesc; FParent.FSets.delete(Self); end; inherited; end; //VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER //VK_DESCRIPTOR_TYPE_STORAGE_BUFFER //VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC //VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC Procedure TvDescriptorSet.BindBuf(aBind,aElem:TVkUInt32;dtype:TVkDescriptorType;buffer:TVkBuffer;offset,range:TVkDeviceSize); var dwrite:TVkWriteDescriptorSet; buf:TVkDescriptorBufferInfo; begin buf:=Default(TVkDescriptorBufferInfo); buf.buffer:=buffer; buf.offset:=offset; buf.range :=range ; dwrite:=Default(TVkWriteDescriptorSet); dwrite.sType :=VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; dwrite.dstSet :=FHandle; dwrite.dstBinding :=aBind; dwrite.dstArrayElement:=aElem; dwrite.descriptorType :=dtype; dwrite.descriptorCount:=1; dwrite.pBufferInfo :=@buf; vkUpdateDescriptorSets(Device.FHandle,1,@dwrite,0,nil); end; Procedure TvDescriptorSet.BindSTI(aBind,aElem:TVkUInt32;img:TVkImageView;Layout:TVkImageLayout); var dwrite:TVkWriteDescriptorSet; dimg:TVkDescriptorImageInfo; begin dimg:=Default(TVkDescriptorImageInfo); dimg.imageView :=img; dimg.imageLayout:=Layout; dwrite:=Default(TVkWriteDescriptorSet); dwrite.sType :=VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; dwrite.dstSet :=FHandle; dwrite.dstBinding :=aBind; dwrite.dstArrayElement:=aElem; dwrite.descriptorType :=VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; dwrite.descriptorCount:=1; dwrite.pImageInfo :=@dimg; vkUpdateDescriptorSets(Device.FHandle,1,@dwrite,0,nil); end; // Function TvDescriptorSet2.IsValid:Boolean; begin Result:=FHandle<>VK_NULL_HANDLE; end; Procedure TvDescriptorSet2.BindBuf(aBind,aElem:TVkUInt32;dtype:TVkDescriptorType;buffer:TVkBuffer;offset,range:TVkDeviceSize); var dwrite:TVkWriteDescriptorSet; buf:TVkDescriptorBufferInfo; begin buf:=Default(TVkDescriptorBufferInfo); buf.buffer:=buffer; buf.offset:=offset; buf.range :=range ; dwrite:=Default(TVkWriteDescriptorSet); dwrite.sType :=VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; dwrite.dstSet :=FHandle; dwrite.dstBinding :=aBind; dwrite.dstArrayElement:=aElem; dwrite.descriptorType :=dtype; dwrite.descriptorCount:=1; dwrite.pBufferInfo :=@buf; vkUpdateDescriptorSets(Device.FHandle,1,@dwrite,0,nil); end; Procedure TvDescriptorSet2.BindSTI(aBind,aElem:TVkUInt32;img:TVkImageView;Layout:TVkImageLayout); var dwrite:TVkWriteDescriptorSet; dimg:TVkDescriptorImageInfo; begin dimg:=Default(TVkDescriptorImageInfo); dimg.imageView :=img; dimg.imageLayout:=Layout; dwrite:=Default(TVkWriteDescriptorSet); dwrite.sType :=VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; dwrite.dstSet :=FHandle; dwrite.dstBinding :=aBind; dwrite.dstArrayElement:=aElem; dwrite.descriptorType :=VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; dwrite.descriptorCount:=1; dwrite.pImageInfo :=@dimg; vkUpdateDescriptorSets(Device.FHandle,1,@dwrite,0,nil); end; Procedure TvDescriptorSet2.BindImg(aBind,aElem:TVkUInt32;img:TVkImageView;Layout:TVkImageLayout); var dwrite:TVkWriteDescriptorSet; dimg:TVkDescriptorImageInfo; begin dimg:=Default(TVkDescriptorImageInfo); dimg.imageView :=img; dimg.imageLayout:=Layout; dwrite:=Default(TVkWriteDescriptorSet); dwrite.sType :=VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; dwrite.dstSet :=FHandle; dwrite.dstBinding :=aBind; dwrite.dstArrayElement:=aElem; dwrite.descriptorType :=VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; dwrite.descriptorCount:=1; dwrite.pImageInfo :=@dimg; vkUpdateDescriptorSets(Device.FHandle,1,@dwrite,0,nil); end; Procedure TvDescriptorSet2.BindSmp(aBind,aElem:TVkUInt32;smp:TVkSampler); var dwrite:TVkWriteDescriptorSet; dimg:TVkDescriptorImageInfo; begin dimg:=Default(TVkDescriptorImageInfo); dimg.sampler:=smp; dwrite:=Default(TVkWriteDescriptorSet); dwrite.sType :=VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; dwrite.dstSet :=FHandle; dwrite.dstBinding :=aBind; dwrite.dstArrayElement:=aElem; dwrite.descriptorType :=VK_DESCRIPTOR_TYPE_SAMPLER; dwrite.descriptorCount:=1; dwrite.pImageInfo :=@dimg; vkUpdateDescriptorSets(Device.FHandle,1,@dwrite,0,nil); end; Constructor TvSetsPool2.Create(Pipeline:TvPipelineLayout;maxGroup:TVkUInt32); begin FPipeline:=Pipeline; FmaxGroup:=maxGroup; end; Destructor TvSetsPool2.Destroy; begin if (FHandle<>VK_NULL_HANDLE) then vkDestroyDescriptorPool(Device.FHandle,FHandle,nil); end; function TvSetsPool2.Compile:Boolean; var i,b,L:Integer; FCounts:TvCountsGroup; FSizes:AvDescriptorPoolSize; cinfo:TVkDescriptorPoolCreateInfo; r:TVkResult; begin Result:=False; if (FHandle<>VK_NULL_HANDLE) then Exit(true); if (FPipeline=nil) then Exit; if (FmaxGroup=0) then Exit; if (not FPipeline.Compile) then Exit; FSizes:=Default(AvDescriptorPoolSize); FmaxSets:=0; FCounts:=Default(TvCountsGroup); if Length(FPipeline.key.FLayouts)<>0 then For i:=0 to High(FPipeline.key.FLayouts) do With FPipeline.key.FLayouts[i] do if (Length(key.FBinds)<>0) then begin Inc(FmaxSets,FmaxGroup); For b:=0 to High(key.FBinds) do with key.FBinds[b] do begin Inc(FCounts[_GetIdByType(descriptorType)],descriptorCount*FmaxGroup); end; end; For i:=0 to 14 do if (FCounts[i]<>0) then begin L:=Length(FSizes); SetLength(FSizes,L+1); FSizes[L].type_ :=_GetTypeById(i); FSizes[L].descriptorCount:=FCounts[i]; end; if (Length(FSizes)=0) then Exit; cinfo:=Default(TVkDescriptorPoolCreateInfo); cinfo.sType :=VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; //cinfo.flags :=ord(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT); cinfo.poolSizeCount:=Length(FSizes); cinfo.pPoolSizes :=@FSizes[0]; cinfo.maxSets :=FmaxSets; r:=vkCreateDescriptorPool(Device.FHandle,@cinfo,nil,@FHandle); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkCreateDescriptorPool:',r); Exit; end; Result:=True; end; function TvSetsPool2.Alloc(L:TvSetLayout):TvDescriptorSet2; var ainfo:TVkDescriptorSetAllocateInfo; FResult:TVkDescriptorSet; r:TVkResult; begin Result:=Default(TvDescriptorSet2); if (L=nil) then Exit; if L.IsSpace then Exit; if not Compile then Exit; ainfo:=Default(TVkDescriptorSetAllocateInfo); ainfo.sType :=VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; ainfo.descriptorPool :=FHandle; ainfo.descriptorSetCount:=1; ainfo.pSetLayouts:=@L.FHandle; r:=vkAllocateDescriptorSets(Device.FHandle,@ainfo,@FResult); if (r<>VK_SUCCESS) then begin Writeln(StdErr,'vkAllocateDescriptorSets:',r); Exit; end; Result.FHandle:=FResult; end; function TvSetsPool2.IsFull:Boolean; begin Result:=(FAlcGroup>=FmaxGroup); end; function TvSetsPool2.Alloc:AvDescriptorSet2; var i:Integer; begin Result:=nil; if IsFull then Exit; SetLength(Result,Length(FPipeline.key.FLayouts)); If (Length(Result)<>0) then For i:=0 to High(Result) do begin Result[i]:=Alloc(FPipeline.key.FLayouts[i]); end; Inc(FAlcGroup); end; { Procedure TvDescriptorGroup.Release; begin lock:=0; end; } end.