Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.

222 righe
8.3 KiB

  1. unit uMainForm;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ExtCtrls,
  6. Vulkan, uvkuAllocationHandler,
  7. uvkuInstance, uvkuInstanceFactory,
  8. uvkuPhysicalDevice, uvkuPhysicalDeviceFactory,
  9. uvkuSurface, uvkuSurfaceFactory,
  10. uvkuDevice, uvkuDeviceFactory,
  11. uvkuSwapChain, uvkuSwapChainFactory;
  12. type
  13. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  14. TCustomAllocHandler = class(TvkuAllocationHandler)
  15. protected
  16. function AllocateMemory(const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid; override;
  17. function ReallocateMemory(const aOriginal: PVkVoid; const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid; override;
  18. procedure FreeMemory(const aMemory: PVkVoid); override;
  19. end;
  20. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  21. TMainForm = class(TForm)
  22. RenderPanel: TPanel;
  23. procedure FormCreate(Sender: TObject);
  24. procedure FormDestroy(Sender: TObject);
  25. private
  26. fAllocHandler: TCustomAllocHandler;
  27. fInstance: TvkuInstance;
  28. fPhyDevice: TvkuPhysicalDevice;
  29. fDevice: TvkuDevice;
  30. fSurface: TvkuSurface;
  31. fSwapChain: TvkuSwapChain;
  32. public
  33. { public declarations }
  34. end;
  35. var
  36. MainForm: TMainForm;
  37. implementation
  38. {$R *.lfm}
  39. {$I Vulkan.inc}
  40. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  41. //TCustomAllocHandler////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  42. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  43. function TCustomAllocHandler.AllocateMemory(const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid;
  44. begin
  45. result := inherited AllocateMemory(aSize, aAlignment, aScope);
  46. WriteLn(Format('%d bytes of memory allocated at %p', [ aSize, result ]));
  47. end;
  48. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  49. function TCustomAllocHandler.ReallocateMemory(const aOriginal: PVkVoid; const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid;
  50. var p: PVkVoid;
  51. begin
  52. p := aOriginal;
  53. result := inherited ReallocateMemory(aOriginal, aSize, aAlignment, aScope);
  54. WriteLn(Format('%d bytes of memory (from %p) reallocated at %p', [ aSize, p, result ]));
  55. end;
  56. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  57. procedure TCustomAllocHandler.FreeMemory(const aMemory: PVkVoid);
  58. begin
  59. WriteLn(Format('free memory at %p', [ aMemory ]));
  60. inherited FreeMemory(aMemory);
  61. end;
  62. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  63. //TMainForm//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  64. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  65. procedure TMainForm.FormCreate(Sender: TObject);
  66. var
  67. PhyDevices: TvkuPhysicalDeviceArr;
  68. iFactory: TvkuInstanceFactory;
  69. pdFactory: TvkuPhysicalDeviceFactory;
  70. dFactory: TvkuDeviceFactory;
  71. sFactory: TvkuSurfaceFactory;
  72. scFactory: TvkuSwapChainFactory;
  73. qci: TvkuQueueCreateInfo;
  74. SrfFormats: TvkuSurfaceFormatArr;
  75. SurfaceCapabilities: TVkSurfaceCapabilitiesKHR;
  76. PresentModes: TvkuPresentModeArr;
  77. pm: TVkPresentModeKHR;
  78. begin
  79. fAllocHandler := TCustomAllocHandler.Create;
  80. WriteLn('create vulkan instance');
  81. iFactory := TvkuInstanceFactory.Create;
  82. try
  83. iFactory.Extensions.Add(VK_KHR_SURFACE_EXTENSION_NAME);
  84. iFactory.Extensions.Add(TvkuSurface.GetPlatformSurfaceExtensionName);
  85. fInstance := iFactory.CreateInstance(fAllocHandler, false);
  86. finally
  87. FreeAndNil(iFactory);
  88. end;
  89. WriteLn('check physical devices');
  90. PhyDevices := fInstance.GetPhysicalDevices;
  91. if (Length(PhyDevices) <= 0) then
  92. raise Exception.Create('unable to get physical device');
  93. pdFactory := TvkuPhysicalDeviceFactory.Create(fInstance);
  94. try
  95. fPhyDevice := pdFactory.CreatePhysicalDevice(PhyDevices[0]);
  96. finally
  97. FreeAndNil(pdFactory);
  98. end;
  99. WriteLn('create vulkan surface');
  100. sFactory := TvkuSurfaceFactory.Create(fInstance);
  101. try
  102. sFactory.WinControl := RenderPanel;
  103. fSurface := sFactory.CreateSurface(fAllocHandler, false);
  104. finally
  105. FreeAndNil(sFactory);
  106. end;
  107. WriteLn('create vulkan device');
  108. dFactory := TvkuDeviceFactory.Create(fInstance);
  109. try
  110. SetLength(qci.Priorities, 1);
  111. qci.Priorities[0] := 1.0;
  112. qci.FamilyIndex := 0;
  113. qci.Flags := 0;
  114. dFactory.QueueCreateInfoCount := 1;
  115. dFactory.QueueCreateInfo[0] := qci;
  116. fDevice := dFactory.CreateDevice(fPhyDevice.Handle, fAllocHandler, false);
  117. finally
  118. FreeAndNil(dFactory);
  119. end;
  120. WriteLn('create swap chain');
  121. scFactory := TvkuSwapChainFactory.Create(fDevice);
  122. try
  123. scFactory.Surface := fSurface.Handle;
  124. scFactory.ImageUsage := [ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ];
  125. scFactory.ImageArrayLayers := 1;
  126. scFactory.ImageSharingMode := VK_SHARING_MODE_EXCLUSIVE;
  127. scFactory.Clipped := true;
  128. scFactory.ComposideAlpha := [ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR ];
  129. WriteLn(' get surface capabilities');
  130. SurfaceCapabilities := fPhyDevice.GetSurfaceCapabilities(fSurface.Handle);
  131. if (SurfaceCapabilities.currentExtent.width = High(VkUint32)) then begin
  132. SurfaceCapabilities.currentExtent.width := ClientWidth;
  133. SurfaceCapabilities.currentExtent.height := ClientHeight;
  134. end else begin
  135. ClientWidth := SurfaceCapabilities.currentExtent.width;
  136. ClientHeight := SurfaceCapabilities.currentExtent.height;
  137. end;
  138. scFactory.ImageExtent := SurfaceCapabilities.currentExtent;
  139. WriteLn(' set min image count');
  140. scFactory.MinImageCount := SurfaceCapabilities.minImageCount + 1;
  141. if (SurfaceCapabilities.maxImageCount > 0) and
  142. (scFactory.MinImageCount > SurfaceCapabilities.maxImageCount) then
  143. scFactory.MinImageCount := SurfaceCapabilities.maxImageCount;
  144. WriteLn(' find suitable image format');
  145. SrfFormats := fPhyDevice.GetSurfaceFormats(fSurface.Handle);
  146. if (Length(SrfFormats) = 0) then begin
  147. WriteLn('no suitable formats found');
  148. halt;
  149. end;
  150. if (Length(SrfFormats) = 1) and (SrfFormats[0].format = VK_FORMAT_UNDEFINED) then begin
  151. scFactory.ImageFormat := VK_FORMAT_R8G8B8A8_UNORM;
  152. scFactory.ImageColorSpace := VK_COLORSPACE_SRGB_NONLINEAR_KHR;
  153. end else begin
  154. scFactory.ImageFormat := SrfFormats[0].format;
  155. scFactory.ImageColorSpace := SrfFormats[0].colorSpace;
  156. end;
  157. WriteLn(' set pre transform');
  158. scFactory.PreTransform := SurfaceCapabilities.currentTransform;
  159. if (VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR in SurfaceCapabilities.supportedTransforms) then
  160. scFactory.PreTransform := scFactory.PreTransform + [ VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ];
  161. WriteLn(' find suitable present mode');
  162. PresentModes := fPhyDevice.GetSurfacePresentModes(fSurface.Handle);
  163. if (Length(PresentModes) = 0) then begin
  164. WriteLn('unable to get present modes');
  165. halt;
  166. end;
  167. for pm in PresentModes do begin
  168. if (pm = VK_PRESENT_MODE_MAILBOX_KHR) then begin
  169. scFactory.PresentMode := pm;
  170. break;
  171. end;
  172. end;
  173. fSwapChain := scFactory.CreateSwapchain(fAllocHandler, false);
  174. finally
  175. FreeAndNil(scFactory);
  176. end;
  177. end;
  178. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  179. procedure TMainForm.FormDestroy(Sender: TObject);
  180. begin
  181. FreeAndNil(fSwapChain);
  182. FreeAndNil(fDevice);
  183. FreeAndNil(fSurface);
  184. FreeAndNil(fPhyDevice);
  185. FreeAndNil(fInstance);
  186. FreeAndNil(fAllocHandler);
  187. end;
  188. end.