You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

241 rivejä
9.3 KiB

  1. unit uvkuImage;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils,
  6. Vulkan, uvkuBase, uvkuDeviceMemory;
  7. type
  8. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. TvkuImage = class(TvkuAllocHandle)
  10. private
  11. fHandle: VkImage;
  12. fDeviceCommands: TVkDeviceCommands;
  13. fImageMemory: TvkuDeviceMemory;
  14. procedure CreateHandle(const aCreateInfo: TVkImageCreateInfo);
  15. public
  16. property Handle: VkImage read fHandle;
  17. property DeviceCommands: TVkDeviceCommands read fDeviceCommands;
  18. function GetMemoryBarrier(
  19. const aAspectMask: VkImageAspectFlags;
  20. const aOldLayout: TVkImageLayout;
  21. const aNewLayout: TVkImageLayout): TVkImageMemoryBarrier;
  22. procedure BindMemory(
  23. const aMemory: VkDeviceMemory;
  24. const aOffset: VkDeviceSize);
  25. function GetMemoryRequirements: TVkMemoryRequirements;
  26. procedure AllocateAndBindImageMemory(
  27. const aMemoryProperties: TVkPhysicalDeviceMemoryProperties;
  28. aAllocCallbacks: PVkAllocationCallbacks = nil);
  29. constructor Create(
  30. const aCreateInfo: TVkImageCreateInfo;
  31. const aDeviceCommands: TVkDeviceCommands;
  32. const aAllocCallbacks: PVkAllocationCallbacks = nil);
  33. constructor Create(
  34. const aHandle: VkImage;
  35. const aOwnsHandle: Boolean;
  36. const aDeviceCommands: TVkDeviceCommands;
  37. const aAllocCallbacks: PVkAllocationCallbacks = nil);
  38. destructor Destroy; override;
  39. end;
  40. implementation
  41. uses
  42. uvkuUtils;
  43. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  44. //TvkuImage//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  45. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  46. procedure TvkuImage.CreateHandle(const aCreateInfo: TVkImageCreateInfo);
  47. var err: TVkResult;
  48. begin
  49. err := fDeviceCommands.vkCreateImage(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle);
  50. if (err < VK_SUCCESS) then
  51. TvkuErrorException.Create('unable to create image', err);
  52. end;
  53. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  54. function TvkuImage.GetMemoryBarrier(
  55. const aAspectMask: VkImageAspectFlags;
  56. const aOldLayout: TVkImageLayout;
  57. const aNewLayout: TVkImageLayout): TVkImageMemoryBarrier;
  58. var
  59. range: TVkImageSubresourceRange;
  60. begin
  61. FillByte(range, SizeOf(range), 0);
  62. range.aspectMask := aAspectMask;
  63. range.baseMipLevel := 0;
  64. range.levelCount := 1;
  65. range.baseArrayLayer := 0;
  66. range.layerCount := 1;
  67. FillByte(result, SizeOf(result), 0);
  68. result.sType := VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  69. result.pNext := nil;
  70. result.srcAccessMask := [];
  71. result.dstAccessMask := [];
  72. result.oldLayout := aOldLayout;
  73. result.newLayout := aNewLayout;
  74. result.srcQueueFamilyIndex := 0;
  75. result.dstQueueFamilyIndex := 0;
  76. result.image := fHandle;
  77. result.subresourceRange := range;
  78. case aOldLayout of
  79. // Undefined layout:
  80. // Note: Only allowed as initial layout!
  81. // Note: Make sure any writes to the image have been finished
  82. VK_IMAGE_LAYOUT_UNDEFINED: begin
  83. result.srcAccessMask := [ VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT ];
  84. end;
  85. // Old layout is color attachment:
  86. // Note: Make sure any writes to the color buffer have been finished
  87. VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: begin
  88. result.srcAccessMask := [ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ];
  89. end;
  90. // Old layout is transfer source:
  91. // Note: Make sure any reads from the image have been finished
  92. VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: begin
  93. result.srcAccessMask := [ VK_ACCESS_TRANSFER_READ_BIT ];
  94. end;
  95. // Old layout is shader read (sampler, input attachment):
  96. // Note: Make sure any shader reads from the image have been finished
  97. VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: begin
  98. result.srcAccessMask := [ VK_ACCESS_SHADER_READ_BIT ];
  99. end;
  100. end;
  101. case aNewLayout of
  102. // New layout is transfer destination (copy, blit):
  103. // Note: Make sure any copyies to the image have been finished
  104. VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL: begin
  105. result.dstAccessMask := [ VK_ACCESS_TRANSFER_WRITE_BIT ];
  106. end;
  107. // New layout is transfer source (copy, blit):
  108. // Note: Make sure any reads from and writes to the image have been finished
  109. VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL: begin
  110. result.srcAccessMask := result.srcAccessMask + [ VK_ACCESS_TRANSFER_READ_BIT ];
  111. result.dstAccessMask := [ VK_ACCESS_TRANSFER_READ_BIT ];
  112. end;
  113. // New layout is color attachment:
  114. // Note: Make sure any writes to the color buffer hav been finished
  115. VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL: begin
  116. result.dstAccessMask := [ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ];
  117. result.srcAccessMask := [ VK_ACCESS_TRANSFER_READ_BIT ];
  118. end;
  119. // New layout is depth attachment:
  120. // Note: Make sure any writes to depth/stencil buffer have been finished
  121. VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL: begin
  122. result.dstAccessMask := result.dstAccessMask + [ VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT ];
  123. end;
  124. // New layout is shader read (sampler, input attachment):
  125. // Note: Make sure any writes to the image have been finished
  126. VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL: begin
  127. result.srcAccessMask := [ VK_ACCESS_HOST_WRITE_BIT, VK_ACCESS_TRANSFER_WRITE_BIT ];
  128. result.dstAccessMask := [ VK_ACCESS_SHADER_READ_BIT ];
  129. end;
  130. end;
  131. end;
  132. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  133. procedure TvkuImage.BindMemory(const aMemory: VkDeviceMemory; const aOffset: VkDeviceSize);
  134. var err: TVkResult;
  135. begin
  136. err := fDeviceCommands.vkBindImageMemory(fDeviceCommands.Device, fHandle, aMemory, aOffset);
  137. if (err < VK_SUCCESS) then
  138. TvkuErrorException.Create('unable to bind image memory', err);
  139. end;
  140. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  141. function TvkuImage.GetMemoryRequirements: TVkMemoryRequirements;
  142. begin
  143. fDeviceCommands.vkGetImageMemoryRequirements(fDeviceCommands.Device, fHandle, @result);
  144. end;
  145. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  146. procedure TvkuImage.AllocateAndBindImageMemory(const aMemoryProperties: TVkPhysicalDeviceMemoryProperties;
  147. aAllocCallbacks: PVkAllocationCallbacks);
  148. var
  149. i: Integer;
  150. bits: VkUint32;
  151. MemReq: TVkMemoryRequirements;
  152. Mem: VkDeviceMemory;
  153. MemAllocInfo: TVkMemoryAllocateInfo;
  154. err: TVkResult;
  155. begin
  156. MemReq := GetMemoryRequirements;
  157. FillByte(MemAllocInfo, SizeOf(MemAllocInfo), 0);
  158. MemAllocInfo.sType := VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  159. MemAllocInfo.pNext := nil;
  160. MemAllocInfo.allocationSize := MemReq.size;
  161. bits := MemReq.memoryTypeBits;
  162. for i := 0 to VK_MAX_MEMORY_TYPES-1 do begin
  163. if ((bits and 1) = 1) and
  164. (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT in aMemoryProperties.memoryTypes[i].propertyFlags) then
  165. begin
  166. MemAllocInfo.memoryTypeIndex := i;
  167. break;
  168. end;
  169. bits := bits shr 1;
  170. end;
  171. if not Assigned(aAllocCallbacks) then
  172. aAllocCallbacks := AllocCallbacks;
  173. err := fDeviceCommands.vkAllocateMemory(fDeviceCommands.Device, @MemAllocInfo, aAllocCallbacks, @Mem);
  174. if (err < VK_SUCCESS) then
  175. raise TvkuErrorException.Create('unable to allocate image memory', err);
  176. fImageMemory := TvkuDeviceMemory.Create(Mem, true, fDeviceCommands, aAllocCallbacks);
  177. BindMemory(fImageMemory.Handle, 0);
  178. end;
  179. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  180. constructor TvkuImage.Create(const aCreateInfo: TVkImageCreateInfo; const aDeviceCommands: TVkDeviceCommands;
  181. const aAllocCallbacks: PVkAllocationCallbacks);
  182. begin
  183. inherited Create;
  184. fDeviceCommands := aDeviceCommands;
  185. SetAllocCallbacks(aAllocCallbacks);
  186. CreateHandle(aCreateInfo);
  187. end;
  188. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  189. constructor TvkuImage.Create(const aHandle: VkImage; const aOwnsHandle: Boolean;
  190. const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks);
  191. begin
  192. inherited Create;
  193. fHandle := aHandle;
  194. fDeviceCommands := aDeviceCommands;
  195. OwnsHandle := aOwnsHandle;
  196. SetAllocCallbacks(aAllocCallbacks);
  197. end;
  198. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  199. destructor TvkuImage.Destroy;
  200. begin
  201. if OwnsHandle and (fHandle <> VK_INVALID_NDP_HANDLE) then
  202. fDeviceCommands.vkDestroyImage(fDeviceCommands.Device, fHandle, AllocCallbacks);
  203. fHandle := VK_INVALID_NDP_HANDLE;
  204. FreeAndNil(fImageMemory);
  205. inherited Destroy;
  206. end;
  207. end.