diff --git a/projects/triangle/triangle.lpi b/projects/triangle/triangle.lpi
index c40805e..aede3e8 100644
--- a/projects/triangle/triangle.lpi
+++ b/projects/triangle/triangle.lpi
@@ -33,7 +33,7 @@
-
+
@@ -185,6 +185,14 @@
+
+
+
+
+
+
+
+
diff --git a/projects/triangle/triangle.lpr b/projects/triangle/triangle.lpr
index 32c0b5a..aef63e3 100644
--- a/projects/triangle/triangle.lpr
+++ b/projects/triangle/triangle.lpr
@@ -7,7 +7,7 @@ uses
{$IFDEF UNIX}{$IFDEF UseCThreads}
cthreads,
{$ENDIF}{$ENDIF}
- Interfaces, Dialogs, Forms, uMainForm, Vulkan;
+ Interfaces, Dialogs, Forms, uMainForm, Vulkan, uvkuPipelineLayout, uvkuPipelineLayoutFactory;
{$R *.res}
diff --git a/projects/triangle/triangle.lps b/projects/triangle/triangle.lps
index cab35dd..b87148e 100644
--- a/projects/triangle/triangle.lps
+++ b/projects/triangle/triangle.lps
@@ -4,14 +4,13 @@
-
+
-
-
-
+
+
@@ -23,21 +22,21 @@
-
+
-
-
-
+
+
+
-
+
@@ -45,7 +44,7 @@
-
+
@@ -53,7 +52,7 @@
-
+
@@ -61,7 +60,7 @@
-
+
@@ -69,7 +68,7 @@
-
+
@@ -77,14 +76,14 @@
-
+
-
+
-
+
@@ -93,22 +92,22 @@
-
+
-
+
-
+
-
+
-
+
@@ -117,7 +116,7 @@
-
+
@@ -125,14 +124,14 @@
-
+
-
+
-
+
@@ -141,7 +140,7 @@
-
+
@@ -149,7 +148,7 @@
-
+
@@ -157,7 +156,7 @@
-
+
@@ -165,31 +164,31 @@
-
+
-
+
-
+
-
-
-
-
+
+
+
+
-
+
-
+
@@ -198,31 +197,31 @@
-
+
-
+
-
+
-
+
-
+
-
+
-
+
@@ -230,7 +229,7 @@
-
+
@@ -238,15 +237,16 @@
-
+
+
-
-
-
+
+
+
@@ -259,10 +259,10 @@
-
+
-
+
@@ -393,7 +393,7 @@
-
+
@@ -414,19 +414,19 @@
-
+
-
+
-
+
-
+
@@ -441,132 +441,150 @@
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/projects/utils/VulkanUtils.pas b/projects/utils/VulkanUtils.pas
index 997d7ab..4a83486 100644
--- a/projects/utils/VulkanUtils.pas
+++ b/projects/utils/VulkanUtils.pas
@@ -14,7 +14,9 @@ uses
uvkuImage, uvkuImageFactory, uvkuImageView, uvkuImageViewFactory,
uvkuBuffer, uvkuBufferFactory, uvkuBufferView, uvkuBufferViewFactory,
uvkuCommandPool, uvkuCommandPoolFactory, uvkuCommandBuffer,
- uvkuRenderPass, uvkuRenderPassFactory, uvkuFrameBuffer, uvkuFrameBufferFactory,
+ uvkuRenderPass, uvkuRenderPassFactory,
+ uvkuFrameBuffer, uvkuFrameBufferFactory,
+ uvkuPipelineLayout, uvkuPipelineLayoutFactory,
uvkuUtils;
type
@@ -87,10 +89,17 @@ type
TvkuRenderPass = uvkuRenderPass.TvkuRenderPass;
TvkuRenderPassEx = uvkuRenderPassFactory.TvkuRenderPassEx;
TvkuRenderPassFactory = uvkuRenderPassFactory.TvkuRenderPassFactory;
+
+ { FrameBuffer }
TvkuFrameBuffer = uvkuFrameBuffer.TvkuFrameBuffer;
TvkuFrameBufferEx = uvkuFrameBufferFactory.TvkuFrameBufferEx;
TvkuFrameBufferFactory = uvkuFrameBufferFactory.TvkuFrameBufferFactory;
+ { Pipeline }
+ TvkuPipelineLayout = uvkuPipelineLayout.TvkuPipelineLayout;
+ TvkuPipelineLayoutEx = uvkuPipelineLayoutFactory.TvkuPipelineLayoutEx;
+ TvkuPipelineLayoutFactory = uvkuPipelineLayoutFactory.TvkuPipelineLayoutFactory;
+
{ Utils }
TvkuException = uvkuUtils.TvkuException;
TvkuErrorException = uvkuUtils.TvkuErrorException;
diff --git a/projects/utils/uvkuPipelineLayout.pas b/projects/utils/uvkuPipelineLayout.pas
new file mode 100644
index 0000000..e02aa14
--- /dev/null
+++ b/projects/utils/uvkuPipelineLayout.pas
@@ -0,0 +1,84 @@
+unit uvkuPipelineLayout;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils,
+ Vulkan, uvkuBase;
+
+type
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ TvkuPipelineLayout = class(TvkuAllocHandle)
+ private
+ fHandle: VkPipelineLayout;
+ fDeviceCommands: TVkDeviceCommands;
+
+ procedure CreateHandle(const aCreateInfo: TVkPipelineLayoutCreateInfo);
+ public
+ property Handle: VkPipelineLayout read fHandle;
+ property DeviceCommands: TVkDeviceCommands read fDeviceCommands;
+
+ constructor Create(
+ const aCreateInfo: TVkPipelineLayoutCreateInfo;
+ const aDeviceCommands: TVkDeviceCommands;
+ const aAllocCallbacks: PVkAllocationCallbacks = nil);
+ constructor Create(
+ const aHandle: VkPipelineLayout;
+ const aOwnsHandle: Boolean;
+ const aDeviceCommands: TVkDeviceCommands;
+ const aAllocCallbacks: PVkAllocationCallbacks = nil);
+ destructor Destroy; override;
+ end;
+
+implementation
+
+uses
+ uvkuUtils;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TvkuPipelineLayout/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TvkuPipelineLayout.CreateHandle(const aCreateInfo: TVkPipelineLayoutCreateInfo);
+var err: TVkResult;
+begin
+ if not Assigned(fDeviceCommands.vkCreatePipelineLayout) then
+ raise TvkuInvalidFuncPtrException.Create('vkCreatePipelineLayout');
+ err := fDeviceCommands.vkCreatePipelineLayout(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle);
+ if (err < VK_SUCCESS) then
+ raise TvkuErrorException.Create('unable to create pipeline layout', err);
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TvkuPipelineLayout.Create(const aCreateInfo: TVkPipelineLayoutCreateInfo;
+ const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks);
+begin
+ inherited Create;
+ fDeviceCommands := aDeviceCommands;
+ SetAllocCallbacks(aAllocCallbacks);
+ CreateHandle(aCreateInfo);
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+constructor TvkuPipelineLayout.Create(const aHandle: VkPipelineLayout; const aOwnsHandle: Boolean;
+ const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks);
+begin
+ inherited Create;
+ fHandle := aHandle;
+ fDeviceCommands := aDeviceCommands;
+ OwnsHandle := aOwnsHandle;
+ SetAllocCallbacks(aAllocCallbacks);
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+destructor TvkuPipelineLayout.Destroy;
+begin
+ if OwnsHandle and (fHandle <> VK_INVALID_NDP_HANDLE) then
+ fDeviceCommands.vkDestroyPipelineLayout(fDeviceCommands.Device, fHandle, AllocCallbacks);
+ fHandle := VK_INVALID_NDP_HANDLE;
+ inherited Destroy;
+end;
+
+end.
+
diff --git a/projects/utils/uvkuPipelineLayoutFactory.pas b/projects/utils/uvkuPipelineLayoutFactory.pas
new file mode 100644
index 0000000..ea145b0
--- /dev/null
+++ b/projects/utils/uvkuPipelineLayoutFactory.pas
@@ -0,0 +1,158 @@
+unit uvkuPipelineLayoutFactory;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils,
+ Vulkan, uvkuFactoryBase, uvkuPipelineLayout, uvkuAllocationHandler, uvkuTypes;
+
+type
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ TvkuPipelineLayoutEx = class(TvkuPipelineLayout)
+ private
+ fAllocHandler: TvkuAllocationHandler;
+ fOwnsHandler: Boolean;
+ public
+ destructor Destroy; override;
+ end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ TvkuPipelineLayoutFactory = class(TvkuDeviceObjFactory)
+ private
+ fFlags: VkPipelineLayoutCreateFlags;
+ fSetLayouts: TvkuDescriptorSetLayoutArr;
+ fPushConstantRanges: TvkuPushConstantRangeArr;
+
+ function GetPushConstantRange(const aIndex: Integer): TVkPushConstantRange;
+ function GetPushConstantRangeCount: Integer;
+ function GetSetLayout(const aIndex: Integer): VkDescriptorSetLayout;
+ function GetSetLayoutCount: Integer;
+ procedure SetPushConstantRange(const aIndex: Integer; aValue: TVkPushConstantRange);
+ procedure SetPushConstantRangeCount(aValue: Integer);
+ procedure SetSetLayout(const aIndex: Integer; aValue: VkDescriptorSetLayout);
+ procedure SetSetLayoutCount(aValue: Integer);
+ public
+ property Flags: VkPipelineLayoutCreateFlags read fFlags write fFlags;
+
+ property SetLayouts: TvkuDescriptorSetLayoutArr read fSetLayouts write fSetLayouts;
+ property SetLayoutCount: Integer read GetSetLayoutCount write SetSetLayoutCount;
+ property SetLayout[const aIndex: Integer]: VkDescriptorSetLayout read GetSetLayout write SetSetLayout;
+
+ property PushConstantRanges: TvkuPushConstantRangeArr read fPushConstantRanges write fPushConstantRanges;
+ property PushConstantRangeCount: Integer read GetPushConstantRangeCount write SetPushConstantRangeCount;
+ property PushConstantRange[const aIndex: Integer]: TVkPushConstantRange read GetPushConstantRange write SetPushConstantRange;
+
+ function CreatePipelineLayout: TvkuPipelineLayoutEx;
+ function CreatePipelineLayout(
+ const aAllocHandler: TvkuAllocationHandler;
+ const aOwnsHandler: Boolean): TvkuPipelineLayoutEx;
+ end;
+
+implementation
+
+uses
+ uvkuUtils;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TvkuPipelineLayoutEx///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+destructor TvkuPipelineLayoutEx.Destroy;
+begin
+ inherited Destroy;
+ if fOwnsHandler then
+ FreeAndNil(fAllocHandler);
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//TvkuPipelineLayoutFactory//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TvkuPipelineLayoutFactory.GetPushConstantRange(const aIndex: Integer): TVkPushConstantRange;
+begin
+ if (aIndex < low(fPushConstantRanges)) or (aIndex > high(fPushConstantRanges)) then
+ raise TvkuException.CreateFmt('index (%d) out of range (%d : %d)', [aIndex, Low(fPushConstantRanges), High(fPushConstantRanges)]);
+ result := fPushConstantRanges[aIndex];
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TvkuPipelineLayoutFactory.GetPushConstantRangeCount: Integer;
+begin
+ result := Length(fPushConstantRanges);
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TvkuPipelineLayoutFactory.GetSetLayout(const aIndex: Integer): VkDescriptorSetLayout;
+begin
+ if (aIndex < low(fSetLayouts)) or (aIndex > high(fSetLayouts)) then
+ raise TvkuException.CreateFmt('index (%d) out of range (%d : %d)', [aIndex, Low(fSetLayouts), High(fSetLayouts)]);
+ result := fSetLayouts[aIndex];
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TvkuPipelineLayoutFactory.GetSetLayoutCount: Integer;
+begin
+ result := Length(fSetLayouts);
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TvkuPipelineLayoutFactory.SetPushConstantRange(const aIndex: Integer; aValue: TVkPushConstantRange);
+begin
+ if (aIndex < low(fPushConstantRanges)) or (aIndex > high(fPushConstantRanges)) then
+ raise TvkuException.CreateFmt('index (%d) out of range (%d : %d)', [aIndex, Low(fPushConstantRanges), High(fPushConstantRanges)]);
+ fPushConstantRanges[aIndex] := aValue;
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TvkuPipelineLayoutFactory.SetPushConstantRangeCount(aValue: Integer);
+begin
+ SetLength(fPushConstantRanges, aValue);
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TvkuPipelineLayoutFactory.SetSetLayout(const aIndex: Integer; aValue: VkDescriptorSetLayout);
+begin
+ if (aIndex < low(fSetLayouts)) or (aIndex > high(fSetLayouts)) then
+ raise TvkuException.CreateFmt('index (%d) out of range (%d : %d)', [aIndex, Low(fSetLayouts), High(fSetLayouts)]);
+ fSetLayouts[aIndex] := aValue;
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+procedure TvkuPipelineLayoutFactory.SetSetLayoutCount(aValue: Integer);
+begin
+ SetLength(fSetLayouts, aValue);
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TvkuPipelineLayoutFactory.CreatePipelineLayout: TvkuPipelineLayoutEx;
+begin
+ result := CreatePipelineLayout(nil, false);
+end;
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+function TvkuPipelineLayoutFactory.CreatePipelineLayout(const aAllocHandler: TvkuAllocationHandler;
+ const aOwnsHandler: Boolean): TvkuPipelineLayoutEx;
+var CreateInfo: TVkPipelineLayoutCreateInfo;
+begin
+ FillByte(CreateInfo, SizeOf(CreateInfo), 0);
+ CreateInfo.sType := VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ CreateInfo.pNext := nil;
+ CreateInfo.flags := fFlags;
+ CreateInfo.setLayoutCount := Length(fSetLayouts);
+ CreateInfo.pSetLayouts := @fSetLayouts[0];
+ CreateInfo.pushConstantRangeCount := Length(fPushConstantRanges);
+ CreateInfo.pPushConstantRanges := @fPushConstantRanges[0];
+ if Assigned(aAllocHandler)
+ then result := TvkuPipelineLayoutEx.Create(CreateInfo, DeviceCommands, aAllocHandler.GetAllocationCallbacksPtr)
+ else result := TvkuPipelineLayoutEx.Create(CreateInfo, DeviceCommands);
+ try
+ TvkuPipelineLayoutEx(result).fAllocHandler := aAllocHandler;
+ TvkuPipelineLayoutEx(result).fOwnsHandler := aOwnsHandler;
+ except
+ FreeAndNil(result);
+ raise;
+ end;
+end;
+
+end.
+
diff --git a/projects/utils/uvkuTypes.pas b/projects/utils/uvkuTypes.pas
index ae8a9ec..927f8e0 100644
--- a/projects/utils/uvkuTypes.pas
+++ b/projects/utils/uvkuTypes.pas
@@ -27,6 +27,8 @@ type
TvkuSubpassDependencyArr = array of TVkSubpassDependency;
TvkuImageViewArr = array of VkImageView;
TvkuDescriptorSetLayoutBindingArr = array of TVkDescriptorSetLayoutBinding;
+ TvkuDescriptorSetLayoutArr = array of VkDescriptorSetLayout;
+ TvkuPushConstantRangeArr = array of TVkPushConstantRange;
TvkuApplicationInfo = packed record
AppName: String;