unit uvkuInstance; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Vulkan, uvkuPhysicalDevice; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TvkuPhysicalDeviceArr = array of VkPhysicalDevice; TvkuInstance = class(TObject) private fHandle: VkInstance; fAllocCallbacks: PVkAllocationCallbacks; fPhysicalDevices: TvkuPhysicalDeviceArr; function GetPhysicalDeviceCount: Integer; function GetPhysicalDevice(const aIndex: Integer): VkPhysicalDevice; procedure UpdatePhysicalDevices; protected procedure CreateHandle(aCreateInfo: PVkInstanceCreateInfo; aAllocCallbacks: PVkAllocationCallbacks); constructor Create; public property Handle: VkInstance read fHandle; property PhysicalDeviceCount: Integer read GetPhysicalDeviceCount; property PhysicalDevices[const aIndex: Integer]: VkPhysicalDevice read GetPhysicalDevice; function GetPhysicalDevices: TvkuPhysicalDeviceArr; constructor Create(const aCreateInfo: TVkInstanceCreateInfo); constructor Create(const aCreateInfo: TVkInstanceCreateInfo; const aAllocCallbacks: TVkAllocationCallbacks); destructor Destroy; override; end; implementation uses uvkuUtils; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuInstance/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuInstance.GetPhysicalDeviceCount: Integer; begin UpdatePhysicalDevices; result := Length(fPhysicalDevices); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuInstance.GetPhysicalDevice(const aIndex: Integer): VkPhysicalDevice; begin UpdatePhysicalDevices; if (aIndex < Low(fPhysicalDevices)) or (aIndex > High(fPhysicalDevices)) then raise TvkuException.CreateFmt('index (%d) out of range (%d : %d)', [aIndex, Low(fPhysicalDevices), High(fPhysicalDevices)]); result := fPhysicalDevices[aIndex]; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuInstance.UpdatePhysicalDevices; var c: VkUint32; err: TVkResult; begin if (Length(fPhysicalDevices) > 0) then exit; err := vkEnumeratePhysicalDevices(fHandle, @c, nil); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device number', err); SetLength(fPhysicalDevices, c); err := vkEnumeratePhysicalDevices(fHandle, @c, @fPhysicalDevices[0]); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical devices', err); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuInstance.GetPhysicalDevices: TvkuPhysicalDeviceArr; begin UpdatePhysicalDevices; result := fPhysicalDevices; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuInstance.CreateHandle(aCreateInfo: PVkInstanceCreateInfo; aAllocCallbacks: PVkAllocationCallbacks); var e: TVkResult; begin if Assigned(aAllocCallbacks) then begin new(fAllocCallbacks); fAllocCallbacks^ := aAllocCallbacks^; end; e := vkCreateInstance(aCreateInfo, fAllocCallbacks, @fHandle); if (e < VK_SUCCESS) then raise TvkuErrorException.Create('unable to create vulkan instance', e); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuInstance.Create; begin inherited Create; fHandle := nil; fAllocCallbacks := nil; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuInstance.Create(const aCreateInfo: TVkInstanceCreateInfo); begin Create; CreateHandle(@aCreateInfo, nil); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuInstance.Create(const aCreateInfo: TVkInstanceCreateInfo; const aAllocCallbacks: TVkAllocationCallbacks); begin Create; CreateHandle(@aCreateInfo, @aAllocCallbacks); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TvkuInstance.Destroy; begin if Assigned(fHandle) then begin vkDestroyInstance(fHandle, fAllocCallbacks); fHandle := nil; end; if Assigned(fAllocCallbacks) then begin Dispose(fAllocCallbacks); fAllocCallbacks := nil; end; inherited Destroy; end; end.