diff --git a/projects/triangle/triangle.lpi b/projects/triangle/triangle.lpi index d830415..2c203dd 100644 --- a/projects/triangle/triangle.lpi +++ b/projects/triangle/triangle.lpi @@ -33,7 +33,7 @@ - + @@ -74,25 +74,85 @@ - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/projects/triangle/triangle.lps b/projects/triangle/triangle.lps index 311b57e..b2018b3 100644 --- a/projects/triangle/triangle.lps +++ b/projects/triangle/triangle.lps @@ -4,13 +4,13 @@ - + - + @@ -18,383 +18,502 @@ - - - + + + - - - - + + + - - + + - + - - - + + - - - + + + - - - - + + + + - - - - - + + + + - - - - + + + + - - - + + + - - - + + + - - - - + + + + - - - + + + - - - - - + + + + - - - - + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - - - - - - - diff --git a/projects/triangle/uMainForm.pas b/projects/triangle/uMainForm.pas index e2635e3..fdf3b12 100644 --- a/projects/triangle/uMainForm.pas +++ b/projects/triangle/uMainForm.pas @@ -6,12 +6,7 @@ interface uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls, - Vulkan, uvkuAllocationHandler, - uvkuInstance, uvkuInstanceFactory, - uvkuPhysicalDevice, uvkuPhysicalDeviceFactory, - uvkuSurface, uvkuSurfaceFactory, - uvkuDevice, uvkuDeviceFactory, - uvkuSwapChain, uvkuSwapChainFactory; + Vulkan, VulkanUtils; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -32,6 +27,7 @@ type fInstance: TvkuInstance; fPhyDevice: TvkuPhysicalDevice; fDevice: TvkuDevice; + fQueue: TvkuQueue; fSurface: TvkuSurface; fSwapChain: TvkuSwapChain; public @@ -78,7 +74,6 @@ procedure TMainForm.FormCreate(Sender: TObject); var PhyDevices: TvkuPhysicalDeviceArr; iFactory: TvkuInstanceFactory; - pdFactory: TvkuPhysicalDeviceFactory; dFactory: TvkuDeviceFactory; sFactory: TvkuSurfaceFactory; scFactory: TvkuSwapChainFactory; @@ -107,13 +102,7 @@ begin PhyDevices := fInstance.GetPhysicalDevices; if (Length(PhyDevices) <= 0) then raise Exception.Create('unable to get physical device'); - pdFactory := TvkuPhysicalDeviceFactory.Create(fInstance); - try - fPhyDevice := pdFactory.CreatePhysicalDevice(PhyDevices[0]); - finally - FreeAndNil(pdFactory); - end; - + fPhyDevice := TvkuPhysicalDevice.Create(PhyDevices[0], fInstance.InstanceCommands); WriteLn('create vulkan surface'); sFactory := TvkuSurfaceFactory.Create(fInstance); @@ -141,6 +130,11 @@ begin FreeAndNil(dFactory); end; + + WriteLn('get queue from device'); + fQueue := TvkuQueue.Create(fDevice.GetQueue(0, 0), fDevice.DeviceCommands); + + WriteLn('create swap chain'); scFactory := TvkuSwapChainFactory.Create(fDevice); try @@ -210,6 +204,7 @@ end; procedure TMainForm.FormDestroy(Sender: TObject); begin FreeAndNil(fSwapChain); + FreeAndNil(fQueue); FreeAndNil(fDevice); FreeAndNil(fSurface); FreeAndNil(fPhyDevice); diff --git a/projects/utils/VulkanUtils.pas b/projects/utils/VulkanUtils.pas new file mode 100644 index 0000000..adb7ab8 --- /dev/null +++ b/projects/utils/VulkanUtils.pas @@ -0,0 +1,87 @@ +unit VulkanUtils; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + uvkuTypes, uvkuAllocationHandler, + uvkuInstance, uvkuInstanceFactory, + uvkuPhysicalDevice, uvkuDevice, uvkuDeviceFactory, uvkuDeviceMemory, uvkuQueue, + uvkuSurface, uvkuSurfaceFactory, + uvkuSwapChain, uvkuSwapChainFactory, + uvkuImage, uvkuImageFactory, uvkuImageView, uvkuImageViewFactory, + uvkuBuffer, uvkuBufferFactory, uvkuBufferView, uvkuBufferViewFactory, + uvkuCommandPool, uvkuCommandPoolFactory, uvkuCommandBuffer; + +type + { Types } + TvkuFloatArr = uvkuTypes.TvkuFloatArr; + TvkuUint32Arr = uvkuTypes.TvkuUint32Arr; + TvkuImageArr = uvkuTypes.TvkuImageArr; + TvkuPhysicalDeviceArr = uvkuTypes.TvkuPhysicalDeviceArr; + TvkuQueueFamilyPropertiesArr = uvkuTypes.TvkuQueueFamilyPropertiesArr; + TvkuSparseImageFormatPropertiesArr = uvkuTypes.TvkuSparseImageFormatPropertiesArr; + TvkuSurfaceFormatArr = uvkuTypes.TvkuSurfaceFormatArr; + TvkuPresentModeArr = uvkuTypes.TvkuPresentModeArr; + TvkuDisplayPropertiesArr = uvkuTypes.TvkuDisplayPropertiesArr; + TvkuDisplayPlanePropertiesArr = uvkuTypes.TvkuDisplayPlanePropertiesArr; + TvkuDisplayArr = uvkuTypes.TvkuDisplayArr; + TvkuDisplayModePropertiesArr = uvkuTypes.TvkuDisplayModePropertiesArr; + TvkuCommandBufferArr = uvkuTypes.TvkuCommandBufferArr; + TvkuApplicationInfo = uvkuTypes.TvkuApplicationInfo; + TvkuQueueCreateInfo = uvkuTypes.TvkuQueueCreateInfo; + TvkuQueueCreateInfoArr = uvkuTypes.TvkuQueueCreateInfoArr; + + TvkuAllocationHandler = uvkuAllocationHandler.TvkuAllocationHandler; + + { Instance } + TvkuInstance = uvkuInstance.TvkuInstance; + TvkuInstanceEx = uvkuInstanceFactory.TvkuInstanceEx; + TvkuInstanceFactory = uvkuInstanceFactory.TvkuInstanceFactory; + + { Device } + TvkuPhysicalDevice = uvkuPhysicalDevice.TvkuPhysicalDevice; + TvkuDevice = uvkuDevice.TvkuDevice; + TvkuDeviceEx = uvkuDeviceFactory.TvkuDeviceEx; + TvkuDeviceFactory = uvkuDeviceFactory.TvkuDeviceFactory; + TvkuDeviceMemory = uvkuDeviceMemory.TvkuDeviceMemory; + TvkuQueue = uvkuQueue.TvkuQueue; + + { Surface } + TvkuSurface = uvkuSurface.TvkuSurface; + TvkuSurfaceEx = uvkuSurfaceFactory.TvkuSurfaceEx; + TvkuSurfaceFactory = uvkuSurfaceFactory.TvkuSurfaceFactory; + + { SwapChain } + TvkuSwapChain = uvkuSwapChain.TvkuSwapChain; + TvkuSwapChainEx = uvkuSwapChainFactory.TvkuSwapChainEx; + TvkuSwapChainFactory = uvkuSwapChainFactory.TvkuSwapChainFactory; + + { Image } + TvkuImage = uvkuImage.TvkuImage; + TvkuImageEx = uvkuImageFactory.TvkuImageEx; + TvkuImageFactory = uvkuImageFactory.TvkuImageFactory; + TvkuImageView = uvkuImageView.TvkuImageView; + TvkuImageViewEx = uvkuImageViewFactory.TvkuImageViewEx; + TvkuImageViewFactory = uvkuImageViewFactory.TvkuImageViewFactory; + + { Buffer } + TvkuBuffer = uvkuBuffer.TvkuBuffer; + TvkuBufferEx = uvkuBufferFactory.TvkuBufferEx; + TvkuBufferFactory = uvkuBufferFactory.TvkuBufferFactory; + TvkuBufferView = uvkuBufferView.TvkuBufferView; + TvkuBufferViewEx = uvkuBufferViewFactory.TvkuBufferViewEx; + TvkuBufferViewFactory = uvkuBufferViewFactory.TvkuBufferViewFactory; + + { Commands } + TvkuCommandPool = uvkuCommandPool.TvkuCommandPool; + TvkuCommandPoolEx = uvkuCommandPoolFactory.TvkuCommandPoolEx; + TvkuCommandPoolFactory = uvkuCommandPoolFactory.TvkuCommandPoolFactory; + TvkuCommandBuffer = uvkuCommandBuffer.TvkuCommandBuffer; + +implementation + +end. + diff --git a/projects/utils/uvkuAllocationHandler.pas b/projects/utils/uvkuAllocationHandler.pas index 8dea193..11a8e84 100644 --- a/projects/utils/uvkuAllocationHandler.pas +++ b/projects/utils/uvkuAllocationHandler.pas @@ -11,6 +11,8 @@ uses type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TvkuAllocationHandler = class(TObject) + private + fAllocCallbacks: PVkAllocationCallbacks; protected function AllocateMemory(const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid; virtual; function ReallocateMemory(const aOriginal: PVkVoid; const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid; virtual; @@ -20,6 +22,10 @@ type procedure InternalFreeNotification(const aSize: VkSize; const aType: TVkInternalAllocationType; const aScope: TVkSystemAllocationScope); public function GetAllocationCallbacks: TVkAllocationCallbacks; + function GetAllocationCallbacksPtr: PVkAllocationCallbacks; + + constructor Create; + destructor Destroy; override; end; implementation @@ -90,13 +96,40 @@ end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuAllocationHandler.GetAllocationCallbacks: TVkAllocationCallbacks; begin - FillByte(result{%H-}, SizeOf(result), 0); - result.pUserData := self; - result.pfnAllocation := @AllocateMemoryCallback; - result.pfnReallocation := @ReallocateMemoryCallback; - result.pfnFree := @FreeMemoryCallback; - result.pfnInternalAllocation := @InternalAllocationCallback; - result.pfnInternalFree := @InternalFreeCallback; + result := GetAllocationCallbacksPtr^; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuAllocationHandler.GetAllocationCallbacksPtr: PVkAllocationCallbacks; +begin + if not Assigned(fAllocCallbacks) then begin + new(fAllocCallbacks); + FillByte(fAllocCallbacks^, SizeOf(result), 0); + fAllocCallbacks^.pUserData := self; + fAllocCallbacks^.pfnAllocation := @AllocateMemoryCallback; + fAllocCallbacks^.pfnReallocation := @ReallocateMemoryCallback; + fAllocCallbacks^.pfnFree := @FreeMemoryCallback; + fAllocCallbacks^.pfnInternalAllocation := @InternalAllocationCallback; + fAllocCallbacks^.pfnInternalFree := @InternalFreeCallback; + end; + result := fAllocCallbacks; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuAllocationHandler.Create; +begin + inherited Create; + fAllocCallbacks := nil; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuAllocationHandler.Destroy; +begin + if Assigned(fAllocCallbacks) then begin + Dispose(fAllocCallbacks); + fAllocCallbacks := nil; + end; + inherited Destroy; end; end. diff --git a/projects/utils/uvkuBase.pas b/projects/utils/uvkuBase.pas new file mode 100644 index 0000000..a53331e --- /dev/null +++ b/projects/utils/uvkuBase.pas @@ -0,0 +1,92 @@ +unit uvkuBase; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuObject = class(TObject) + end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuHandle = class(TvkuObject) + private + fOwnsHandle: Boolean; + public + property OwnsHandle: Boolean read fOwnsHandle write fOwnsHandle; + constructor Create; + end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuAllocHandle = class(TvkuHandle) + private + fAllocCallbacks: PVkAllocationCallbacks; + protected + property AllocCallbacks: PVkAllocationCallbacks read fAllocCallbacks; + + procedure SetAllocCallbacks(const aAllocCallbacks: TVkAllocationCallbacks); + procedure SetAllocCallbacks(const aAllocCallbacks: PVkAllocationCallbacks); + procedure DisposeAllocCallbacks; + public + constructor Create; + destructor Destroy; override; + end; + +implementation + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuHandle///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuHandle.Create; +begin + inherited Create; + fOwnsHandle := true; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuAllocHandle//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuAllocHandle.SetAllocCallbacks(const aAllocCallbacks: TVkAllocationCallbacks); +begin + if not Assigned(fAllocCallbacks) then + new(fAllocCallbacks); + fAllocCallbacks^ := aAllocCallbacks; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuAllocHandle.SetAllocCallbacks(const aAllocCallbacks: PVkAllocationCallbacks); +begin + if Assigned(aAllocCallbacks) then + SetAllocCallbacks(aAllocCallbacks^); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuAllocHandle.DisposeAllocCallbacks; +begin + if not Assigned(fAllocCallbacks) then + exit; + Dispose(fAllocCallbacks); + fAllocCallbacks := nil; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuAllocHandle.Create; +begin + inherited Create; + fAllocCallbacks := nil; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuAllocHandle.Destroy; +begin + inherited Destroy; + DisposeAllocCallbacks; +end; + +end. + diff --git a/projects/utils/uvkuBuffer.pas b/projects/utils/uvkuBuffer.pas new file mode 100644 index 0000000..39aee69 --- /dev/null +++ b/projects/utils/uvkuBuffer.pas @@ -0,0 +1,82 @@ +unit uvkuBuffer; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuBase; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuBuffer = class(TvkuAllocHandle) + private + fHandle: VkBuffer; + fDeviceCommands: TVkDeviceCommands; + + procedure CreateHandle(const aCreateInfo: TVkBufferCreateInfo); + public + property Handle: VkBuffer read fHandle; + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + + constructor Create( + const aCreateInfo: TVkBufferCreateInfo; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + constructor Create( + const aHandle: VkBuffer; + const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + destructor Destroy; override; + end; + +implementation + +uses + uvkuUtils; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuBuffer///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuBuffer.CreateHandle(const aCreateInfo: TVkBufferCreateInfo); +var err: TVkResult; +begin + err := fDeviceCommands.vkCreateBuffer(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); + if (err < VK_SUCCESS) then + raise TvkuErrorException.Create('unable to create buffer', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuBuffer.Create(const aCreateInfo: TVkBufferCreateInfo; const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fDeviceCommands := aDeviceCommands; + SetAllocCallbacks(aAllocCallbacks); + CreateHandle(aCreateInfo); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuBuffer.Create(const aHandle: VkBuffer; const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fHandle := aHandle; + fDeviceCommands := aDeviceCommands; + OwnsHandle := aOwnsHandle; + SetAllocCallbacks(aAllocCallbacks); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuBuffer.Destroy; +begin + if OwnsHandle and (fHandle <> VK_INVALID_NDP_HANDLE) then + fDeviceCommands.vkDestroyBuffer(fDeviceCommands.Device, fHandle, AllocCallbacks); + fHandle := VK_INVALID_NDP_HANDLE; + inherited Destroy; +end; + +end. + diff --git a/projects/utils/uvkuBufferFactory.pas b/projects/utils/uvkuBufferFactory.pas new file mode 100644 index 0000000..1e93f21 --- /dev/null +++ b/projects/utils/uvkuBufferFactory.pas @@ -0,0 +1,140 @@ +unit uvkuBufferFactory; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuBuffer, uvkuDevice, uvkuAllocationHandler, uvkuTypes; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuBufferEx = class(TvkuBuffer) + private + fAllocHandler: TvkuAllocationHandler; + fOwnsHandle: Boolean; + public + destructor Destroy; override; + end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuBufferFactory = class(TObject) + private + fDeviceCommands: TVkDeviceCommands; + fFlags: VkBufferCreateFlags; + fSize: VkDeviceSize; + fUsage: VkBufferUsageFlags; + fSharingMode: TVkSharingMode; + fQueueFamilyIndices: TvkuUint32Arr; + + function GetQueueFamilyIndex(const aIndex: Integer): VkUint32; + function GetQueueFamilyIndexCount: Integer; + procedure SetQueueFamilyIndex(const aIndex: Integer; aValue: VkUint32); + public + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + property Flags: VkBufferCreateFlags read fFlags write fFlags; + property Size: VkDeviceSize read fSize write fSize; + property Usage: VkBufferUsageFlags read fUsage write fUsage; + property SharingMode: TVkSharingMode read fSharingMode write fSharingMode; + + property QueueFamilyIndices: TvkuUint32Arr read fQueueFamilyIndices; + property QueueFamilyIndexCount: Integer read GetQueueFamilyIndexCount; + property QueueFamilyIndex[const aIndex: Integer]: VkUint32 read GetQueueFamilyIndex write SetQueueFamilyIndex; + + function CreateBuffer: TvkuBufferEx; + function CreateBuffer( + const aAllocHandler: TvkuAllocationHandler; + const aOwnsHandler: Boolean): TvkuBufferEx; + + constructor Create(const aDevice: TvkuDevice); + constructor Create(const aDeviceCommands: TVkDeviceCommands); + end; + +implementation + +uses + uvkuUtils; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuBufferEx/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuBufferEx.Destroy; +begin + if fOwnsHandle then + FreeAndNil(fAllocHandler); + inherited Destroy; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuBufferFactory////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuBufferFactory.GetQueueFamilyIndex(const aIndex: Integer): VkUint32; +begin + if (aIndex < low(fQueueFamilyIndices)) or (aIndex > high(fQueueFamilyIndices)) then + raise TvkuException.CreateFmt('index (%d) out of range (%d : %d)', [aIndex, Low(fQueueFamilyIndices), High(fQueueFamilyIndices)]); + result := fQueueFamilyIndices[aIndex]; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuBufferFactory.GetQueueFamilyIndexCount: Integer; +begin + result := Length(fQueueFamilyIndices); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuBufferFactory.SetQueueFamilyIndex(const aIndex: Integer; aValue: VkUint32); +begin + if (aIndex < low(fQueueFamilyIndices)) or (aIndex > high(fQueueFamilyIndices)) then + raise TvkuException.CreateFmt('index (%d) out of range (%d : %d)', [aIndex, Low(fQueueFamilyIndices), High(fQueueFamilyIndices)]); + fQueueFamilyIndices[aIndex] := aValue; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuBufferFactory.CreateBuffer: TvkuBufferEx; +begin + result := CreateBuffer(nil, false); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuBufferFactory.CreateBuffer(const aAllocHandler: TvkuAllocationHandler; const aOwnsHandler: Boolean): TvkuBufferEx; +var + CreateInfo: TVkBufferCreateInfo; +begin + FillByte(CreateInfo, 0, SizeOf(CreateInfo)); + CreateInfo.sType := VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + CreateInfo.pNext := nil; + CreateInfo.flags := fFlags; + CreateInfo.size := fSize; + CreateInfo.usage := fUsage; + CreateInfo.sharingMode := fSharingMode; + CreateInfo.queueFamilyIndexCount := Length(fQueueFamilyIndices); + CreateInfo.pQueueFamilyIndices := @fQueueFamilyIndices[0]; + + if Assigned(aAllocHandler) + then result := TvkuBufferEx.Create(CreateInfo, fDeviceCommands, aAllocHandler.GetAllocationCallbacksPtr) + else result := TvkuBufferEx.Create(CreateInfo, fDeviceCommands); + try + TvkuBufferEx(result).fAllocHandler := aAllocHandler; + TvkuBufferEx(result).fOwnsHandle := aOwnsHandler; + except + FreeAndNil(result); + raise; + end; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuBufferFactory.Create(const aDevice: TvkuDevice); +begin + Create(aDevice.DeviceCommands); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuBufferFactory.Create(const aDeviceCommands: TVkDeviceCommands); +begin + inherited Create; + fDeviceCommands := aDeviceCommands; +end; + +end. + diff --git a/projects/utils/uvkuBufferView.pas b/projects/utils/uvkuBufferView.pas new file mode 100644 index 0000000..3c85465 --- /dev/null +++ b/projects/utils/uvkuBufferView.pas @@ -0,0 +1,82 @@ +unit uvkuBufferView; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuBase; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuBufferView = class(TvkuAllocHandle) + private + fHandle: VkBufferView; + fDeviceCommands: TVkDeviceCommands; + + procedure CreateHandle(const aCreateInfo: TVkBufferViewCreateInfo); + public + property Handle: VkBufferView read fHandle; + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + + constructor Create( + const aCreateInfo: TVkBufferViewCreateInfo; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + constructor Create( + const aHandle: VkBufferView; + const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + destructor Destroy; override; + end; + +implementation + +uses + uvkuUtils; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuBufferView///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuBufferView.CreateHandle(const aCreateInfo: TVkBufferViewCreateInfo); +var err: TVkResult; +begin + err := fDeviceCommands.vkCreateBufferView(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); + if (err < VK_SUCCESS) then + raise TvkuErrorException.Create('unable to create buffer view', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuBufferView.Create(const aCreateInfo: TVkBufferViewCreateInfo; const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fDeviceCommands := aDeviceCommands; + SetAllocCallbacks(aAllocCallbacks); + CreateHandle(aCreateInfo); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuBufferView.Create(const aHandle: VkBufferView; const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fHandle := aHandle; + fDeviceCommands := aDeviceCommands; + OwnsHandle := aOwnsHandle; + SetAllocCallbacks(aAllocCallbacks); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuBufferView.Destroy; +begin + if OwnsHandle and (fHandle <> VK_INVALID_NDP_HANDLE) then + fDeviceCommands.vkDestroyBufferView(fDeviceCommands.Device, fHandle, AllocCallbacks); + fHandle := VK_INVALID_NDP_HANDLE; + inherited Destroy; +end; + +end. + diff --git a/projects/utils/uvkuBufferViewFactory.pas b/projects/utils/uvkuBufferViewFactory.pas new file mode 100644 index 0000000..44ca264 --- /dev/null +++ b/projects/utils/uvkuBufferViewFactory.pas @@ -0,0 +1,107 @@ +unit uvkuBufferViewFactory; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuBufferView, uvkuAllocationHandler, uvkuDevice; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuBufferViewEx = class(TvkuBufferView) + private + fAllocHandler: TvkuAllocationHandler; + fOwnsHandler: Boolean; + public + destructor Destroy; override; + end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuBufferViewFactory = class(TObject) + private + fDeviceCommands: TVkDeviceCommands; + + fFlags: VkBufferViewCreateFlags; + fBuffer: VkBuffer; + fFormat: TVkFormat; + fOffset: VkDeviceSize; + fRange: VkDeviceSize; + public + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + + property Flags: VkBufferViewCreateFlags read fFlags write fFlags; + property Buffer: VkBuffer read fBuffer write fBuffer; + property Format: TVkFormat read fFormat write fFormat; + property Offset: VkDeviceSize read fOffset write fOffset; + property Range: VkDeviceSize read fRange write fRange; + + function CreateBufferView: TvkuBufferViewEx; + function CreateBufferView( + const aAllocHandler: TvkuAllocationHandler; + const aOwnsHandler: Boolean): TvkuBufferViewEx; + + constructor Create(const aDevice: TvkuDevice); + constructor Create(const aDeviceCommands: TVkDeviceCommands); + end; + +implementation + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuBufferViewEx/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuBufferViewEx.Destroy; +begin + inherited Destroy; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuBufferViewFactory////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuBufferViewFactory.CreateBufferView: TvkuBufferViewEx; +begin + result := CreateBufferView(nil, false); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuBufferViewFactory.CreateBufferView(const aAllocHandler: TvkuAllocationHandler; const aOwnsHandler: Boolean): TvkuBufferViewEx; +var + CreateInfo: TVkBufferViewCreateInfo; +begin + FillByte(CreateInfo, SizeOf(CreateInfo), 0); + CreateInfo.sType := VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO; + CreateInfo.pNext := nil; + CreateInfo.flags := fFlags; + CreateInfo.buffer := fBuffer; + CreateInfo.format := fFormat; + CreateInfo.offset := fOffset; + CreateInfo.range := fRange; + + if Assigned(aAllocHandler) + then result := TvkuBufferViewEx.Create(CreateInfo, fDeviceCommands, aAllocHandler.GetAllocationCallbacksPtr) + else result := TvkuBufferViewEx.Create(CreateInfo, fDeviceCommands); + try + TvkuBufferViewEx(result).fAllocHandler := aAllocHandler; + TvkuBufferViewEx(result).fOwnsHandler := aOwnsHandler; + except + FreeAndNil(result); + raise; + end; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuBufferViewFactory.Create(const aDevice: TvkuDevice); +begin + Create(aDevice.DeviceCommands); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuBufferViewFactory.Create(const aDeviceCommands: TVkDeviceCommands); +begin + inherited Create; + fDeviceCommands := aDeviceCommands; +end; + +end. + diff --git a/projects/utils/uvkuCommandBuffer.pas b/projects/utils/uvkuCommandBuffer.pas new file mode 100644 index 0000000..64aad9b --- /dev/null +++ b/projects/utils/uvkuCommandBuffer.pas @@ -0,0 +1,56 @@ +unit uvkuCommandBuffer; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuBase; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuCommandBuffer = class(TvkuHandle) + private + fHandle: VkCommandBuffer; + fCommandPool: VkCommandPool; + fDeviceCommands: TVkDeviceCommands; + public + property Handle: VkCommandBuffer read fHandle; + property CommandPool: VkCommandPool read fCommandPool; + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + + constructor Create( + const aHandle: VkCommandBuffer; + const aOwnsHandle: Boolean; + const aCommandPool: VkCommandPool; + const aDeviceCommands: TVkDeviceCommands); + destructor Destroy; override; + end; + +implementation + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuCommandBuffer////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuCommandBuffer.Create(const aHandle: VkCommandBuffer; const aOwnsHandle: Boolean; + const aCommandPool: VkCommandPool; const aDeviceCommands: TVkDeviceCommands); +begin + inherited Create; + fHandle := aHandle; + fCommandPool := aCommandPool; + fDeviceCommands := aDeviceCommands; + OwnsHandle := aOwnsHandle; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuCommandBuffer.Destroy; +begin + if OwnsHandle and (fHandle <> VK_INVALID_HANDLE) then + fDeviceCommands.vkFreeCommandBuffers(fDeviceCommands.Device, fCommandPool, 1, @fHandle); + fHandle := VK_INVALID_HANDLE; + inherited Destroy; +end; + +end. + diff --git a/projects/utils/uvkuCommandPool.pas b/projects/utils/uvkuCommandPool.pas new file mode 100644 index 0000000..0b5f251 --- /dev/null +++ b/projects/utils/uvkuCommandPool.pas @@ -0,0 +1,128 @@ +unit uvkuCommandPool; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuBase, uvkuTypes; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuCommandPool = class(TvkuAllocHandle) + private + fHandle: VkCommandPool; + fDeviceCommands: TVkDeviceCommands; + + procedure CreateHandle(const aCreateInfo: TVkCommandPoolCreateInfo); + public + property Handle: VkCommandPool read fHandle; + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + + function CreateCommandBuffer( + const aLevel: TVkCommandBufferLevel): VkCommandBuffer; + function CreateCommandBuffers( + const aLevel: TVkCommandBufferLevel; + const aCount: Integer): TvkuCommandBufferArr; + procedure FreeCommandBuffer( + const aBuffer: VkCommandBuffer); + procedure FreeCommandBuffers( + const aBuffers: TvkuCommandBufferArr); + + constructor Create( + const aCreateInfo: TVkCommandPoolCreateInfo; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + constructor Create( + const aHandle: VkCommandPool; + const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + destructor Destroy; override; + end; + +implementation + +uses + uvkuUtils; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuCommandPool//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuCommandPool.CreateHandle(const aCreateInfo: TVkCommandPoolCreateInfo); +var err: TVkResult; +begin + err := fDeviceCommands.vkCreateCommandPool(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); + if (err < VK_SUCCESS) then + raise TvkuErrorException.Create('unable to create command pool', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuCommandPool.CreateCommandBuffer(const aLevel: TVkCommandBufferLevel): VkCommandBuffer; +begin + result := CreateCommandBuffers(aLevel, 1)[0]; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuCommandPool.CreateCommandBuffers(const aLevel: TVkCommandBufferLevel; const aCount: Integer): TvkuCommandBufferArr; +var + AllocInfo: TVkCommandBufferAllocateInfo; + err: TVkResult; +begin + FillByte(AllocInfo, SizeOf(AllocInfo), 0); + AllocInfo.sType := VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + AllocInfo.pNext := nil; + AllocInfo.commandPool := fHandle; + AllocInfo.level := aLevel; + AllocInfo.commandBufferCount := aCount; + SetLength(result, aCount); + err := fDeviceCommands.vkAllocateCommandBuffers(fDeviceCommands.Device, @AllocInfo, @result[0]); + if (err < VK_SUCCESS) then + raise TvkuErrorException.Create('unable to create command buffers', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuCommandPool.FreeCommandBuffer(const aBuffer: VkCommandBuffer); +begin + FreeCommandBuffers(TvkuCommandBufferArr.Create(aBuffer)); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuCommandPool.FreeCommandBuffers(const aBuffers: TvkuCommandBufferArr); +begin + fDeviceCommands.vkFreeCommandBuffers(fDeviceCommands.Device, fHandle, Length(aBuffers), @aBuffers[0]); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuCommandPool.Create(const aCreateInfo: TVkCommandPoolCreateInfo; + const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fDeviceCommands := aDeviceCommands; + SetAllocCallbacks(aAllocCallbacks); + CreateHandle(aCreateInfo); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuCommandPool.Create(const aHandle: VkCommandPool; const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fHandle := aHandle; + fDeviceCommands := aDeviceCommands; + OwnsHandle := aOwnsHandle; + SetAllocCallbacks(aAllocCallbacks); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuCommandPool.Destroy; +begin + if OwnsHandle and (fHandle <> VK_INVALID_NDP_HANDLE) then + fDeviceCommands.vkDestroyCommandPool(fDeviceCommands.Device, fHandle, AllocCallbacks); + fHandle := VK_INVALID_NDP_HANDLE; + inherited Destroy; +end; + +end. + diff --git a/projects/utils/uvkuCommandPoolFactory.pas b/projects/utils/uvkuCommandPoolFactory.pas new file mode 100644 index 0000000..c6a144b --- /dev/null +++ b/projects/utils/uvkuCommandPoolFactory.pas @@ -0,0 +1,92 @@ +unit uvkuCommandPoolFactory; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuCommandPool, uvkuDevice, uvkuAllocationHandler; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuCommandPoolEx = class(TvkuCommandPool) + private + fAllocHandler: TvkuAllocationHandler; + fOwnsHandler: Boolean; + public + destructor Destroy; override; + end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuCommandPoolFactory = class(TObject) + private + fDeviceCommands: TVkDeviceCommands; + fFlags: VkCommandPoolCreateFlags; + fQueueFamilyIndex: VkUint32; + public + function CreateCommandPool: TvkuCommandPoolEx; + function CreateCommandPool( + const aAllocHandler: TvkuAllocationHandler; + const aOwnsHandler: Boolean): TvkuCommandPoolEx; + + constructor Create(const aDevice: TvkuDevice); + constructor Create(const aDeviceCommands: TVkDeviceCommands); + end; + +implementation + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuCommandPoolEx////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuCommandPoolEx.Destroy; +begin + if fOwnsHandler then + FreeAndNil(fAllocHandler); + inherited Destroy; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuCommandPoolFactory///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuCommandPoolFactory.CreateCommandPool: TvkuCommandPoolEx; +begin + result := CreateCommandPool(nil, false); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuCommandPoolFactory.CreateCommandPool(const aAllocHandler: TvkuAllocationHandler; const aOwnsHandler: Boolean): TvkuCommandPoolEx; +var CreateInfo: TVkCommandPoolCreateInfo; +begin + FillByte(CreateInfo, SizeOf(CreateInfo), 0); + CreateInfo.sType := VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + CreateInfo.pNext := nil; + CreateInfo.flags := fFlags; + CreateInfo.queueFamilyIndex := fQueueFamilyIndex; + if Assigned(aAllocHandler) + then result := TvkuCommandPoolEx.Create(CreateInfo, fDeviceCommands, aAllocHandler.GetAllocationCallbacksPtr) + else result := TvkuCommandPoolEx.Create(CreateInfo, fDeviceCommands); + try + TvkuCommandPoolEx(result).fAllocHandler := aAllocHandler; + TvkuCommandPoolEx(result).fOwnsHandler := aOwnsHandler; + except + FreeAndNil(result); + raise; + end; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuCommandPoolFactory.Create(const aDevice: TvkuDevice); +begin + Create(aDevice.DeviceCommands); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuCommandPoolFactory.Create(const aDeviceCommands: TVkDeviceCommands); +begin + inherited Create; + fDeviceCommands := aDeviceCommands; +end; + +end. + diff --git a/projects/utils/uvkuDevice.pas b/projects/utils/uvkuDevice.pas index 9f1fdc5..d3dcd23 100644 --- a/projects/utils/uvkuDevice.pas +++ b/projects/utils/uvkuDevice.pas @@ -6,35 +6,35 @@ interface uses Classes, SysUtils, - Vulkan; + Vulkan, uvkuBase; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TvkuDevice = class(TObject) + TvkuDevice = class(TvkuAllocHandle) private fHandle: VkDevice; - fPhysicalDevice: VkPhysicalDevice; - fAllocCallbacks: PVkAllocationCallbacks; fInstanceCommands: TVkInstanceCommands; fDeviceCommands: TVkDeviceCommands; procedure CreateHandle( - const aCreateInfo: PVkDeviceCreateInfo; - const aAllocCallbacks: PVkAllocationCallbacks); + const aPhyDevice: VkPhysicalDevice; + const aCreateInfo: PVkDeviceCreateInfo); public property Handle: VkDevice read fHandle; - property PhysicalDevice: VkPhysicalDevice read fPhysicalDevice; property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + function GetQueue(const aQueueFamilyIndex, aQueueIndex: VkUint32): VkQueue; + constructor Create( const aPhysicalDevice: VkPhysicalDevice; const aCreateInfo: TVkDeviceCreateInfo; - const aInstanceCommands: TVkInstanceCommands); + const aInstanceCommands: TVkInstanceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); constructor Create( - const aPhysicalDevice: VkPhysicalDevice; - const aCreateInfo: TVkDeviceCreateInfo; + const aHandle: VkDevice; + const aOwnsHandle: Boolean; const aInstanceCommands: TVkInstanceCommands; - const aAllocCallbacks: TVkAllocationCallbacks); + const aAllocCallbacks: PVkAllocationCallbacks = nil); destructor Destroy; override; end; @@ -46,16 +46,12 @@ uses ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuDevice///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TvkuDevice.CreateHandle(const aCreateInfo: PVkDeviceCreateInfo; const aAllocCallbacks: PVkAllocationCallbacks); +procedure TvkuDevice.CreateHandle(const aPhyDevice: VkPhysicalDevice; const aCreateInfo: PVkDeviceCreateInfo); var err: TVkResult; begin if not Assigned(fInstanceCommands.vkCreateDevice) then - raise TvkuException.Create('invalid function pointer: vkCreateDevice; did you load the vulkan core commands?'); - if Assigned(aAllocCallbacks) then begin - new(fAllocCallbacks); - fAllocCallbacks^ := aAllocCallbacks^; - end; - err := fInstanceCommands.vkCreateDevice(fPhysicalDevice, aCreateInfo, fAllocCallbacks, @fHandle); + raise TvkuInvalidFuncPtrException.Create('vkCreateDevice'); + err := fInstanceCommands.vkCreateDevice(aPhyDevice, aCreateInfo, AllocCallbacks, @fHandle); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to create device', err); fDeviceCommands := LoadDeviceCommands(fInstanceCommands.Instance, fHandle); @@ -63,39 +59,44 @@ begin raise TvkuException.Create('unable to load device commands'); end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuDevice.GetQueue(const aQueueFamilyIndex, aQueueIndex: VkUint32): VkQueue; +begin + if not Assigned(fDeviceCommands.vkGetDeviceQueue) then + raise TvkuInvalidFuncPtrException.Create('vkGetDeviceQueue'); + fDeviceCommands.vkGetDeviceQueue(fHandle, aQueueFamilyIndex, aQueueIndex, @result); + if (result = VK_INVALID_HANDLE) then + raise TvkuException.Create('unable to get device queue'); +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuDevice.Create(const aPhysicalDevice: VkPhysicalDevice; const aCreateInfo: TVkDeviceCreateInfo; - const aInstanceCommands: TVkInstanceCommands); + const aInstanceCommands: TVkInstanceCommands; const aAllocCallbacks: PVkAllocationCallbacks); begin inherited Create; fHandle := nil; - fPhysicalDevice := aPhysicalDevice; fInstanceCommands := aInstanceCommands; - CreateHandle(@aCreateInfo, nil); + SetAllocCallbacks(aAllocCallbacks); + CreateHandle(aPhysicalDevice, @aCreateInfo); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TvkuDevice.Create(const aPhysicalDevice: VkPhysicalDevice; const aCreateInfo: TVkDeviceCreateInfo; - const aInstanceCommands: TVkInstanceCommands; const aAllocCallbacks: TVkAllocationCallbacks); +constructor TvkuDevice.Create(const aHandle: VkDevice; const aOwnsHandle: Boolean; + const aInstanceCommands: TVkInstanceCommands; const aAllocCallbacks: PVkAllocationCallbacks); begin inherited Create; - fHandle := nil; - fPhysicalDevice := aPhysicalDevice; + fHandle := aHandle; fInstanceCommands := aInstanceCommands; - CreateHandle(@aCreateInfo, @aAllocCallbacks); + OwnsHandle := aOwnsHandle; + SetAllocCallbacks(aAllocCallbacks); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TvkuDevice.Destroy; begin - if (fHandle <> VK_INVALID_HANDLE) then begin - fDeviceCommands.vkDestroyDevice(fHandle, fAllocCallbacks); - fHandle := VK_INVALID_HANDLE; - end; - if Assigned(fAllocCallbacks) then begin - Dispose(fAllocCallbacks); - fAllocCallbacks := nil; - end; + if OwnsHandle and (fHandle <> VK_INVALID_HANDLE) then + fDeviceCommands.vkDestroyDevice(fHandle, AllocCallbacks); + fHandle := VK_INVALID_HANDLE; FreeAndNil(fDeviceCommands); inherited Destroy; end; diff --git a/projects/utils/uvkuDeviceFactory.pas b/projects/utils/uvkuDeviceFactory.pas index 81af413..e1451de 100644 --- a/projects/utils/uvkuDeviceFactory.pas +++ b/projects/utils/uvkuDeviceFactory.pas @@ -6,18 +6,9 @@ interface uses Classes, SysUtils, - Vulkan, uvkuInstance, uvkuDevice, uvkuAllocationHandler; + Vulkan, uvkuInstance, uvkuDevice, uvkuAllocationHandler, uvkuTypes; type -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TvkuQueuePriorityArr = array of VkFloat; - TvkuQueueCreateInfo = packed record - Flags: VkDeviceQueueCreateFlags; - FamilyIndex: VkUint32; - Priorities: TvkuQueuePriorityArr; - end; - TvkuQueueCreateInfoArr = array of TvkuQueueCreateInfo; - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TvkuDeviceEx = class(TvkuDevice) private @@ -58,11 +49,11 @@ type property QueueCreateInfo[const aIndex: Integer]: TvkuQueueCreateInfo read GetQueueCreateInfo write SetQueueCreateInfo; function CreateDevice( - const aPhysicalDevice: VkPhysicalDevice): TvkuDevice; + const aPhysicalDevice: VkPhysicalDevice): TvkuDeviceEx; function CreateDevice( const aPhysicalDevice: VkPhysicalDevice; const aAllocHandler: TvkuAllocationHandler; - const aOwnsHandler: Boolean): TvkuDevice; + const aOwnsHandler: Boolean): TvkuDeviceEx; constructor Create(const aInstance: TvkuInstance); constructor Create(const aInstanceCommands: TVkInstanceCommands); @@ -141,14 +132,14 @@ begin end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuDeviceFactory.CreateDevice(const aPhysicalDevice: VkPhysicalDevice): TvkuDevice; +function TvkuDeviceFactory.CreateDevice(const aPhysicalDevice: VkPhysicalDevice): TvkuDeviceEx; begin result := CreateDevice(aPhysicalDevice, nil, false); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuDeviceFactory.CreateDevice(const aPhysicalDevice: VkPhysicalDevice; - const aAllocHandler: TvkuAllocationHandler; const aOwnsHandler: Boolean): TvkuDevice; + const aAllocHandler: TvkuAllocationHandler; const aOwnsHandler: Boolean): TvkuDeviceEx; var CreateInfo: TVkDeviceCreateInfo; QueueInfos: array of TVkDeviceQueueCreateInfo; @@ -193,7 +184,7 @@ begin CreateInfo.pEnabledFeatures := @fFeatures; if Assigned(aAllocHandler) - then result := TvkuDeviceEx.Create(aPhysicalDevice, CreateInfo, fInstanceCommands, aAllocHandler.GetAllocationCallbacks) + then result := TvkuDeviceEx.Create(aPhysicalDevice, CreateInfo, fInstanceCommands, aAllocHandler.GetAllocationCallbacksPtr) else result := TvkuDeviceEx.Create(aPhysicalDevice, CreateInfo, fInstanceCommands); try TvkuDeviceEx(result).fAllocHandler := aAllocHandler; diff --git a/projects/utils/uvkuDeviceMemory.pas b/projects/utils/uvkuDeviceMemory.pas new file mode 100644 index 0000000..7cc6ed3 --- /dev/null +++ b/projects/utils/uvkuDeviceMemory.pas @@ -0,0 +1,100 @@ +unit uvkuDeviceMemory; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuBase; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuDeviceMemory = class(TvkuAllocHandle) + private + fHandle: VkDeviceMemory; + fDeviceCommands: TVkDeviceCommands; + + procedure CreateHandle(const aAllocInfo: TVkMemoryAllocateInfo); + public + property Handle: VkDeviceMemory read fHandle; + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + + function Map(const aOffset: VkDeviceSize; aSize: VkDeviceSize; aFlags: VkMemoryMapFlags): PVkVoid; + procedure Unmap; + + constructor Create(const aAllocInfo: TVkMemoryAllocateInfo; const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks); + constructor Create( + const aHandle: VkDeviceMemory; + const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + destructor Destroy; override; + end; + +implementation + +uses + uvkuUtils; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuDeviceMemory/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuDeviceMemory.CreateHandle(const aAllocInfo: TVkMemoryAllocateInfo); +var err: TVkResult; +begin + if not Assigned(fDeviceCommands.vkAllocateMemory) then + raise TvkuInvalidFuncPtrException.Create('vkAllocateMemory'); + err := fDeviceCommands.vkAllocateMemory(fDeviceCommands.Device, @aAllocInfo, AllocCallbacks, @fHandle); + if (err < VK_SUCCESS) then + raise TvkuErrorException.Create('unable to allocate device memory', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuDeviceMemory.Map(const aOffset: VkDeviceSize; aSize: VkDeviceSize; aFlags: VkMemoryMapFlags): PVkVoid; +var err: TVkResult; +begin + err := fDeviceCommands.vkMapMemory(fDeviceCommands.Device, fHandle, aOffset, aSize, aFlags, @result); + if (err < VK_SUCCESS) then + raise TvkuErrorException.Create('unable to map device memory', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuDeviceMemory.Unmap; +begin + fDeviceCommands.vkUnmapMemory(fDeviceCommands.Device, fHandle); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuDeviceMemory.Create(const aAllocInfo: TVkMemoryAllocateInfo; const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fDeviceCommands := aDeviceCommands; + SetAllocCallbacks(aAllocCallbacks); + CreateHandle(aAllocInfo); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuDeviceMemory.Create(const aHandle: VkDeviceMemory; const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fHandle := aHandle; + fDeviceCommands := aDeviceCommands; + OwnsHandle := aOwnsHandle; + SetAllocCallbacks(aAllocCallbacks); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuDeviceMemory.Destroy; +begin + if OwnsHandle and (fHandle <> VK_INVALID_NDP_HANDLE) then + fDeviceCommands.vkFreeMemory(fDeviceCommands.Device, fHandle, AllocCallbacks); + fHandle := VK_INVALID_NDP_HANDLE; + inherited Destroy; +end; + +end. + diff --git a/projects/utils/uvkuImage.pas b/projects/utils/uvkuImage.pas new file mode 100644 index 0000000..eca9d36 --- /dev/null +++ b/projects/utils/uvkuImage.pas @@ -0,0 +1,177 @@ +unit uvkuImage; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuBase; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuImage = class(TvkuAllocHandle) + private + fHandle: VkImage; + fDeviceCommands: TVkDeviceCommands; + + procedure CreateHandle(const aCreateInfo: TVkImageCreateInfo); + public + property Handle: VkImage read fHandle; + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + + function GetMemoryBarrier( + const aAspectMask: VkImageAspectFlags; + const aOldLayout: TVkImageLayout; + const aNewLayout: TVkImageLayout): TVkImageMemoryBarrier; + + constructor Create( + const aCreateInfo: TVkImageCreateInfo; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + constructor Create( + const aHandle: VkImage; + const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + destructor Destroy; override; + end; + +implementation + +uses + uvkuUtils; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuImage////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuImage.CreateHandle(const aCreateInfo: TVkImageCreateInfo); +var err: TVkResult; +begin + err := fDeviceCommands.vkCreateImage(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); + if (err < VK_SUCCESS) then + TvkuErrorException.Create('unable to create image', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuImage.GetMemoryBarrier( + const aAspectMask: VkImageAspectFlags; + const aOldLayout: TVkImageLayout; + const aNewLayout: TVkImageLayout): TVkImageMemoryBarrier; +var + range: TVkImageSubresourceRange; +begin + FillByte(range, SizeOf(range), 0); + range.aspectMask := aAspectMask; + range.baseMipLevel := 0; + range.levelCount := 1; + range.baseArrayLayer := 0; + range.layerCount := 1; + + FillByte(result, SizeOf(result), 0); + result.sType := VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER; + result.pNext := nil; + result.srcAccessMask := []; + result.dstAccessMask := []; + result.oldLayout := aOldLayout; + result.newLayout := aNewLayout; + result.srcQueueFamilyIndex := 0; + result.dstQueueFamilyIndex := 0; + result.image := fHandle; + result.subresourceRange := range; + + case aOldLayout of + // Undefined layout: + // Note: Only allowed as initial layout! + // Note: Make sure any writes to the image have been finished + VK_IMAGE_LAYOUT_UNDEFINED: begin + result.srcAccessMask := [ VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT ]; + end; + + // Old layout is color attachment: + // Note: Make sure any writes to the color buffer have been finished + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: begin + result.srcAccessMask := [ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ]; + end; + + // Old layout is transfer source: + // Note: Make sure any reads from the image have been finished + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: begin + result.srcAccessMask := [ VK_ACCESS_TRANSFER_READ_BIT ]; + end; + + // Old layout is shader read (sampler, input attachment): + // Note: Make sure any shader reads from the image have been finished + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: begin + result.srcAccessMask := [ VK_ACCESS_SHADER_READ_BIT ]; + end; + end; + + case aNewLayout of + // New layout is transfer destination (copy, blit): + // Note: Make sure any copyies to the image have been finished + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: begin + result.dstAccessMask := [ VK_ACCESS_TRANSFER_WRITE_BIT ]; + end; + + // New layout is transfer source (copy, blit): + // Note: Make sure any reads from and writes to the image have been finished + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: begin + result.srcAccessMask := result.srcAccessMask + [ VK_ACCESS_TRANSFER_READ_BIT ]; + result.dstAccessMask := [ VK_ACCESS_TRANSFER_READ_BIT ]; + end; + + // New layout is color attachment: + // Note: Make sure any writes to the color buffer hav been finished + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: begin + result.dstAccessMask := [ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ]; + result.srcAccessMask := [ VK_ACCESS_TRANSFER_READ_BIT ]; + end; + + // New layout is depth attachment: + // Note: Make sure any writes to depth/stencil buffer have been finished + VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: begin + result.dstAccessMask := result.dstAccessMask + [ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT ]; + end; + + // New layout is shader read (sampler, input attachment): + // Note: Make sure any writes to the image have been finished + VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: begin + result.srcAccessMask := [ VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT ]; + result.dstAccessMask := [ VK_ACCESS_SHADER_READ_BIT ]; + end; + end; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuImage.Create(const aCreateInfo: TVkImageCreateInfo; const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fDeviceCommands := aDeviceCommands; + SetAllocCallbacks(aAllocCallbacks); + CreateHandle(aCreateInfo); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuImage.Create(const aHandle: VkImage; const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fHandle := aHandle; + fDeviceCommands := aDeviceCommands; + OwnsHandle := aOwnsHandle; + SetAllocCallbacks(aAllocCallbacks); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuImage.Destroy; +begin + if OwnsHandle and (fHandle <> VK_INVALID_NDP_HANDLE) then + fDeviceCommands.vkDestroyImage(fDeviceCommands.Device, fHandle, AllocCallbacks); + fHandle := VK_INVALID_NDP_HANDLE; + inherited Destroy; +end; + +end. + diff --git a/projects/utils/uvkuImageFactory.pas b/projects/utils/uvkuImageFactory.pas new file mode 100644 index 0000000..2c03673 --- /dev/null +++ b/projects/utils/uvkuImageFactory.pas @@ -0,0 +1,161 @@ +unit uvkuImageFactory; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuImage, uvkuDevice, uvkuAllocationHandler, uvkuTypes; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuImageEx = class(TvkuImage) + private + fAllocHandler: TvkuAllocationHandler; + fOwnsHandle: Boolean; + public + destructor Destroy; override; + end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuImageFactory = class(TObject) + private + fDeviceCommands: TVkDeviceCommands; + fFlags: VkImageCreateFlags; + fImageType: TVkImageType; + fFormat: TVkFormat; + fExtent: TVkExtent3D; + fMipLevels: VkUint32; + fArrayLayers: VkUint32; + fSamples: TVkSampleCountFlagBits; + fTiling: TVkImageTiling; + fUsage: VkImageUsageFlags; + fSharingMode: TVkSharingMode; + fQueueFamilyIndices: TvkuUint32Arr; + fInitialLayout: TVkImageLayout; + + function GetQueueFamilyIndex(const aIndex: Integer): VkUint32; + function GetQueueFamilyIndexCount: Integer; + procedure SetQueueFamilyIndex(const aIndex: Integer; aValue: VkUint32); + public + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + property Flags: VkImageCreateFlags read fFlags write fFlags; + property ImageType: TVkImageType read fImageType write fImageType; + property Format: TVkFormat read fFormat write fFormat; + property Extent: TVkExtent3D read fExtent write fExtent; + property MipLevels: VkUint32 read fMipLevels write fMipLevels; + property ArrayLayers: VkUint32 read fArrayLayers write fArrayLayers; + property Samples: TVkSampleCountFlagBits read fSamples write fSamples; + property Tiling: TVkImageTiling read fTiling write fTiling; + property Usage: VkImageUsageFlags read fUsage write fUsage; + property SharingMode: TVkSharingMode read fSharingMode write fSharingMode; + property InitialLayout: TVkImageLayout read fInitialLayout write fInitialLayout; + + property QueueFamilyIndices: TvkuUint32Arr read fQueueFamilyIndices; + property QueueFamilyIndexCount: Integer read GetQueueFamilyIndexCount; + property QueueFamilyIndex[const aIndex: Integer]: VkUint32 read GetQueueFamilyIndex write SetQueueFamilyIndex; + + function CreateImage: TvkuImageEx; + function CreateImage( + const aAllocHandler: TvkuAllocationHandler; + const aOwnsHandler: Boolean): TvkuImageEx; + + constructor Create(const aDevice: TvkuDevice); + constructor Create(const aDeviceCommands: TVkDeviceCommands); + end; + +implementation + +uses + uvkuUtils; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuImageEx//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuImageEx.Destroy; +begin + if fOwnsHandle then + FreeAndNil(fAllocHandler); + inherited Destroy; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuImageFactory/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuImageFactory.GetQueueFamilyIndex(const aIndex: Integer): VkUint32; +begin + if (aIndex < low(fQueueFamilyIndices)) or (aIndex > high(fQueueFamilyIndices)) then + raise TvkuException.CreateFmt('index (%d) out of range (%d : %d)', [aIndex, Low(fQueueFamilyIndices), High(fQueueFamilyIndices)]); + result := fQueueFamilyIndices[aIndex]; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuImageFactory.GetQueueFamilyIndexCount: Integer; +begin + result := Length(fQueueFamilyIndices); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuImageFactory.SetQueueFamilyIndex(const aIndex: Integer; aValue: VkUint32); +begin + if (aIndex < low(fQueueFamilyIndices)) or (aIndex > high(fQueueFamilyIndices)) then + raise TvkuException.CreateFmt('index (%d) out of range (%d : %d)', [aIndex, Low(fQueueFamilyIndices), High(fQueueFamilyIndices)]); + fQueueFamilyIndices[aIndex] := aValue; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuImageFactory.CreateImage: TvkuImageEx; +begin + result := CreateImage(nil, false); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuImageFactory.CreateImage(const aAllocHandler: TvkuAllocationHandler; const aOwnsHandler: Boolean): TvkuImageEx; +var + CreateInfo: TVkImageCreateInfo; +begin + FillByte(CreateInfo, 0, SizeOf(CreateInfo)); + CreateInfo.sType := VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO; + CreateInfo.pNext := nil; + CreateInfo.flags := fFlags; + CreateInfo.imageType := fImageType; + CreateInfo.format := fFormat; + CreateInfo.extent := fExtent; + CreateInfo.mipLevels := fMipLevels; + CreateInfo.arrayLayers := fArrayLayers; + CreateInfo.samples := fSamples; + CreateInfo.tiling := fTiling; + CreateInfo.usage := fUsage; + CreateInfo.sharingMode := fSharingMode; + CreateInfo.queueFamilyIndexCount := Length(fQueueFamilyIndices); + CreateInfo.pQueueFamilyIndices := @fQueueFamilyIndices[0]; + CreateInfo.initialLayout := fInitialLayout; + + if Assigned(aAllocHandler) + then result := TvkuImageEx.Create(CreateInfo, fDeviceCommands, aAllocHandler.GetAllocationCallbacksPtr) + else result := TvkuImageEx.Create(CreateInfo, fDeviceCommands); + try + TvkuImageEx(result).fAllocHandler := aAllocHandler; + TvkuImageEx(result).fOwnsHandle := aOwnsHandler; + except + FreeAndNil(result); + raise; + end; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuImageFactory.Create(const aDevice: TvkuDevice); +begin + Create(aDevice.DeviceCommands); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuImageFactory.Create(const aDeviceCommands: TVkDeviceCommands); +begin + inherited Create; + fDeviceCommands := aDeviceCommands; +end; + +end. + diff --git a/projects/utils/uvkuImageView.pas b/projects/utils/uvkuImageView.pas new file mode 100644 index 0000000..e4ec45a --- /dev/null +++ b/projects/utils/uvkuImageView.pas @@ -0,0 +1,84 @@ +unit uvkuImageView; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuBase; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuImageView = class(TvkuAllocHandle) + private + fHandle: VkImageView; + fDeviceCommands: TVkDeviceCommands; + + procedure CreateHandle(const aCreateInfo: TVkImageViewCreateInfo); + public + property Handle: VkImageView read fHandle; + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + + constructor Create( + const aCreateInfo: TVkImageViewCreateInfo; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + constructor Create( + const aHandle: VkImageView; + const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + destructor Destroy; override; + end; + +implementation + +uses + uvkuUtils; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuImageView////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuImageView.CreateHandle(const aCreateInfo: TVkImageViewCreateInfo); +var err: TVkResult; +begin + if not Assigned(fDeviceCommands.vkCreateImageView) then + raise TvkuInvalidFuncPtrException.Create('vkCreateImageView'); + err := fDeviceCommands.vkCreateImageView(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); + if (err < VK_SUCCESS) then + raise TvkuErrorException.Create('unable to create image view', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuImageView.Create(const aCreateInfo: TVkImageViewCreateInfo; const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fDeviceCommands := aDeviceCommands; + SetAllocCallbacks(aAllocCallbacks); + CreateHandle(aCreateInfo); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuImageView.Create(const aHandle: VkImageView; const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fHandle := aHandle; + fDeviceCommands := aDeviceCommands; + OwnsHandle := aOwnsHandle; + SetAllocCallbacks(aAllocCallbacks); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuImageView.Destroy; +begin + if OwnsHandle and (fHandle <> VK_INVALID_NDP_HANDLE) then + fDeviceCommands.vkDestroyImageView(fDeviceCommands.Device, fHandle, AllocCallbacks); + fHandle := VK_INVALID_NDP_HANDLE; + inherited Destroy; +end; + +end. + diff --git a/projects/utils/uvkuImageViewFactory.pas b/projects/utils/uvkuImageViewFactory.pas new file mode 100644 index 0000000..e59b285 --- /dev/null +++ b/projects/utils/uvkuImageViewFactory.pas @@ -0,0 +1,110 @@ +unit uvkuImageViewFactory; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuAllocationHandler, uvkuImageView, uvkuDevice; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuImageViewEx = class(TvkuImageView) + private + fAllocHandler: TvkuAllocationHandler; + fOwnsHandler: Boolean; + public + destructor Destroy; override; + end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuImageViewFactory = class(TObject) + private + fDeviceCommands: TVkDeviceCommands; + + fFlags: VkImageViewCreateFlags; + fImage: VkImage; + fViewType: TVkImageViewType; + fFormat: TVkFormat; + fComponents: TVkComponentMapping; + fSubresourceRange: TVkImageSubresourceRange; + public + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + + property Flags: VkImageViewCreateFlags read fFlags write fFlags; + property Image: VkImage read fImage write fImage; + property ViewType: TVkImageViewType read fViewType write fViewType; + property Format: TVkFormat read fFormat write fFormat; + property Components: TVkComponentMapping read fComponents write fComponents; + property SubresourceRange: TVkImageSubresourceRange read fSubresourceRange write fSubresourceRange; + + function CreateImageView: TvkuImageViewEx; + function CreateImageView( + const aAllocHandler: TvkuAllocationHandler; + const aOwnsHandler: Boolean): TvkuImageViewEx; + + constructor Create(const aDevice: TvkuDevice); + constructor Create(const aDeviceCommands: TVkDeviceCommands); + end; + +implementation + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuImageViewEx//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuImageViewEx.Destroy; +begin + inherited Destroy; + if fOwnsHandler then + FreeAndNil(fAllocHandler); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuImageViewFactory/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuImageViewFactory.CreateImageView: TvkuImageViewEx; +begin + result := CreateImageView(nil, false); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuImageViewFactory.CreateImageView(const aAllocHandler: TvkuAllocationHandler; const aOwnsHandler: Boolean): TvkuImageViewEx; +var CreateInfo: TVkImageViewCreateInfo; +begin + FillByte(CreateInfo, SizeOf(CreateInfo), 0); + CreateInfo.sType := VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + CreateInfo.pNext := nil; + CreateInfo.flags := fFlags; + CreateInfo.image := fImage; + CreateInfo.viewType := fViewType; + CreateInfo.format := fFormat; + CreateInfo.components := fComponents; + CreateInfo.subresourceRange := fSubresourceRange; + if Assigned(aAllocHandler) + then result := TvkuImageViewEx.Create(CreateInfo, fDeviceCommands, aAllocHandler.GetAllocationCallbacksPtr) + else result := TvkuImageViewEx.Create(CreateInfo, fDeviceCommands); + try + TvkuImageViewEx(result).fAllocHandler := aAllocHandler; + TvkuImageViewEx(result).fOwnsHandler := aOwnsHandler; + except + FreeAndNil(result); + raise; + end; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuImageViewFactory.Create(const aDevice: TvkuDevice); +begin + Create(aDevice.DeviceCommands); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuImageViewFactory.Create(const aDeviceCommands: TVkDeviceCommands); +begin + inherited Create; + fDeviceCommands := aDeviceCommands; +end; + +end. + diff --git a/projects/utils/uvkuInstance.pas b/projects/utils/uvkuInstance.pas index 9424ccb..8789f2a 100644 --- a/projects/utils/uvkuInstance.pas +++ b/projects/utils/uvkuInstance.pas @@ -6,35 +6,32 @@ interface uses Classes, SysUtils, - Vulkan; + Vulkan, uvkuBase, uvkuTypes; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TvkuPhysicalDeviceArr = array of VkPhysicalDevice; - TvkuInstance = class(TObject) + TvkuInstance = class(TvkuAllocHandle) private fHandle: VkInstance; - fAllocCallbacks: PVkAllocationCallbacks; fPhysicalDevices: TvkuPhysicalDeviceArr; fInstanceCommands: TVkInstanceCommands; procedure UpdatePhysicalDevices; protected - procedure CreateHandle(const aCreateInfo: PVkInstanceCreateInfo; const aAllocCallbacks: PVkAllocationCallbacks); - {%H-}constructor Create; + procedure CreateHandle(const aCreateInfo: PVkInstanceCreateInfo); public property Handle: VkInstance read fHandle; property InstanceCommands: TVkInstanceCommands read fInstanceCommands; function GetPhysicalDevices: TvkuPhysicalDeviceArr; - constructor Create( - const aCreateInfo: TVkInstanceCreateInfo); - constructor Create( const aCreateInfo: TVkInstanceCreateInfo; - const aAllocCallbacks: TVkAllocationCallbacks); - + const aAllocCallbacks: PVkAllocationCallbacks = nil); + constructor Create( + const aHandle: VkInstance; + const aOwnsHandle: Boolean; + const aAllocCallbacks: PVkAllocationCallbacks = nil); destructor Destroy; override; end; @@ -65,14 +62,10 @@ begin end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TvkuInstance.CreateHandle(const aCreateInfo: PVkInstanceCreateInfo; const aAllocCallbacks: PVkAllocationCallbacks); +procedure TvkuInstance.CreateHandle(const aCreateInfo: PVkInstanceCreateInfo); var e: TVkResult; begin - if Assigned(aAllocCallbacks) then begin - new(fAllocCallbacks); - fAllocCallbacks^ := aAllocCallbacks^; - end; - e := vkCreateInstance(aCreateInfo, fAllocCallbacks, @fHandle); + e := vkCreateInstance(aCreateInfo, AllocCallbacks, @fHandle); if (e < VK_SUCCESS) then raise TvkuErrorException.Create('unable to create vulkan instance', e); fInstanceCommands := LoadInstanceCommands(fHandle); @@ -80,14 +73,6 @@ begin raise TvkuException.Create('unable to load instance commands'); end; -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TvkuInstance.Create; -begin - inherited Create; - fHandle := nil; - fAllocCallbacks := nil; -end; - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuInstance.GetPhysicalDevices: TvkuPhysicalDeviceArr; begin @@ -96,30 +81,29 @@ begin end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TvkuInstance.Create(const aCreateInfo: TVkInstanceCreateInfo); +constructor TvkuInstance.Create(const aCreateInfo: TVkInstanceCreateInfo; const aAllocCallbacks: PVkAllocationCallbacks); begin - Create; - CreateHandle(@aCreateInfo, nil); + inherited Create; + fHandle := VK_INVALID_HANDLE; + SetAllocCallbacks(aAllocCallbacks); + CreateHandle(@aCreateInfo); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TvkuInstance.Create(const aCreateInfo: TVkInstanceCreateInfo; const aAllocCallbacks: TVkAllocationCallbacks); +constructor TvkuInstance.Create(const aHandle: VkInstance; const aOwnsHandle: Boolean; const aAllocCallbacks: PVkAllocationCallbacks); begin - Create; - CreateHandle(@aCreateInfo, @aAllocCallbacks); + inherited Create; + fHandle := aHandle; + OwnsHandle := aOwnsHandle; + SetAllocCallbacks(aAllocCallbacks); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TvkuInstance.Destroy; begin - if (fHandle <> VK_INVALID_HANDLE) then begin - InstanceCommands.vkDestroyInstance(fHandle, fAllocCallbacks); - fHandle := VK_INVALID_HANDLE; - end; - if Assigned(fAllocCallbacks) then begin - Dispose(fAllocCallbacks); - fAllocCallbacks := nil; - end; + if OwnsHandle and (fHandle <> VK_INVALID_HANDLE) then + InstanceCommands.vkDestroyInstance(fHandle, AllocCallbacks); + fHandle := VK_INVALID_HANDLE; FreeAndNil(fInstanceCommands); inherited Destroy; end; diff --git a/projects/utils/uvkuInstanceFactory.pas b/projects/utils/uvkuInstanceFactory.pas index 6b6d666..a8e94f5 100644 --- a/projects/utils/uvkuInstanceFactory.pas +++ b/projects/utils/uvkuInstanceFactory.pas @@ -7,18 +7,9 @@ interface uses Classes, SysUtils, - Vulkan, uvkuInstance, uvkuAllocationHandler; + Vulkan, uvkuInstance, uvkuAllocationHandler, uvkuTypes; type -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TvkuApplicationInfo = packed record - AppName: String; - AppVersion: VkVersion; - EngineName: String; - EngineVersion: VkVersion; - ApiVersion: VkVersion; - end; - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TvkuInstanceEx = class(TvkuInstance) private @@ -45,10 +36,10 @@ type property Layers: TStrings read GetLayers; property Extensions: TStrings read GetExtensions; - function CreateInstance: TvkuInstance; + function CreateInstance: TvkuInstanceEx; function CreateInstance( const aAllocHandler: TvkuAllocationHandler; - const aOwnsHandler: Boolean): TvkuInstance; + const aOwnsHandler: Boolean): TvkuInstanceEx; constructor Create; destructor Destroy; override; @@ -110,13 +101,13 @@ begin end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuInstanceFactory.CreateInstance: TvkuInstance; +function TvkuInstanceFactory.CreateInstance: TvkuInstanceEx; begin result := CreateInstance(nil, false); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuInstanceFactory.CreateInstance(const aAllocHandler: TvkuAllocationHandler; const aOwnsHandler: Boolean): TvkuInstance; +function TvkuInstanceFactory.CreateInstance(const aAllocHandler: TvkuAllocationHandler; const aOwnsHandler: Boolean): TvkuInstanceEx; var CreateInfo: TVkInstanceCreateInfo; AppInfo: TVkApplicationInfo; @@ -152,7 +143,7 @@ begin CreateInfo.ppEnabledExtensionNames := @ext[0]; if Assigned(aAllocHandler) - then result := TvkuInstanceEx.Create(CreateInfo, aAllocHandler.GetAllocationCallbacks) + then result := TvkuInstanceEx.Create(CreateInfo, aAllocHandler.GetAllocationCallbacksPtr) else result := TvkuInstanceEx.Create(CreateInfo); try TvkuInstanceEx(result).fAllocHandler := aAllocHandler; diff --git a/projects/utils/uvkuPhysicalDevice.pas b/projects/utils/uvkuPhysicalDevice.pas index bf2764e..37f4a3b 100644 --- a/projects/utils/uvkuPhysicalDevice.pas +++ b/projects/utils/uvkuPhysicalDevice.pas @@ -6,20 +6,11 @@ interface uses Classes, SysUtils, - Vulkan, uvkuInstance; + Vulkan, uvkuBase, uvkuTypes; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TvkuQueueFamilyPropertiesArr = array of TVkQueueFamilyProperties; - TvkuSparseImageFormatPropertiesArr = array of TVkSparseImageFormatProperties; - TvkuSurfaceFormatArr = array of TVkSurfaceFormatKHR; - TvkuPresentModeArr = array of TVkPresentModeKHR; - TvkuDisplayPropertiesArr = array of TVkDisplayPropertiesKHR; - TvkuDisplayPlanePropertiesArr = array of TVkDisplayPlanePropertiesKHR; - TvkuDisplayArr = array of VkDisplayKHR; - TvkuDisplayModePropertiesArr = array of TVkDisplayModePropertiesKHR; - - TvkuPhysicalDevice = class(TObject) + TvkuPhysicalDevice = class(TvkuObject) private fHandle: VkPhysicalDevice; fInstanceCommands: TVkInstanceCommands; @@ -59,7 +50,9 @@ type property Handle: VkPhysicalDevice read fHandle; property InstanceCommands: TVkInstanceCommands read fInstanceCommands; - constructor Create(const aHandle: VkPhysicalDevice; const aInstanceCommands: TVkInstanceCommands); + constructor Create( + const aHandle: VkPhysicalDevice; + const aInstanceCommands: TVkInstanceCommands); end; implementation @@ -73,7 +66,7 @@ uses function TvkuPhysicalDevice.GetFeatures: TVkPhysicalDeviceFeatures; begin if not Assigned(fInstanceCommands.vkGetPhysicalDeviceFeatures) then - raise TvkuException.Create('invalid function pointer: vkGetPhysicalDeviceFeatures; did you load the vulkan core commands?'); + raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceFeatures'); fInstanceCommands.vkGetPhysicalDeviceFeatures(fHandle, @result); end; @@ -81,7 +74,7 @@ end; function TvkuPhysicalDevice.GetProperties: TVkPhysicalDeviceProperties; begin if not Assigned(fInstanceCommands.vkGetPhysicalDeviceProperties) then - raise TvkuException.Create('invalid function pointer: vkGetPhysicalDeviceProperties; did you load the vulkan core commands?'); + raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceProperties'); fInstanceCommands.vkGetPhysicalDeviceProperties(fHandle, @result); end; @@ -89,7 +82,7 @@ end; function TvkuPhysicalDevice.GetMemoryProperties: TVkPhysicalDeviceMemoryProperties; begin if not Assigned(fInstanceCommands.vkGetPhysicalDeviceMemoryProperties) then - raise TvkuException.Create('invalid function pointer: vkGetPhysicalDeviceMemoryProperties; did you load the vulkan core commands?'); + raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceMemoryProperties'); fInstanceCommands.vkGetPhysicalDeviceMemoryProperties(fHandle, @result); end; @@ -99,7 +92,7 @@ var c: VkUint32; begin result := nil; if not Assigned(fInstanceCommands.vkGetPhysicalDeviceQueueFamilyProperties) then - raise TvkuException.Create('invalid function pointer: vkGetPhysicalDeviceQueueFamilyProperties; did you load the vulkan core commands?'); + raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceQueueFamilyProperties'); fInstanceCommands.vkGetPhysicalDeviceQueueFamilyProperties(fHandle, @c, nil); SetLength(result, c); fInstanceCommands.vkGetPhysicalDeviceQueueFamilyProperties(fHandle, @c, @result[0]); @@ -109,7 +102,7 @@ end; function TvkuPhysicalDevice.GetFormatProperties(const aFormat: TVkFormat): TVkFormatProperties; begin if not Assigned(fInstanceCommands.vkGetPhysicalDeviceFormatProperties) then - raise TvkuException.Create('invalid function pointer: vkGetPhysicalDeviceFormatProperties; did you load the vulkan core commands?'); + raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceFormatProperties'); fInstanceCommands.vkGetPhysicalDeviceFormatProperties(fHandle, aFormat, @result); end; @@ -119,7 +112,7 @@ function TvkuPhysicalDevice.GetImageFormatProperties(const aFormat: TVkFormat; c var err: TVkResult; begin if not Assigned(fInstanceCommands.vkGetPhysicalDeviceImageFormatProperties) then - raise TvkuException.Create('invalid function pointer: vkGetPhysicalDeviceImageFormatProperties; did you load the vulkan core commands?'); + raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceImageFormatProperties'); err := fInstanceCommands.vkGetPhysicalDeviceImageFormatProperties(fHandle, aFormat, aImageType, aTiling, aUsage, aFlags, @result); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device image format properties', err); @@ -132,7 +125,7 @@ var c: VkUint32; begin result := nil; if not Assigned(fInstanceCommands.vkGetPhysicalDeviceSparseImageFormatProperties) then - raise TvkuException.Create('invalid function pointer: vkGetPhysicalDeviceSparseImageFormatProperties; did you load the vulkan core commands?'); + raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceSparseImageFormatProperties'); fInstanceCommands.vkGetPhysicalDeviceSparseImageFormatProperties(fHandle, aFormat, aImageType, aSamples, aUsage, aTiling, @c, nil); SetLength(result, c); fInstanceCommands.vkGetPhysicalDeviceSparseImageFormatProperties(fHandle, aFormat, aImageType, aSamples, aUsage, aTiling, @c, @result[0]); @@ -145,7 +138,7 @@ var err: TVkResult; begin if not Assigned(fInstanceCommands.vkGetPhysicalDeviceSurfaceSupportKHR) then - raise TvkuException.Create('invalid function pointer: vkGetPhysicalDeviceSurfaceSupportKHR; did you enabled the VK_KHR_surface extension?'); + raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceSurfaceSupportKHR', 'VK_KHR_surface'); err := fInstanceCommands.vkGetPhysicalDeviceSurfaceSupportKHR(fHandle, aQueueFamilyIndex, aSurface, @b); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device surface support', err); @@ -158,7 +151,7 @@ var err: TVkResult; begin if not Assigned(fInstanceCommands.vkGetPhysicalDeviceSurfaceCapabilitiesKHR) then - raise TvkuException.Create('invalid function pointer: vkGetPhysicalDeviceSurfaceCapabilitiesKHR; did you enabled the VK_KHR_surface extension?'); + raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceSurfaceCapabilitiesKHR', 'VK_KHR_surface'); err := fInstanceCommands.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(fHandle, aSurface, @result); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device surface capabilities', err); @@ -170,7 +163,7 @@ var c: VkUint32; begin result := nil; if not Assigned(fInstanceCommands.vkGetPhysicalDeviceSurfaceFormatsKHR) then - raise TvkuException.Create('invalid function pointer: vkGetPhysicalDeviceSurfaceFormatsKHR; did you enabled the VK_KHR_surface extension?'); + raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceSurfaceFormatsKHR', 'VK_KHR_surface'); fInstanceCommands.vkGetPhysicalDeviceSurfaceFormatsKHR(fHandle, aSurface, @c, nil); SetLength(result, c); fInstanceCommands.vkGetPhysicalDeviceSurfaceFormatsKHR(fHandle, aSurface, @c, @result[0]); @@ -184,7 +177,7 @@ var begin result := nil; if not Assigned(fInstanceCommands.vkGetPhysicalDeviceSurfacePresentModesKHR) then - raise TvkuException.Create('invalid function pointer: vkGetPhysicalDeviceSurfacePresentModesKHR; did you enabled the VK_KHR_surface extension?'); + raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceSurfacePresentModesKHR', 'VK_KHR_surface'); err := fInstanceCommands.vkGetPhysicalDeviceSurfacePresentModesKHR(fHandle, aSurface, @c, nil); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device surface present mode count', err); @@ -202,7 +195,7 @@ var begin result := nil; if not Assigned(fInstanceCommands.vkGetPhysicalDeviceDisplayPropertiesKHR) then - raise TvkuException.Create('invalid function pointer: vkGetPhysicalDeviceDisplayPropertiesKHR; did you enabled the VK_KHR_display extension?'); + raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceDisplayPropertiesKHR', 'VK_KHR_display'); err := fInstanceCommands.vkGetPhysicalDeviceDisplayPropertiesKHR(fHandle, @c, nil); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device display property count', err); @@ -220,7 +213,7 @@ var begin result := nil; if not Assigned(fInstanceCommands.vkGetPhysicalDeviceDisplayPlanePropertiesKHR) then - raise TvkuException.Create('invalid function pointer: vkGetPhysicalDeviceDisplayPlanePropertiesKHR; did you enabled the VK_KHR_display extension?'); + raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceDisplayPlanePropertiesKHR', 'VK_KHR_display'); err := fInstanceCommands.vkGetPhysicalDeviceDisplayPlanePropertiesKHR(fHandle, @c, nil); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device display plane property count', err); @@ -238,7 +231,7 @@ var begin result := nil; if not Assigned(fInstanceCommands.vkGetDisplayPlaneSupportedDisplaysKHR) then - raise TvkuException.Create('invalid function pointer: vkGetDisplayPlaneSupportedDisplaysKHR; did you enabled the VK_KHR_display extension?'); + raise TvkuInvalidFuncPtrException.Create('vkGetDisplayPlaneSupportedDisplaysKHR', 'VK_KHR_display'); err := fInstanceCommands.vkGetDisplayPlaneSupportedDisplaysKHR(fHandle, aPlaneIndex, @c, nil); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get supported display plane count', err); @@ -256,7 +249,7 @@ var begin result := nil; if not Assigned(fInstanceCommands.vkGetDisplayModePropertiesKHR) then - raise TvkuException.Create('invalid function pointer: vkGetDisplayModePropertiesKHR; did you enabled the VK_KHR_display extension?'); + raise TvkuInvalidFuncPtrException.Create('vkGetDisplayModePropertiesKHR', 'VK_KHR_display'); err := fInstanceCommands.vkGetDisplayModePropertiesKHR(fHandle, aDisplay, @c, nil); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get display mode property count', err); diff --git a/projects/utils/uvkuPhysicalDeviceFactory.pas b/projects/utils/uvkuPhysicalDeviceFactory.pas deleted file mode 100644 index 89923f4..0000000 --- a/projects/utils/uvkuPhysicalDeviceFactory.pas +++ /dev/null @@ -1,41 +0,0 @@ -unit uvkuPhysicalDeviceFactory; - -{$mode objfpc}{$H+} - -interface - -uses - Classes, SysUtils, - Vulkan, uvkuInstance, uvkuPhysicalDevice; - -type -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TvkuPhysicalDeviceFactory = class(TObject) - private - fInstance: TvkuInstance; - public - function CreatePhysicalDevice( - const aHandle: VkPhysicalDevice): TvkuPhysicalDevice; - - constructor Create(const aInstance: TvkuInstance); - end; - -implementation - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -//TvkuPhysicalDeviceFactory////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuPhysicalDeviceFactory.CreatePhysicalDevice(const aHandle: VkPhysicalDevice): TvkuPhysicalDevice; -begin - result := TvkuPhysicalDevice.Create(aHandle, fInstance.InstanceCommands); -end; - -///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TvkuPhysicalDeviceFactory.Create(const aInstance: TvkuInstance); -begin - inherited Create; - fInstance := aInstance; -end; - -end. - diff --git a/projects/utils/uvkuQueue.pas b/projects/utils/uvkuQueue.pas new file mode 100644 index 0000000..d36f3ab --- /dev/null +++ b/projects/utils/uvkuQueue.pas @@ -0,0 +1,39 @@ +unit uvkuQueue; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuBase; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuQueue = class(TvkuObject) + private + fHandle: VkQueue; + fDeviceCommands: TVkDeviceCommands; + public + property Handle: VkQueue read fHandle; + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + + constructor Create( + const aHandle: VkQueue; + const aDeviceCommands: TVkDeviceCommands); + end; + +implementation + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuQueue////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuQueue.Create(const aHandle: VkQueue; const aDeviceCommands: TVkDeviceCommands); +begin + inherited Create; + fHandle := aHandle; + fDeviceCommands := aDeviceCommands; +end; + +end. + diff --git a/projects/utils/uvkuSurface.pas b/projects/utils/uvkuSurface.pas index 1844f4d..ddb5dd8 100644 --- a/projects/utils/uvkuSurface.pas +++ b/projects/utils/uvkuSurface.pas @@ -7,36 +7,34 @@ interface uses Classes, SysUtils, - Vulkan; + Vulkan, uvkuBase; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TvkuSurface = class(TObject) + TvkuSurface = class(TvkuAllocHandle) private fHandle: VkSurfaceKHR; - fInstance: VkInstance; - fAllocCallbacks: PVkAllocationCallbacks; fInstanceCommands: TVkInstanceCommands; - procedure CreateHandle(const aCreateInfo: Pointer; const aAllocCallbacks: PVkAllocationCallbacks); + procedure CreateHandle(const aCreateInfo: Pointer); public property Handle: VkSurfaceKHR read fHandle; - property Instance: VkInstance read fInstance; property InstanceCommands: TVkInstanceCommands read fInstanceCommands; {$IF DEFINED(VK_USE_PLATFORM_WIN32_KHR)} constructor Create( - const aInstance: VkInstance; - const aCreateInfo: TVkWin32SurfaceCreateInfoKHR; - const aInstanceCommands: TVkInstanceCommands); - constructor Create( - const aInstance: VkInstance; const aCreateInfo: TVkWin32SurfaceCreateInfoKHR; const aInstanceCommands: TVkInstanceCommands; - const aAllocCallbacks: TVkAllocationCallbacks); + const aAllocCallbacks: PVkAllocationCallbacks = nil); {$ELSE} {$ERROR 'unknown or unsupportet platform'} {$ENDIF} + + constructor Create( + const aHandle: VkSurfaceKHR; + const aOwnsHandle: Boolean; + const aInstanceCommands: TVkInstanceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); destructor Destroy; override; public class function GetPlatformSurfaceExtensionName: String; @@ -50,17 +48,13 @@ uses ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuSurface//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TvkuSurface.CreateHandle(const aCreateInfo: Pointer; const aAllocCallbacks: PVkAllocationCallbacks); +procedure TvkuSurface.CreateHandle(const aCreateInfo: Pointer); var err: TVkResult; begin - if Assigned(aAllocCallbacks) then begin - new(fAllocCallbacks); - fAllocCallbacks^ := aAllocCallbacks^; - end; {$IF DEFINED(VK_USE_PLATFORM_WIN32_KHR)} if not Assigned(fInstanceCommands.vkCreateWin32SurfaceKHR) then - raise TvkuException.Create('invalid function pointer: vkCreateWin32SurfaceKHR; did you enabled the VK_KHR_win32_surface extension?'); - err := fInstanceCommands.vkCreateWin32SurfaceKHR(fInstance, aCreateInfo, fAllocCallbacks, @fHandle); + raise TvkuInvalidFuncPtrException.Create('vkCreateWin32SurfaceKHR', 'VK_KHR_win32_surface'); + err := fInstanceCommands.vkCreateWin32SurfaceKHR(fInstanceCommands.Instance, aCreateInfo, AllocCallbacks, @fHandle); {$ENDIF} if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to create surface', err); @@ -68,37 +62,33 @@ end; {$IF DEFINED(VK_USE_PLATFORM_WIN32_KHR)} ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TvkuSurface.Create(const aInstance: VkInstance; const aCreateInfo: TVkWin32SurfaceCreateInfoKHR; - const aInstanceCommands: TVkInstanceCommands); +constructor TvkuSurface.Create(const aCreateInfo: TVkWin32SurfaceCreateInfoKHR; + const aInstanceCommands: TVkInstanceCommands; const aAllocCallbacks: PVkAllocationCallbacks); begin inherited Create; - fInstance := aInstance; fInstanceCommands := aInstanceCommands; - CreateHandle(@aCreateInfo, nil); + SetAllocCallbacks(aAllocCallbacks); + CreateHandle(@aCreateInfo); end; +{$ENDIF} ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TvkuSurface.Create(const aInstance: VkInstance; const aCreateInfo: TVkWin32SurfaceCreateInfoKHR; - const aInstanceCommands: TVkInstanceCommands; const aAllocCallbacks: TVkAllocationCallbacks); +constructor TvkuSurface.Create(const aHandle: VkSurfaceKHR; const aOwnsHandle: Boolean; + const aInstanceCommands: TVkInstanceCommands; const aAllocCallbacks: PVkAllocationCallbacks); begin inherited Create; - fInstance := aInstance; + fHandle := aHandle; fInstanceCommands := aInstanceCommands; - CreateHandle(@aCreateInfo, @aAllocCallbacks); + OwnsHandle := aOwnsHandle; + SetAllocCallbacks(aAllocCallbacks); end; -{$ENDIF} ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TvkuSurface.Destroy; begin - if (fHandle <> VK_INVALID_NDP_HANDLE) then begin - fInstanceCommands.vkDestroySurfaceKHR(fInstance, fHandle, fAllocCallbacks); - fHandle := VK_INVALID_NDP_HANDLE; - end; - if Assigned(fAllocCallbacks) then begin - Dispose(fAllocCallbacks); - fAllocCallbacks := nil; - end; + if OwnsHandle and (fHandle <> VK_INVALID_NDP_HANDLE) then + fInstanceCommands.vkDestroySurfaceKHR(fInstanceCommands.Instance, fHandle, AllocCallbacks); + fHandle := VK_INVALID_NDP_HANDLE; inherited Destroy; end; diff --git a/projects/utils/uvkuSurfaceFactory.pas b/projects/utils/uvkuSurfaceFactory.pas index 6a3c6ad..e92b19d 100644 --- a/projects/utils/uvkuSurfaceFactory.pas +++ b/projects/utils/uvkuSurfaceFactory.pas @@ -34,20 +34,19 @@ type private fFlags: VkFlags; fWinControl: TWinControl; - fInstance: VkInstance; fInstanceCommands: TVkInstanceCommands; procedure SetWinControl(aValue: TWinControl); public property WinControl: TWinControl read fWinControl write SetWinControl; property Flags: VkFlags read fFlags write fFlags; - function CreateSurface: TvkuSurface; + function CreateSurface: TvkuSurfaceEx; function CreateSurface( const aAllocHandler: TvkuAllocationHandler; - const aOwnsHandler: Boolean): TvkuSurface; + const aOwnsHandler: Boolean): TvkuSurfaceEx; constructor Create(const aInstance: TvkuInstance); - constructor Create(const aInstance: VkInstance; const aInstanceCommands: TVkInstanceCommands); + constructor Create(const aInstanceCommands: TVkInstanceCommands); end; implementation @@ -154,13 +153,13 @@ begin end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuSurfaceFactory.CreateSurface: TvkuSurface; +function TvkuSurfaceFactory.CreateSurface: TvkuSurfaceEx; begin result := CreateSurface(nil, false); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuSurfaceFactory.CreateSurface(const aAllocHandler: TvkuAllocationHandler; const aOwnsHandler: Boolean): TvkuSurface; +function TvkuSurfaceFactory.CreateSurface(const aAllocHandler: TvkuAllocationHandler; const aOwnsHandler: Boolean): TvkuSurfaceEx; {$IF DEFINED(VK_USE_PLATFORM_XLIB_KHR)} {$ERROR 'TODO: implement'} {$ELSEIF DEFINED(VK_USE_PLATFORM_XCB_KHR)} @@ -195,8 +194,8 @@ begin CreateInfo.hwnd := fHwnd; {$ENDIF} if Assigned(aAllocHandler) - then srf := TvkuSurfaceEx.Create(fInstance, CreateInfo, fInstanceCommands, aAllocHandler.GetAllocationCallbacks) - else srf := TvkuSurfaceEx.Create(fInstance, CreateInfo, fInstanceCommands); + then srf := TvkuSurfaceEx.Create(CreateInfo, fInstanceCommands, aAllocHandler.GetAllocationCallbacksPtr) + else srf := TvkuSurfaceEx.Create(CreateInfo, fInstanceCommands); try srf.fAllocHandler := aAllocHandler; srf.fOwnsHandler := aOwnsHandler; @@ -209,11 +208,11 @@ end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuSurfaceFactory.Create(const aInstance: TvkuInstance); begin - Create(aInstance.Handle, aInstance.InstanceCommands); + Create(aInstance.InstanceCommands); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TvkuSurfaceFactory.Create(const aInstance: VkInstance; const aInstanceCommands: TVkInstanceCommands); +constructor TvkuSurfaceFactory.Create(const aInstanceCommands: TVkInstanceCommands); begin inherited Create; {$IF DEFINED(VK_USE_PLATFORM_XLIB_KHR)} @@ -229,7 +228,6 @@ begin {$ELSEIF DEFINED(VK_USE_PLATFORM_WIN32_KHR)} fHInstance := Vulkan.HINSTANCE(GetModuleHandle(nil)); {$ENDIF} - fInstance := aInstance; fInstanceCommands := aInstanceCommands; fFlags := 0; end; diff --git a/projects/utils/uvkuSwapChain.pas b/projects/utils/uvkuSwapChain.pas index 71baa3a..78d0a71 100644 --- a/projects/utils/uvkuSwapChain.pas +++ b/projects/utils/uvkuSwapChain.pas @@ -6,38 +6,32 @@ interface uses Classes, SysUtils, - Vulkan; + Vulkan, uvkuBase, uvkuTypes; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TvkuImageArr = array of VkImage; - TvkuSwapChain = class(TObject) + TvkuSwapChain = class(TvkuAllocHandle) private fHandle: VkSwapchainKHR; - fDevice: VkDevice; - fAllocCallbacks: PVkAllocationCallbacks; fDeviceCommands: TVkDeviceCommands; - procedure CreateHandle( - const aCreateInfo: PVkSwapchainCreateInfoKHR; - const aAllocCallbacks: PVkAllocationCallbacks); + procedure CreateHandle(const aCreateInfo: PVkSwapchainCreateInfoKHR); public property Handle: VkSwapchainKHR read fHandle; - property Device: VkDevice read fDevice; property DeviceCommands: TVkDeviceCommands read fDeviceCommands; function GetImages: TvkuImageArr; function AcquireNextImage(const aTimeout: VkUint64; const aSemaphore: VkSemaphore; const aFence: VkFence): VkUint32; constructor Create( - const aDevice: VkDevice; const aCreateInfo: TVkSwapchainCreateInfoKHR; - const aDeviceCommands: TVkDeviceCommands); + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); overload; constructor Create( - const aDevice: VkDevice; - const aCreateInfo: TVkSwapchainCreateInfoKHR; + const aHandle: VkSwapchainKHR; + const aOwnsHandle: Boolean; const aDeviceCommands: TVkDeviceCommands; - const aAllocCallbacks: TVkAllocationCallbacks); + const aAllocCallbacks: PVkAllocationCallbacks = nil); overload; destructor Destroy; override; end; @@ -49,18 +43,14 @@ uses ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuSwapChain////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -procedure TvkuSwapChain.CreateHandle(const aCreateInfo: PVkSwapchainCreateInfoKHR; const aAllocCallbacks: PVkAllocationCallbacks); +procedure TvkuSwapChain.CreateHandle(const aCreateInfo: PVkSwapchainCreateInfoKHR); var err: TVkResult; begin - if Assigned(aAllocCallbacks) then begin - new(fAllocCallbacks); - fAllocCallbacks^ := aAllocCallbacks^; - end; if not Assigned(fDeviceCommands.vkCreateSwapchainKHR) then raise TvkuException.Create('invalid function pointer: vkCreateSwapchainKHR; did you enabled the VK_KHR_swapchain extension?'); - err := fDeviceCommands.vkCreateSwapchainKHR(fDevice, aCreateInfo, fAllocCallbacks, @fHandle); + err := fDeviceCommands.vkCreateSwapchainKHR(fDeviceCommands.Device, aCreateInfo, AllocCallbacks, @fHandle); if (err < VK_SUCCESS) then - raise TvkuErrorException.Create('unable to create surface', err); + raise TvkuErrorException.Create('unable to create swap chain', err); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -70,12 +60,12 @@ var err: TVkResult; begin if not Assigned(fDeviceCommands.vkGetSwapchainImagesKHR) then - raise TvkuException.Create('invalid function pointer: vkGetSwapchainImagesKHR; did you enabled the VK_KHR_swapchain extension?'); - err := fDeviceCommands.vkGetSwapchainImagesKHR(fDevice, fHandle, @c, nil); + raise TvkuInvalidFuncPtrException.Create('vkGetSwapchainImagesKHR', 'VK_KHR_swapchain'); + err := fDeviceCommands.vkGetSwapchainImagesKHR(fDeviceCommands.Device, fHandle, @c, nil); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get swap chain image count', err); SetLength(result, c); - err := fDeviceCommands.vkGetSwapchainImagesKHR(fDevice, fHandle, @c, @result[0]); + err := fDeviceCommands.vkGetSwapchainImagesKHR(fDeviceCommands.Device, fHandle, @c, @result[0]); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get swap chain images', err); end; @@ -83,46 +73,42 @@ end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuSwapChain.AcquireNextImage(const aTimeout: VkUint64; const aSemaphore: VkSemaphore; const aFence: VkFence): VkUint32; var - c: VkUint32; err: TVkResult; begin if not Assigned(fDeviceCommands.vkAcquireNextImageKHR) then - raise TvkuException.Create('invalid function pointer: vkAcquireNextImageKHR; did you enabled the VK_KHR_swapchain extension?'); - err := fDeviceCommands.vkAcquireNextImageKHR(fDevice, fHandle, aTimeout, aSemaphore, aFence, @result); + raise TvkuInvalidFuncPtrException.Create('vkAcquireNextImageKHR', 'VK_KHR_swapchain'); + err := fDeviceCommands.vkAcquireNextImageKHR(fDeviceCommands.Device, fHandle, aTimeout, aSemaphore, aFence, @result); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to aquire next image', err); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TvkuSwapChain.Create(const aDevice: VkDevice; const aCreateInfo: TVkSwapchainCreateInfoKHR; const aDeviceCommands: TVkDeviceCommands); +constructor TvkuSwapChain.Create(const aCreateInfo: TVkSwapchainCreateInfoKHR; const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks); begin inherited Create; - fDevice := aDevice; fDeviceCommands := aDeviceCommands; - CreateHandle(@aCreateInfo, nil); + SetAllocCallbacks(aAllocCallbacks); + CreateHandle(@aCreateInfo); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TvkuSwapChain.Create(const aDevice: VkDevice; const aCreateInfo: TVkSwapchainCreateInfoKHR; - const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: TVkAllocationCallbacks); +constructor TvkuSwapChain.Create(const aHandle: VkSwapchainKHR; const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks); begin inherited Create; - fDevice := aDevice; + fHandle := aHandle; fDeviceCommands := aDeviceCommands; - CreateHandle(@aCreateInfo, @aAllocCallbacks); + OwnsHandle := aOwnsHandle; + SetAllocCallbacks(aAllocCallbacks); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TvkuSwapChain.Destroy; begin - if (fHandle <> VK_INVALID_NDP_HANDLE) then begin - fDeviceCommands.vkDestroySwapchainKHR(fDevice, fHandle, fAllocCallbacks); - fHandle := VK_INVALID_NDP_HANDLE; - end; - if Assigned(fAllocCallbacks) then begin - Dispose(fAllocCallbacks); - fAllocCallbacks := nil; - end; + if OwnsHandle and (fHandle <> VK_INVALID_NDP_HANDLE) then + fDeviceCommands.vkDestroySwapchainKHR(fDeviceCommands.Device, fHandle, AllocCallbacks); + fHandle := VK_INVALID_NDP_HANDLE; inherited Destroy; end; diff --git a/projects/utils/uvkuSwapChainFactory.pas b/projects/utils/uvkuSwapChainFactory.pas index 3c3289f..03d1bb2 100644 --- a/projects/utils/uvkuSwapChainFactory.pas +++ b/projects/utils/uvkuSwapChainFactory.pas @@ -6,7 +6,7 @@ interface uses Classes, SysUtils, - Vulkan, uvkuSwapChain, uvkuAllocationHandler, uvkuDevice; + Vulkan, uvkuSwapChain, uvkuTypes, uvkuAllocationHandler, uvkuDevice; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -19,10 +19,8 @@ type end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - TvkuUint32Arr = array of VkUint32; TvkuSwapChainFactory = class(TObject) private - fDevice: VkDevice; fDeviceCommands: TVkDeviceCommands; fFlags: VkSwapchainCreateFlagsKHR; @@ -45,7 +43,6 @@ type function GetQueueFamilyIndex(const aIndex: Integer): VkUint32; procedure SetQueueFamilyIndex(const aIndex: Integer; aValue: VkUint32); public - property Device: VkDevice read fDevice; property DeviceCommands: TVkDeviceCommands read fDeviceCommands; property Flags: VkSwapchainCreateFlagsKHR read fFlags write fFlags; @@ -73,7 +70,7 @@ type const aOwnsHandler: Boolean): TvkuSwapChain; constructor Create(const aDevice: TvkuDevice); - constructor Create(const aDevice: VkDevice; const aDeviceCommands: TVkDeviceCommands); + constructor Create(const aDeviceCommands: TVkDeviceCommands); end; implementation @@ -149,27 +146,27 @@ begin else CreateInfo.clipped := VK_FALSE; if Assigned(aAllocHandler) - then result := TvkuSwapChainEx.Create(fDevice, CreateInfo, fDeviceCommands, aAllocHandler.GetAllocationCallbacks) - else result := TvkuSwapChainEx.Create(fDevice, CreateInfo, fDeviceCommands); + then result := TvkuSwapChainEx.Create(CreateInfo, fDeviceCommands, aAllocHandler.GetAllocationCallbacksPtr) + else result := TvkuSwapChainEx.Create(CreateInfo, fDeviceCommands); try TvkuSwapChainEx(result).fAllocHandler := aAllocHandler; TvkuSwapChainEx(result).fOwnsHandler := aOwnsHandler; except FreeAndNil(result); + raise; end; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuSwapChainFactory.Create(const aDevice: TvkuDevice); begin - Create(aDevice.Handle, aDevice.DeviceCommands); + Create(aDevice.DeviceCommands); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -constructor TvkuSwapChainFactory.Create(const aDevice: VkDevice; const aDeviceCommands: TVkDeviceCommands); +constructor TvkuSwapChainFactory.Create(const aDeviceCommands: TVkDeviceCommands); begin inherited Create; - fDevice := aDevice; fDeviceCommands := aDeviceCommands; fPresentMode := VK_PRESENT_MODE_FIFO_KHR; end; diff --git a/projects/utils/uvkuTypes.pas b/projects/utils/uvkuTypes.pas new file mode 100644 index 0000000..af9e9da --- /dev/null +++ b/projects/utils/uvkuTypes.pas @@ -0,0 +1,45 @@ +unit uvkuTypes; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan; + +type + TvkuFloatArr = array of VkFloat; + TvkuUint32Arr = array of VkUint32; + TvkuImageArr = array of VkImage; + TvkuPhysicalDeviceArr = array of VkPhysicalDevice; + TvkuQueueFamilyPropertiesArr = array of TVkQueueFamilyProperties; + TvkuSparseImageFormatPropertiesArr = array of TVkSparseImageFormatProperties; + TvkuSurfaceFormatArr = array of TVkSurfaceFormatKHR; + TvkuPresentModeArr = array of TVkPresentModeKHR; + TvkuDisplayPropertiesArr = array of TVkDisplayPropertiesKHR; + TvkuDisplayPlanePropertiesArr = array of TVkDisplayPlanePropertiesKHR; + TvkuDisplayArr = array of VkDisplayKHR; + TvkuDisplayModePropertiesArr = array of TVkDisplayModePropertiesKHR; + TvkuCommandBufferArr = array of VkCommandBuffer; + + TvkuApplicationInfo = packed record + AppName: String; + AppVersion: VkVersion; + EngineName: String; + EngineVersion: VkVersion; + ApiVersion: VkVersion; + end; + + TvkuQueueCreateInfo = packed record + Flags: VkDeviceQueueCreateFlags; + FamilyIndex: VkUint32; + Priorities: TvkuFloatArr; + end; + TvkuQueueCreateInfoArr = array of TvkuQueueCreateInfo; + + +implementation + +end. + diff --git a/projects/utils/uvkuUtils.pas b/projects/utils/uvkuUtils.pas index 40ecf56..f328b7f 100644 --- a/projects/utils/uvkuUtils.pas +++ b/projects/utils/uvkuUtils.pas @@ -11,6 +11,7 @@ uses type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TvkuException = class(Exception); + TvkuErrorException = class(TvkuException) private fError: TVkResult; @@ -19,6 +20,18 @@ type constructor Create(const msg: string; const aError: TVkResult); end; + TvkuInvalidFuncPtrException = class(TvkuException) + private + fExtensionName: String; + fFunctionName: String; + fExtentionName: String; + public + property FunctionName: String read fFunctionName; + property ExtensionName: String read fExtensionName; + + constructor Create(const aFunctionName: String; const aExtensionName: String = ''); + end; + function vkuMakeString(const aFeatures: TVkPhysicalDeviceFeatures; const aSeperator: String = sLineBreak): String; function vkuMakeString(const aProperties: TVkPhysicalDeviceProperties; const aPrintLimits, aPrintSparseProps: Boolean): String; function vkuMakeString(const aMemoryProperties: TVkPhysicalDeviceMemoryProperties): String; @@ -34,6 +47,20 @@ begin fError := aError; end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuInvalidFuncPtrException//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuInvalidFuncPtrException.Create(const aFunctionName: String; const aExtensionName: String); +var s: String; +begin + fFunctionName := aFunctionName; + fExtensionName := aExtensionName; + s := 'did you load the vulkan core commands?'; + if (aExtensionName <> '') then + s := 'did you enabled/load the ' + fExtensionName + ' extension?'; + inherited Create('invalid function pointer: ' + fFunctionName + '; ' + s); +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////