unit uvkuSwapChain; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Vulkan; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TvkuImageArr = array of VkImage; TvkuSwapChain = class(TObject) private fHandle: VkSwapchainKHR; fDevice: VkDevice; fAllocCallbacks: PVkAllocationCallbacks; fDeviceCommands: TVkDeviceCommands; procedure CreateHandle( const aCreateInfo: PVkSwapchainCreateInfoKHR; const aAllocCallbacks: PVkAllocationCallbacks); 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); constructor Create( const aDevice: VkDevice; const aCreateInfo: TVkSwapchainCreateInfoKHR; const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: TVkAllocationCallbacks); destructor Destroy; override; end; implementation uses uvkuUtils; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuSwapChain////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuSwapChain.CreateHandle(const aCreateInfo: PVkSwapchainCreateInfoKHR; const aAllocCallbacks: PVkAllocationCallbacks); 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); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to create surface', err); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuSwapChain.GetImages: TvkuImageArr; var c: VkUint32; 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); 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]); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get swap chain images', err); 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); 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); begin inherited Create; fDevice := aDevice; fDeviceCommands := aDeviceCommands; CreateHandle(@aCreateInfo, nil); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuSwapChain.Create(const aDevice: VkDevice; const aCreateInfo: TVkSwapchainCreateInfoKHR; const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: TVkAllocationCallbacks); begin inherited Create; fDevice := aDevice; fDeviceCommands := aDeviceCommands; CreateHandle(@aCreateInfo, @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; inherited Destroy; end; end.