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;