No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.
 
 

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