25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
8.1 KiB

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