mirror of https://github.com/red-prig/fpPS4.git
386 lines
8.3 KiB
Plaintext
386 lines
8.3 KiB
Plaintext
unit vPipeline;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Vulkan,
|
|
vDevice,
|
|
vShader,
|
|
vDependence;
|
|
|
|
type
|
|
AVkDescriptorSetLayoutBinding=array of TVkDescriptorSetLayoutBinding;
|
|
|
|
PvSetLayoutKey=^TvSetLayoutKey;
|
|
TvSetLayoutKey=record
|
|
FStage:TVkShaderStageFlags;
|
|
FFlags:TVkUInt32;
|
|
FBinds:AVkDescriptorSetLayoutBinding;
|
|
end;
|
|
|
|
TvSetLayout=class
|
|
FHandle:TVkDescriptorSetLayout;
|
|
key:TvSetLayoutKey;
|
|
Procedure SetUsePushDescriptor(b:Boolean);
|
|
function GetUsePushDescriptor:Boolean;
|
|
Procedure Add(aBind:TVkUInt32;dType:TVkDescriptorType;Flags:TVkShaderStageFlags;count:TVkUInt32=1);
|
|
Procedure SetBinds(const A:AVkDescriptorSetLayoutBinding);
|
|
procedure Clear;
|
|
function Compile:Boolean;
|
|
Function IsSpace:Boolean; inline;
|
|
Destructor Destroy; override;
|
|
end;
|
|
|
|
AvSetLayout=array of TvSetLayout;
|
|
AvPushConstantRange=array of TVkPushConstantRange;
|
|
|
|
PvPipelineLayoutKey=^TvPipelineLayoutKey;
|
|
TvPipelineLayoutKey=record
|
|
FLayouts :AvSetLayout;
|
|
FPushConsts:AvPushConstantRange;
|
|
end;
|
|
|
|
TvPipelineLayout=class
|
|
FHandle:TVkPipelineLayout;
|
|
key:TvPipelineLayoutKey;
|
|
//
|
|
FBinds:TVkUInt32;
|
|
FSets :TVkUInt32;
|
|
FTypes:TVkUInt32;
|
|
//
|
|
FCounts:TvCountsGroup;
|
|
//
|
|
Procedure AddLayout(F:TvSetLayout);
|
|
Procedure SetLayouts(const A:AvSetLayout);
|
|
Procedure AddPushConst(offset,size:TVkUInt32;Flags:TVkShaderStageFlags);
|
|
Procedure SetPushConst(const A:AvPushConstantRange);
|
|
procedure Clear;
|
|
function Compile:Boolean;
|
|
procedure calc_counts;
|
|
Destructor Destroy; override;
|
|
Function isSpace:Boolean;
|
|
end;
|
|
|
|
TvPipelineCache=class
|
|
FHandle:TVkPipelineCache;
|
|
Constructor Create(data:Pointer;size:TVkSize);
|
|
Destructor Destroy; override;
|
|
end;
|
|
|
|
TvPipeline=class(TvRefsObject)
|
|
FHandle:TVkPipeline;
|
|
FPCache:TvPipelineCache;
|
|
Destructor Destroy; override;
|
|
end;
|
|
|
|
TvRenderPass=class(TvRefsObject)
|
|
FHandle:TVkRenderPass;
|
|
Destructor Destroy; override;
|
|
end;
|
|
|
|
///////
|
|
|
|
implementation
|
|
|
|
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;
|
|
end;
|
|
|
|
Procedure TvSetLayout.SetBinds(const A:AVkDescriptorSetLayoutBinding);
|
|
begin
|
|
key.FBinds:=A;
|
|
end;
|
|
|
|
Function TvSetLayout.IsSpace:Boolean; inline;
|
|
begin
|
|
Result:=Length(key.FBinds)=0;
|
|
end;
|
|
|
|
Procedure TvSetLayout.Clear;
|
|
begin
|
|
SetLength(key.FBinds,0);
|
|
key.FFlags:=0;
|
|
end;
|
|
|
|
function TvSetLayout.Compile:Boolean;
|
|
var
|
|
cinfo:TVkDescriptorSetLayoutCreateInfo;
|
|
binfo:TVkDescriptorSetLayoutBindingFlagsCreateInfo;
|
|
bflag:array of TVkDescriptorBindingFlags;
|
|
r:TVkResult;
|
|
i,c:Integer;
|
|
partially:Boolean;
|
|
begin
|
|
Result:=False;
|
|
|
|
if (FHandle<>VK_NULL_HANDLE) then Exit(True);
|
|
|
|
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;
|
|
//
|
|
{
|
|
if (limits.DescriptorIndexingFeatures.descriptorBindingPartiallyBound<>0) then
|
|
begin
|
|
partially:=False;
|
|
c:=Length(key.FBinds);
|
|
if (c<>0) then
|
|
begin
|
|
For i:=0 to c-1 do
|
|
if (key.FBinds[i].descriptorCount>1) then
|
|
begin
|
|
partially:=True;
|
|
Break;
|
|
end;
|
|
end;
|
|
//
|
|
if partially then
|
|
begin
|
|
SetLength(bflag,c);
|
|
For i:=0 to c-1 do
|
|
begin
|
|
bflag[i]:=0;
|
|
if (key.FBinds[i].descriptorCount>1) then
|
|
begin
|
|
bflag[i]:=ord(VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT) or
|
|
ord(VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT);
|
|
end;
|
|
end;
|
|
//
|
|
binfo:=Default(TVkDescriptorSetLayoutBindingFlagsCreateInfo);
|
|
binfo.sType:=VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO;
|
|
binfo.bindingCount :=c;
|
|
binfo.pBindingFlags:=@bflag[0];
|
|
//
|
|
cinfo.pNext:=@binfo;
|
|
end;
|
|
end;
|
|
}
|
|
//
|
|
r:=vkCreateDescriptorSetLayout(Device.FHandle,@cinfo,nil,@FHandle);
|
|
if (r<>VK_SUCCESS) then
|
|
begin
|
|
Writeln(StdErr,'vkCreateDescriptorSetLayout:',r);
|
|
Exit;
|
|
end;
|
|
Result:=True;
|
|
end;
|
|
|
|
Destructor TvSetLayout.Destroy;
|
|
begin
|
|
if (FHandle<>VK_NULL_HANDLE) then
|
|
begin
|
|
vkDestroyDescriptorSetLayout(Device.FHandle,FHandle,nil);
|
|
end;
|
|
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);
|
|
end;
|
|
False:
|
|
if (key.FFlags=ord(VK_DESCRIPTOR_SET_LAYOUT_CREATE_PUSH_DESCRIPTOR_BIT_KHR)) then
|
|
begin
|
|
key.FFlags:=0;
|
|
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
|
|
begin
|
|
vkDestroyPipelineLayout(Device.FHandle,FHandle,nil);
|
|
end;
|
|
end;
|
|
|
|
Procedure TvPipelineLayout.AddLayout(F:TvSetLayout);
|
|
begin
|
|
if (F=nil) then Exit;
|
|
Insert(F,key.FLayouts,Length(key.FLayouts));
|
|
end;
|
|
|
|
Procedure TvPipelineLayout.SetLayouts(const A:AvSetLayout);
|
|
begin
|
|
key.FLayouts:=A;
|
|
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;
|
|
end;
|
|
|
|
Procedure TvPipelineLayout.SetPushConst(const A:AvPushConstantRange);
|
|
begin
|
|
key.FPushConsts:=A;
|
|
end;
|
|
|
|
Function TvPipelineLayout.isSpace:Boolean;
|
|
begin
|
|
Result:=(FBinds=0);
|
|
end;
|
|
|
|
procedure TvPipelineLayout.Clear;
|
|
begin
|
|
SetLength(key.FLayouts ,0);
|
|
SetLength(key.FPushConsts,0);
|
|
FBinds:=0;
|
|
FSets :=0;
|
|
FTypes:=0;
|
|
//
|
|
FCounts:=Default(TvCountsGroup);
|
|
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 Exit(True);
|
|
|
|
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
|
|
Assert(key.FLayouts[i]<>nil,'key.FLayouts[i]=nil');
|
|
_data_set[i]:=key.FLayouts[i].FHandle;
|
|
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;
|
|
|
|
calc_counts;
|
|
|
|
Result:=True;
|
|
end;
|
|
|
|
procedure TvPipelineLayout.calc_counts;
|
|
var
|
|
i,b:Integer;
|
|
t:Byte;
|
|
begin
|
|
if Length(key.FLayouts)<>0 then
|
|
begin
|
|
For i:=0 to High(key.FLayouts) do
|
|
With key.FLayouts[i] do
|
|
if (Length(key.FBinds)<>0) then
|
|
begin
|
|
Inc(FBinds,Length(key.FBinds));
|
|
Inc(FSets);
|
|
For b:=0 to High(key.FBinds) do
|
|
with key.FBinds[b] do
|
|
begin
|
|
t:=_GetIdByType(descriptorType);
|
|
|
|
if (FCounts[t]=0) then
|
|
begin
|
|
Inc(FTypes);
|
|
end;
|
|
|
|
Inc(FCounts[t],descriptorCount);
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
Constructor TvPipelineCache.Create(data:Pointer;size:TVkSize);
|
|
var
|
|
info:TVkPipelineCacheCreateInfo;
|
|
r:TVkResult;
|
|
begin
|
|
info:=Default(TVkPipelineCacheCreateInfo);
|
|
info.sType:=VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
|
|
info.initialDataSize:=size;
|
|
info.pInitialData :=data;
|
|
|
|
r:=vkCreatePipelineCache(Device.FHandle,@info,nil,@FHandle);
|
|
|
|
if (r<>VK_SUCCESS) then
|
|
begin
|
|
Writeln(StdErr,'vkCreatePipelineCache:',r);
|
|
end;
|
|
end;
|
|
|
|
Destructor TvPipelineCache.Destroy;
|
|
begin
|
|
if (FHandle<>VK_NULL_HANDLE) then
|
|
begin
|
|
vkDestroyPipelineCache(Device.FHandle,FHandle,nil);
|
|
end;
|
|
end;
|
|
|
|
Destructor TvPipeline.Destroy;
|
|
begin
|
|
if (FHandle<>VK_NULL_HANDLE) then
|
|
begin
|
|
vkDestroyPipeline(Device.FHandle,FHandle,nil);
|
|
end;
|
|
end;
|
|
|
|
Destructor TvRenderPass.Destroy;
|
|
begin
|
|
if (FHandle<>VK_NULL_HANDLE) then
|
|
begin
|
|
vkDestroyRenderPass(Device.FHandle,FHandle,nil);
|
|
end;
|
|
end;
|
|
|
|
|
|
end.
|
|
|