unit uvkuDevice; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Vulkan, uvkuBase; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TvkuDevice = class(TvkuAllocHandle) private fHandle: VkDevice; fInstanceCommands: TVkInstanceCommands; fDeviceCommands: TVkDeviceCommands; procedure CreateHandle( const aPhyDevice: VkPhysicalDevice; const aCreateInfo: PVkDeviceCreateInfo); public property Handle: VkDevice read fHandle; property DeviceCommands: TVkDeviceCommands read fDeviceCommands; function GetQueue( const aQueueFamilyIndex: VkUint32; const aQueueIndex: VkUint32): VkQueue; function AllocateMemory( const aSize: VkUint32; const aMemoryTypeIndex: VkUint32; aAllocCallbacks: PVkAllocationCallbacks = nil): VkDeviceMemory; procedure FreeMemory( const aMemory: VkDeviceMemory; aAllocCallbacks: PVkAllocationCallbacks = nil); constructor Create( const aPhysicalDevice: VkPhysicalDevice; const aCreateInfo: TVkDeviceCreateInfo; const aInstanceCommands: TVkInstanceCommands; const aAllocCallbacks: PVkAllocationCallbacks = nil); constructor Create( const aHandle: VkDevice; const aOwnsHandle: Boolean; const aInstanceCommands: TVkInstanceCommands; const aAllocCallbacks: PVkAllocationCallbacks = nil); destructor Destroy; override; end; implementation uses uvkuUtils; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuDevice///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuDevice.CreateHandle(const aPhyDevice: VkPhysicalDevice; const aCreateInfo: PVkDeviceCreateInfo); var err: TVkResult; begin if not Assigned(fInstanceCommands.vkCreateDevice) then 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); if not Assigned(fDeviceCommands) then raise TvkuException.Create('unable to load device commands'); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuDevice.GetQueue(const aQueueFamilyIndex: VkUint32; const 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; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuDevice.AllocateMemory(const aSize: VkUint32; const aMemoryTypeIndex: VkUint32; aAllocCallbacks: PVkAllocationCallbacks): VkDeviceMemory; var AllocInfo: TVkMemoryAllocateInfo; err: TVkResult; begin FillByte(AllocInfo, SizeOf(AllocInfo), 0); AllocInfo.sType := VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; AllocInfo.pNext := nil; AllocInfo.allocationSize := aSize; AllocInfo.memoryTypeIndex := aMemoryTypeIndex; if not Assigned(aAllocCallbacks) then aAllocCallbacks := AllocCallbacks; err := fDeviceCommands.vkAllocateMemory(fHandle, @AllocInfo, aAllocCallbacks, @result); if (err < VK_SUCCESS) then raise TvkuErrorException.Create('unable to allocate device memory', err); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuDevice.FreeMemory(const aMemory: VkDeviceMemory; aAllocCallbacks: PVkAllocationCallbacks); begin if not Assigned(aAllocCallbacks) then aAllocCallbacks := AllocCallbacks; fDeviceCommands.vkFreeMemory(fHandle, aMemory, aAllocCallbacks); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuDevice.Create(const aPhysicalDevice: VkPhysicalDevice; const aCreateInfo: TVkDeviceCreateInfo; const aInstanceCommands: TVkInstanceCommands; const aAllocCallbacks: PVkAllocationCallbacks); begin inherited Create; fHandle := nil; fInstanceCommands := aInstanceCommands; SetAllocCallbacks(aAllocCallbacks); CreateHandle(aPhysicalDevice, @aCreateInfo); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuDevice.Create(const aHandle: VkDevice; const aOwnsHandle: Boolean; const aInstanceCommands: TVkInstanceCommands; const aAllocCallbacks: PVkAllocationCallbacks); begin inherited Create; fHandle := aHandle; fInstanceCommands := aInstanceCommands; OwnsHandle := aOwnsHandle; SetAllocCallbacks(aAllocCallbacks); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// destructor TvkuDevice.Destroy; begin if OwnsHandle and (fHandle <> VK_INVALID_HANDLE) then fDeviceCommands.vkDestroyDevice(fHandle, AllocCallbacks); fHandle := VK_INVALID_HANDLE; FreeAndNil(fDeviceCommands); inherited Destroy; end; end.