unit uvkuBuffer; {$mode objfpc}{$H+} interface uses Classes, SysUtils, Vulkan, uvkuBase, uvkuDeviceMemory; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// TvkuBuffer = class(TvkuAllocHandle) private fHandle: VkBuffer; fDeviceCommands: TVkDeviceCommands; fMemory: VkDeviceMemory; fBufferMemory: TvkuDeviceMemory; procedure CreateHandle(const aCreateInfo: TVkBufferCreateInfo); public property Handle: VkBuffer read fHandle; property DeviceCommands: TVkDeviceCommands read fDeviceCommands; property Memory: VkDeviceMemory read fMemory; procedure BindMemory( const aMemory: VkDeviceMemory; const aOffset: VkDeviceSize); function GetMemoryRequirements: TVkMemoryRequirements; procedure AllocateAndBindBufferMemory( const aMemoryProperties: TVkPhysicalDeviceMemoryProperties; aAllocCallbacks: PVkAllocationCallbacks = nil); 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; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuBuffer.BindMemory(const aMemory: VkDeviceMemory; const aOffset: VkDeviceSize); var err: TVkResult; begin err := fDeviceCommands.vkBindBufferMemory(fDeviceCommands.Device, fHandle, aMemory, aOffset); if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to bind buffer memory', err); fMemory := aMemory; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuBuffer.GetMemoryRequirements: TVkMemoryRequirements; begin fDeviceCommands.vkGetBufferMemoryRequirements(fDeviceCommands.Device, fHandle, @result); end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuBuffer.AllocateAndBindBufferMemory( const aMemoryProperties: TVkPhysicalDeviceMemoryProperties; aAllocCallbacks: PVkAllocationCallbacks); var i: Integer; bits: VkUint32; MemReq: TVkMemoryRequirements; Mem: VkDeviceMemory; MemAllocInfo: TVkMemoryAllocateInfo; err: TVkResult; begin MemReq := GetMemoryRequirements; FillByte(MemAllocInfo, SizeOf(MemAllocInfo), 0); MemAllocInfo.sType := VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; MemAllocInfo.pNext := nil; MemAllocInfo.allocationSize := MemReq.size; MemAllocInfo.memoryTypeIndex := vkuGetMemoryTypeIndex( aMemoryProperties, MemReq.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT); if not Assigned(aAllocCallbacks) then aAllocCallbacks := AllocCallbacks; err := fDeviceCommands.vkAllocateMemory(fDeviceCommands.Device, @MemAllocInfo, aAllocCallbacks, @Mem); if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to allocate buffer memory', err); fBufferMemory := TvkuDeviceMemory.Create(Mem, true, fDeviceCommands, aAllocCallbacks); BindMemory(fBufferMemory.Handle, 0); 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; FreeAndNil(fBufferMemory); inherited Destroy; end; end.