|
- unit uvkuImage;
-
- {$mode objfpc}{$H+}
-
- interface
-
- uses
- Classes, SysUtils,
- Vulkan, uvkuBase, uvkuDeviceMemory;
-
- type
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- TvkuImage = class(TvkuAllocHandle)
- private
- fHandle: VkImage;
- fDeviceCommands: TVkDeviceCommands;
- fMemory: VkDeviceMemory;
- fImageMemory: TvkuDeviceMemory;
-
- procedure CreateHandle(const aCreateInfo: TVkImageCreateInfo);
- public
- property Handle: VkImage read fHandle;
- property DeviceCommands: TVkDeviceCommands read fDeviceCommands;
- property Memory: VkDeviceMemory read fMemory;
-
- function GetMemoryBarrier(
- const aAspectMask: VkImageAspectFlags;
- const aOldLayout: TVkImageLayout;
- const aNewLayout: TVkImageLayout): TVkImageMemoryBarrier;
- procedure BindMemory(
- const aMemory: VkDeviceMemory;
- const aOffset: VkDeviceSize);
- function GetMemoryRequirements: TVkMemoryRequirements;
-
- procedure AllocateAndBindImageMemory(
- const aMemoryProperties: TVkPhysicalDeviceMemoryProperties;
- aAllocCallbacks: PVkAllocationCallbacks = nil);
-
- 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 := VK_QUEUE_FAMILY_IGNORED;
- result.dstQueueFamilyIndex := VK_QUEUE_FAMILY_IGNORED;
- 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;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TvkuImage.BindMemory(const aMemory: VkDeviceMemory; const aOffset: VkDeviceSize);
- var err: TVkResult;
- begin
- err := fDeviceCommands.vkBindImageMemory(fDeviceCommands.Device, fHandle, aMemory, aOffset);
- if (err <> VK_SUCCESS) then
- TvkuErrorException.Create('unable to bind image memory', err);
- fMemory := aMemory;
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- function TvkuImage.GetMemoryRequirements: TVkMemoryRequirements;
- begin
- fDeviceCommands.vkGetImageMemoryRequirements(fDeviceCommands.Device, fHandle, @result);
- end;
-
- /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- procedure TvkuImage.AllocateAndBindImageMemory(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_DEVICE_LOCAL_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 image memory', err);
- fImageMemory := TvkuDeviceMemory.Create(Mem, true, fDeviceCommands, aAllocCallbacks);
- BindMemory(fImageMemory.Handle, 0);
- 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;
- FreeAndNil(fImageMemory);
- inherited Destroy;
- end;
-
- end.
|