Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

1152 rader
45 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. ugluVector, ugluMatrix, uglcCamera;
  8. type
  9. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. TCustomAllocHandler = class(TvkuAllocationHandler)
  11. protected
  12. function AllocateMemory(const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid; override;
  13. function ReallocateMemory(const aOriginal: PVkVoid; const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid; override;
  14. procedure FreeMemory(const aMemory: PVkVoid); override;
  15. end;
  16. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  17. type
  18. TUniforms = packed record
  19. ProjectionMat: TgluMatrix4f;
  20. ModelMatrix: TgluMatrix4f;
  21. ViewMatrix: TgluMatrix4f;
  22. end;
  23. TMainForm = class(TForm)
  24. ApplicationProperties: TApplicationProperties;
  25. RenderPanel: TPanel;
  26. procedure ApplicationPropertiesIdle(Sender: TObject; var Done: Boolean);
  27. procedure FormCreate(Sender: TObject);
  28. procedure FormDestroy(Sender: TObject);
  29. private
  30. fGraphicsQueueFamilyIndex: VkUint32;
  31. fGraphicsQueueNodeIndex: VkUint32;
  32. fPresentQueueNodeIndex: VkUint32;
  33. fColorFormat: TVkFormat;
  34. fSurfaceColorSpace: TVkColorSpaceKHR;
  35. fDepthFormat: TVkFormat;
  36. fCamera: TglcCamera;
  37. fAllocHandler: TCustomAllocHandler;
  38. fDebugReporter: TvkuConsoleDebugReporter;
  39. fInstance: TvkuInstance;
  40. fPhyDevice: TvkuPhysicalDevice;
  41. fDevice: TvkuDevice;
  42. fQueue: TvkuQueue;
  43. fSurface: TvkuSurface;
  44. fSwapChain: TvkuSwapChain;
  45. fImages: array of TvkuImage;
  46. fImageViews: array of TvkuImageView;
  47. fRenderPass: TvkuRenderPass;
  48. fFrameBuffers: array of TvkuFrameBuffer;
  49. fDescSetLayout: TvkuDescriptorSetLayout;
  50. fPipelineLayout: TvkuPipelineLayout;
  51. fVertexShader: TvkuShaderModule;
  52. fFragmentShader: TvkuShaderModule;
  53. fPipeline: TvkuGraphicsPipeline;
  54. fCommandPool: TvkuCommandPool;
  55. fDrawCommandBuffers: array of TvkuCommandBuffer;
  56. fPostPresentCommandBuffer: TvkuCommandBuffer;
  57. fDepthStencilImage: TvkuImage;
  58. fDepthStencilImageView: TvkuImageView;
  59. fPipelineCache: TvkuPipelineCache;
  60. fDescriptorPool: TvkuDescriptorPool;
  61. fDescriptorSet: TvkuDescriptorSet;
  62. fVertex: packed record
  63. DataMemory: TvkuDeviceMemory;
  64. DataBuffer: TvkuBuffer;
  65. IndexMemory: TvkuDeviceMemory;
  66. IndexBuffer: TvkuBuffer;
  67. end;
  68. fUniform: packed record
  69. Values: TUniforms;
  70. Memory: TvkuDeviceMemory;
  71. Buffer: TvkuBuffer;
  72. end;
  73. procedure UpdateUniformBuffers;
  74. procedure Render;
  75. end;
  76. var
  77. MainForm: TMainForm;
  78. implementation
  79. {$R *.lfm}
  80. {$I Vulkan.inc}
  81. uses
  82. uvkuUtils;
  83. const
  84. VERTEX_BUFFER_BIND_ID = 0;
  85. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  86. //TCustomAllocHandler////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  87. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  88. function TCustomAllocHandler.AllocateMemory(const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid;
  89. begin
  90. result := inherited AllocateMemory(aSize, aAlignment, aScope);
  91. WriteLn(Format(' MEM - %d bytes of memory allocated at %p', [ aSize, result ]));
  92. end;
  93. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  94. function TCustomAllocHandler.ReallocateMemory(const aOriginal: PVkVoid; const aSize: VkSize; const aAlignment: VkSize; const aScope: TVkSystemAllocationScope): PVkVoid;
  95. var p: PVkVoid;
  96. begin
  97. p := aOriginal;
  98. result := inherited ReallocateMemory(aOriginal, aSize, aAlignment, aScope);
  99. WriteLn(Format(' MEM - %d bytes of memory (from %p) reallocated at %p', [ aSize, p, result ]));
  100. end;
  101. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  102. procedure TCustomAllocHandler.FreeMemory(const aMemory: PVkVoid);
  103. begin
  104. WriteLn(Format(' MEM - free memory at %p', [ aMemory ]));
  105. inherited FreeMemory(aMemory);
  106. end;
  107. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  108. //TMainForm//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  109. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  110. procedure TMainForm.FormCreate(Sender: TObject);
  111. type
  112. TVertex = packed record
  113. position: array[0..2] of VkFloat;
  114. color: array[0..2] of VkFloat;
  115. end;
  116. TVertexData = array[0..2] of TVertex;
  117. TIndexData = array[0..2] of VkUint32;
  118. const
  119. ClearColor: TVkClearValue = ( color: ( float32: ( 0.0, 0.0, 0.0, 1.0 ) ) );
  120. ClearDepthStencil: TVkClearValue = ( depthStencil: ( depth: 1.0; stencil: 0 ) );
  121. VertexData: TVertexData = (
  122. ( position: ( 1.0, 1.0, 0.0 ); color: ( 1.0, 0.0, 0.0 ) ),
  123. ( position: (-1.0, 1.0, 0.0 ); color: ( 0.0, 1.0, 0.0 ) ),
  124. ( position: ( 0.0,-1.0, 0.0 ); color: ( 0.0, 0.0, 1.0 ) )
  125. );
  126. IndexData: TIndexData = (
  127. 0, 1, 2
  128. );
  129. var
  130. PhyDevices: TVkPhysicalDeviceArr;
  131. InstanceFactory: TvkuInstanceFactory;
  132. DeviceFactory: TvkuDeviceFactory;
  133. SurfaceFactory: TvkuSurfaceFactory;
  134. CommandPoolFactory: TvkuCommandPoolFactory;
  135. SwapChainFactory: TvkuSwapChainFactory;
  136. ImageFactory: TvkuImageFactory;
  137. ImageViewFactory: TvkuImageViewFactory;
  138. RenderPassFactory: TvkuRenderPassFactory;
  139. FrameBufferFactory: TvkuFrameBufferFactory;
  140. DescSetLayoutFactory: TvkuDescriptorSetLayoutFactory;
  141. PipelineLayoutFactory: TvkuPipelineLayoutFactory;
  142. ShaderModuleFactory: TvkuShaderModuleFactory;
  143. PipelineFactory: TvkuGraphicsPipelineFactory;
  144. PipelineCacheFactory: TvkuPipelineCacheFactory;
  145. BufferFactory: TvkuBufferFactory;
  146. DescriptorPoolFactory: TvkuDescriptorPoolFactory;
  147. SetupCommandBuffer: TvkuCommandBuffer;
  148. QueueFamProps: TVkQueueFamilyPropertiesArr;
  149. f: TVkFormat;
  150. i: Integer;
  151. p: PVkVoid;
  152. SrfFormats: TVkSurfaceFormatArr;
  153. SurfaceCapabilities: TVkSurfaceCapabilitiesKHR;
  154. PresentModes: TVkPresentModeArr;
  155. pm: TVkPresentModeKHR;
  156. Images: TVkImageArr;
  157. AllocCallbacks: TVkAllocationCallbacks;
  158. ImageMemoryBarrier: TVkImageMemoryBarrier;
  159. CommandBuffers: TVkCommandBufferArr;
  160. MemReq: TVkMemoryRequirements;
  161. vp: TVkViewport;
  162. r2D: TVkRect2D;
  163. begin
  164. try
  165. SetupCommandBuffer := nil;
  166. fCamera := TglcCamera.Create;
  167. fAllocHandler := TCustomAllocHandler.Create;
  168. AllocCallbacks := fAllocHandler.GetStructure;
  169. //////////////////////////////////////////////////////////////////////////////
  170. WriteLn('create instance: ');
  171. InstanceFactory := TvkuInstanceFactory.Create;
  172. try
  173. InstanceFactory.AllocHandler := fAllocHandler;
  174. InstanceFactory.EnabledExtensionNames.Add(VK_KHR_SURFACE_EXTENSION_NAME);
  175. InstanceFactory.EnabledExtensionNames.Add(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
  176. InstanceFactory.EnabledExtensionNames.Add(TvkuSurface.GetPlatformSurfaceExtensionName);
  177. fInstance := InstanceFactory.CreateInstance;
  178. WriteLn(' handle: ', PtrUInt(fInstance.Handle));
  179. WriteLn(' done');
  180. finally
  181. FreeAndNil(InstanceFactory);
  182. end;
  183. fDebugReporter := TvkuConsoleDebugReporter.Create(fInstance.InstanceCommands, fAllocHandler);
  184. //////////////////////////////////////////////////////////////////////////////
  185. WriteLn('find suitable physical device');
  186. PhyDevices := fInstance.GetPhysicalDevices;
  187. if (Length(PhyDevices) <= 0) then
  188. raise TvkuException.Create('unable to get physical device');
  189. fPhyDevice := TvkuPhysicalDevice.Create(PhyDevices[0], fInstance.InstanceCommands);
  190. WriteLn(' handle: ', PtrUInt(fPhyDevice.Handle));
  191. Write(' find suitable graphics queue index... ');
  192. QueueFamProps := fPhyDevice.GetQueueFamilyProperties;
  193. fGraphicsQueueFamilyIndex := high(fGraphicsQueueFamilyIndex);
  194. for i := low(QueueFamProps) to high(QueueFamProps) do begin
  195. if (VK_QUEUE_GRAPHICS_BIT in QueueFamProps[i].queueFlags) then begin
  196. fGraphicsQueueFamilyIndex := i;
  197. WriteLn(fGraphicsQueueFamilyIndex);
  198. break;
  199. end;
  200. end;
  201. if (fGraphicsQueueFamilyIndex = high(fGraphicsQueueFamilyIndex)) then
  202. raise TvkuException.Create('unable to find graphics queue index');
  203. Write(' find suitable depth format... ');
  204. f := VK_FORMAT_UNDEFINED;
  205. for f in [ VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D16_UNORM ] do begin
  206. if (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT in fPhyDevice.GetFormatProperties(f).optimalTilingFeatures) then begin
  207. fDepthFormat := f;
  208. break;
  209. end;
  210. end;
  211. WriteLn(fDepthFormat);
  212. WriteLn(' done');
  213. //////////////////////////////////////////////////////////////////////////////
  214. WriteLn('create device');
  215. DeviceFactory := TvkuDeviceFactory.Create(fInstance);
  216. try
  217. DeviceFactory.AllocHandler := fAllocHandler;
  218. DeviceFactory.EnabledExtensionNames.Add('VK_KHR_swapchain');
  219. DeviceFactory.QueueCreateInfos.Length := 1;
  220. with DeviceFactory.QueueCreateInfos[0] do begin
  221. Flags := 0;
  222. QueueFamilyIndex := fGraphicsQueueFamilyIndex;
  223. QueuePriorities.Length := 1;
  224. QueuePriorities[0] := 1.0;
  225. end;
  226. fDevice := DeviceFactory.CreateDevice(fPhyDevice.Handle);
  227. WriteLn(' handle: ', PtrUInt(fDevice.Handle));
  228. WriteLn(' done');
  229. finally
  230. FreeAndNil(DeviceFactory);
  231. end;
  232. //////////////////////////////////////////////////////////////////////////////
  233. WriteLn('find suitable queue');
  234. fQueue := TvkuQueue.Create(fDevice.GetQueue(fGraphicsQueueFamilyIndex, 0), fDevice.DeviceCommands);
  235. WriteLn(' handle: ', PtrUInt(fQueue.Handle));
  236. WriteLn(' done');
  237. //////////////////////////////////////////////////////////////////////////////
  238. WriteLn('create surface: ');
  239. SurfaceFactory := TvkuSurfaceFactory.Create(fInstance);
  240. try
  241. SurfaceFactory.AllocHandler := fAllocHandler;
  242. SurfaceFactory.WinControl := RenderPanel;
  243. fSurface := SurfaceFactory.CreateSurface;
  244. WriteLn(' handle: ', PtrUInt(fSurface.Handle));
  245. WriteLn(' find suitable graphics and present queue node index');
  246. fGraphicsQueueNodeIndex := high(fGraphicsQueueNodeIndex);
  247. fPresentQueueNodeIndex := high(fPresentQueueNodeIndex);
  248. QueueFamProps := fPhyDevice.GetQueueFamilyProperties;
  249. for i := low(QueueFamProps) to high(QueueFamProps) do begin
  250. if (VK_QUEUE_GRAPHICS_BIT in QueueFamProps[i].queueFlags) then begin
  251. if (fGraphicsQueueNodeIndex = high(fGraphicsQueueNodeIndex)) then
  252. fGraphicsQueueNodeIndex := i;
  253. if fPhyDevice.GetSurfaceSupport(i, fSurface.Handle) then begin
  254. fGraphicsQueueNodeIndex := i;
  255. fPresentQueueNodeIndex := i;
  256. break;
  257. end;
  258. end;
  259. end;
  260. if (fPresentQueueNodeIndex = high(fPresentQueueNodeIndex)) then begin
  261. for i := low(QueueFamProps) to high(QueueFamProps) do begin
  262. if fPhyDevice.GetSurfaceSupport(i, fSurface.Handle) then begin
  263. fPresentQueueNodeIndex := i;
  264. break;
  265. end;
  266. end;
  267. end;
  268. WriteLn(' graphics queue node index: ', fGraphicsQueueNodeIndex);
  269. WriteLn(' present queue node index: ', fPresentQueueNodeIndex);
  270. if (fGraphicsQueueNodeIndex = high(fGraphicsQueueNodeIndex)) or
  271. (fPresentQueueNodeIndex = high(fPresentQueueNodeIndex)) or
  272. (fPresentQueueNodeIndex <> fGraphicsQueueNodeIndex) then
  273. raise TvkuException.Create('different graphic and present queue node index is not supported yet');
  274. WriteLn(' find suitable image format');
  275. SrfFormats := fPhyDevice.GetSurfaceFormats(fSurface.Handle);
  276. if (Length(SrfFormats) = 0) then
  277. raise TvkuException.Create('no suitable formats found');
  278. if (Length(SrfFormats) = 1) and (SrfFormats[0].format = VK_FORMAT_UNDEFINED) then begin
  279. fColorFormat := VK_FORMAT_B8G8R8A8_UNORM;
  280. fSurfaceColorSpace := VK_COLORSPACE_SRGB_NONLINEAR_KHR;
  281. end else begin
  282. fColorFormat := SrfFormats[0].format;
  283. fSurfaceColorSpace := SrfFormats[0].colorSpace;
  284. end;
  285. WriteLn(' format: ', fColorFormat);
  286. WriteLn(' color space: ', fSurfaceColorSpace);
  287. WriteLn(' done');
  288. finally
  289. FreeAndNil(SurfaceFactory);
  290. end;
  291. //////////////////////////////////////////////////////////////////////////////
  292. WriteLn('create command pool');
  293. CommandPoolFactory := TvkuCommandPoolFactory.Create(fDevice);
  294. try
  295. CommandPoolFactory.Flags := [ VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT ];
  296. CommandPoolFactory.QueueFamilyIndex := fGraphicsQueueNodeIndex;
  297. fCommandPool := CommandPoolFactory.CreateCommandPool;
  298. WriteLn(' handle: ', PtrUInt(fCommandPool.Handle));
  299. WriteLn(' alloc setup command buffer');
  300. SetupCommandBuffer := TvkuCommandBuffer.Create(
  301. fCommandPool.AllocateCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY),
  302. true, fCommandPool.Handle, fDevice.DeviceCommands);
  303. SetupCommandBuffer.BeginCommand;
  304. WriteLn(' handle: ', PtrUInt(SetupCommandBuffer.Handle));
  305. WriteLn(' done');
  306. finally
  307. FreeAndNil(CommandPoolFactory);
  308. end;
  309. //////////////////////////////////////////////////////////////////////////////
  310. WriteLn('create swap chain');
  311. SwapChainFactory := TvkuSwapChainFactory.Create(fDevice);
  312. try
  313. SwapChainFactory.AllocHandler := fAllocHandler;
  314. SwapChainFactory.Surface := fSurface.Handle;
  315. SwapChainFactory.ImageUsage := [ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ];
  316. SwapChainFactory.ImageArrayLayers := 1;
  317. SwapChainFactory.ImageSharingMode := VK_SHARING_MODE_EXCLUSIVE;
  318. SwapChainFactory.Clipped := true;
  319. SwapChainFactory.ComposideAlpha := [ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR ];
  320. SwapChainFactory.ImageFormat := fColorFormat;
  321. SwapChainFactory.ImageColorSpace := fSurfaceColorSpace;
  322. WriteLn(' get surface capabilities');
  323. SurfaceCapabilities := fPhyDevice.GetSurfaceCapabilities(fSurface.Handle);
  324. if (SurfaceCapabilities.currentExtent.width = High(VkUint32)) then begin
  325. SurfaceCapabilities.currentExtent.width := ClientWidth;
  326. SurfaceCapabilities.currentExtent.height := ClientHeight;
  327. end else begin
  328. ClientWidth := SurfaceCapabilities.currentExtent.width;
  329. ClientHeight := SurfaceCapabilities.currentExtent.height;
  330. end;
  331. WriteLn(' width: ', SurfaceCapabilities.currentExtent.width);
  332. WriteLn(' height: ', SurfaceCapabilities.currentExtent.height);
  333. SwapChainFactory.ImageExtent := SurfaceCapabilities.currentExtent;
  334. Write(' set min image count... ');
  335. SwapChainFactory.MinImageCount := SurfaceCapabilities.minImageCount + 1;
  336. if (SurfaceCapabilities.maxImageCount > 0) and
  337. (SwapChainFactory.MinImageCount > SurfaceCapabilities.maxImageCount) then
  338. SwapChainFactory.MinImageCount := SurfaceCapabilities.maxImageCount;
  339. WriteLn(SwapChainFactory.MinImageCount);
  340. WriteLn(' set pre transform...');
  341. SwapChainFactory.PreTransform := SurfaceCapabilities.currentTransform;
  342. if (VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR in SurfaceCapabilities.supportedTransforms) then
  343. SwapChainFactory.PreTransform := [ VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ];
  344. Write(' find suitable present mode... ');
  345. PresentModes := fPhyDevice.GetSurfacePresentModes(fSurface.Handle);
  346. if (Length(PresentModes) = 0) then
  347. raise TvkuException.Create('unable to get present modes');
  348. for pm in PresentModes do begin
  349. if (pm = VK_PRESENT_MODE_MAILBOX_KHR) then begin
  350. SwapChainFactory.PresentMode := pm;
  351. break;
  352. end;
  353. if (SwapChainFactory.PresentMode <> VK_PRESENT_MODE_MAILBOX_KHR)
  354. and (pm = VK_PRESENT_MODE_IMMEDIATE_KHR)
  355. then
  356. SwapChainFactory.PresentMode := pm;
  357. end;
  358. WriteLn(SwapChainFactory.PresentMode);
  359. fSwapChain := SwapChainFactory.CreateSwapchain;
  360. WriteLn(' handle: ', PtrUInt(fSwapChain.Handle));
  361. WriteLn(' done');
  362. finally
  363. FreeAndNil(SwapChainFactory);
  364. end;
  365. //////////////////////////////////////////////////////////////////////////////
  366. WriteLn('create images and image views');
  367. Images := fSwapChain.GetImages;
  368. SetLength(fImages, Length(Images));
  369. SetLength(fImageViews, Length(Images));
  370. ImageViewFactory := TvkuImageViewFactory.Create(fDevice);
  371. try
  372. ImageViewFactory.AllocHandler := fAllocHandler;
  373. ImageViewFactory.Format := fColorFormat;
  374. ImageViewFactory.ViewType := VK_IMAGE_VIEW_TYPE_2D;
  375. with ImageViewFactory.SubresourceRange do begin
  376. AspectMask := [ VK_IMAGE_ASPECT_COLOR_BIT ];
  377. BaseMipLevel := 0;
  378. LevelCount := 1;
  379. BaseArrayLayer := 0;
  380. LayerCount := 1;
  381. end;
  382. with ImageViewFactory.Components do begin
  383. r := VK_COMPONENT_SWIZZLE_R;
  384. g := VK_COMPONENT_SWIZZLE_G;
  385. b := VK_COMPONENT_SWIZZLE_B;
  386. a := VK_COMPONENT_SWIZZLE_A;
  387. end;
  388. for i := Low(fImageViews) to High(fImageViews) do begin
  389. fImages[i] := TvkuImage.Create(Images[i], false, fDevice.DeviceCommands, @AllocCallbacks);
  390. WriteLn(' image handle: ', PtrUInt(fImages[i].Handle));
  391. ImageMemoryBarrier := fImages[i].GetMemoryBarrier(
  392. [ VK_IMAGE_ASPECT_COLOR_BIT ],
  393. VK_IMAGE_LAYOUT_UNDEFINED,
  394. VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
  395. SetupCommandBuffer.PipelineBarrier(
  396. [ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT ],
  397. [ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT ],
  398. [],
  399. [],
  400. [],
  401. [ ImageMemoryBarrier ]);
  402. ImageViewFactory.Image := fImages[i].Handle;
  403. fImageViews[i] := ImageViewFactory.CreateImageView;
  404. WriteLn(' view handle: ', PtrUInt(fImageViews[i].Handle));
  405. end;
  406. WriteLn(' done');
  407. finally
  408. FreeAndNil(ImageViewFactory);
  409. end;
  410. //////////////////////////////////////////////////////////////////////////////
  411. WriteLn('create draw command buffers');
  412. SetLength(fDrawCommandBuffers, Length(fImageViews));
  413. CommandBuffers := fCommandPool.AllocateCommandBuffers(
  414. VK_COMMAND_BUFFER_LEVEL_PRIMARY,
  415. Length(fDrawCommandBuffers));
  416. for i := low(CommandBuffers) to high(CommandBuffers) do begin
  417. fDrawCommandBuffers[i] := TvkuCommandBuffer.Create(
  418. CommandBuffers[i],
  419. true,
  420. fCommandPool.Handle,
  421. fDevice.DeviceCommands);
  422. WriteLn(' handle: ', PtrUInt(fDrawCommandBuffers[i].Handle));
  423. end;
  424. WriteLn(' done');
  425. //////////////////////////////////////////////////////////////////////////////
  426. WriteLn('create post present command buffers');
  427. fPostPresentCommandBuffer := TvkuCommandBuffer.Create(
  428. fCommandPool.AllocateCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY),
  429. true,
  430. fCommandPool.Handle,
  431. fDevice.DeviceCommands);
  432. WriteLn(' handle: ', PtrUInt(fPostPresentCommandBuffer.Handle));
  433. WriteLn(' done');
  434. //////////////////////////////////////////////////////////////////////////////
  435. WriteLn('create depth stencil image and image view');
  436. ImageFactory := TvkuImageFactory.Create(fDevice);
  437. ImageViewFactory := TvkuImageViewFactory.Create(fDevice);
  438. try
  439. ImageFactory.ImageType := VK_IMAGE_TYPE_2D;
  440. ImageFactory.Format := fDepthFormat;
  441. ImageFactory.Extent := vkExtent3D(
  442. SurfaceCapabilities.currentExtent.width,
  443. SurfaceCapabilities.currentExtent.height,
  444. 1);
  445. ImageFactory.MipLevels := 1;
  446. ImageFactory.ArrayLayers := 1;
  447. ImageFactory.Samples := [ VK_SAMPLE_COUNT_1_BIT ];
  448. ImageFactory.Tiling := VK_IMAGE_TILING_OPTIMAL;
  449. ImageFactory.Usage := [
  450. VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
  451. VK_IMAGE_USAGE_TRANSFER_SRC_BIT ];
  452. fDepthStencilImage := ImageFactory.CreateImage;
  453. fDepthStencilImage.AllocateAndBindImageMemory(
  454. fPhyDevice.GetMemoryProperties,
  455. @AllocCallbacks);
  456. WriteLn(' image handle: ', PtrUInt(fDepthStencilImage.Handle));
  457. WriteLn(' create image memory barrier');
  458. ImageMemoryBarrier := fImages[i].GetMemoryBarrier(
  459. [ VK_IMAGE_ASPECT_DEPTH_BIT ],
  460. VK_IMAGE_LAYOUT_UNDEFINED,
  461. VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
  462. SetupCommandBuffer.PipelineBarrier(
  463. [ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT ],
  464. [ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT ],
  465. [],
  466. [],
  467. [],
  468. [ ImageMemoryBarrier ]);
  469. ImageViewFactory.Image := fDepthStencilImage.Handle;
  470. ImageViewFactory.ViewType := VK_IMAGE_VIEW_TYPE_2D;
  471. ImageViewFactory.Format := fDepthFormat;
  472. with ImageViewFactory.SubresourceRange do begin
  473. AspectMask := [ VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_ASPECT_STENCIL_BIT ];
  474. BaseMipLevel := 0;
  475. LevelCount := 1;
  476. BaseArrayLayer := 0;
  477. LayerCount := 1;
  478. end;
  479. fDepthStencilImageView := ImageViewFactory.CreateImageView;
  480. WriteLn(' view handle: ', PtrUInt(fDepthStencilImageView.Handle));
  481. WriteLn(' done');
  482. finally
  483. FreeAndNil(ImageViewFactory);
  484. FreeAndNil(ImageFactory);
  485. end;
  486. //////////////////////////////////////////////////////////////////////////////
  487. WriteLn('create render pass');
  488. RenderPassFactory := TvkuRenderPassFactory.Create(fDevice);
  489. try
  490. RenderPassFactory.Attachments.Length := 2;
  491. with RenderPassFactory.Attachments[0] do begin
  492. Format := fColorFormat;
  493. Samples := [ VK_SAMPLE_COUNT_1_BIT ];
  494. LoadOp := VK_ATTACHMENT_LOAD_OP_CLEAR;
  495. StoreOp := VK_ATTACHMENT_STORE_OP_STORE;
  496. StencilLoadOp := VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  497. StencilStoreOp := VK_ATTACHMENT_STORE_OP_DONT_CARE;
  498. InitialLayout := VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  499. FinalLayout := VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  500. end;
  501. with RenderPassFactory.Attachments[1] do begin
  502. Format := fDepthFormat;
  503. Samples := [ VK_SAMPLE_COUNT_1_BIT ];
  504. LoadOp := VK_ATTACHMENT_LOAD_OP_CLEAR;
  505. StoreOp := VK_ATTACHMENT_STORE_OP_STORE;
  506. StencilLoadOp := VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  507. StencilStoreOp := VK_ATTACHMENT_STORE_OP_DONT_CARE;
  508. InitialLayout := VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  509. FinalLayout := VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  510. end;
  511. RenderPassFactory.Subpasses.Length := 1;
  512. with RenderPassFactory.Subpasses[0] do begin
  513. PipelineBindPoint := VK_PIPELINE_BIND_POINT_GRAPHICS;
  514. ColorAttachments.Length := 1;
  515. ColorAttachments[0].Attachment := 0;
  516. ColorAttachments[0].Layout := VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  517. DepthStencilAttachments.Length := 1;
  518. DepthStencilAttachments[0].Attachment := 1;
  519. DepthStencilAttachments[0].Layout := VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  520. end;
  521. RenderPassFactory.AllocHandler := fAllocHandler;
  522. fRenderPass := RenderPassFactory.CreateRenderPass;
  523. WriteLn(' handle: ', PtrUInt(fRenderPass.Handle));
  524. WriteLn(' done');
  525. finally
  526. FreeAndNil(RenderPassFactory);
  527. end;
  528. //////////////////////////////////////////////////////////////////////////////
  529. WriteLn('create pipeline cache');
  530. PipelineCacheFactory := TvkuPipelineCacheFactory.Create(fDevice);
  531. try
  532. fPipelineCache := PipelineCacheFactory.CreatePipelineCache;
  533. WriteLn(' handle: ', PtrUInt(fPipelineCache.Handle));
  534. WriteLn(' done');
  535. finally
  536. FreeAndNil(PipelineCacheFactory);
  537. end;
  538. //////////////////////////////////////////////////////////////////////////////
  539. WriteLn('create frame buffers');
  540. FrameBufferFactory := TvkuFrameBufferFactory.Create(fDevice);
  541. try
  542. SetLength(fFrameBuffers, Length(fImageViews));
  543. FrameBufferFactory.AllocHandler := fAllocHandler;
  544. FrameBufferFactory.RenderPass := fRenderPass.Handle;
  545. FrameBufferFactory.Width := SurfaceCapabilities.currentExtent.width;
  546. FrameBufferFactory.Height := SurfaceCapabilities.currentExtent.height;
  547. FrameBufferFactory.Layers := 1;
  548. FrameBufferFactory.Attachments.Length := 2;
  549. FrameBufferFactory.Attachments[1] := fDepthStencilImageView.Handle;
  550. for i := low(fFrameBuffers) to high(fFrameBuffers) do begin
  551. FrameBufferFactory.Attachments[0] := fImageViews[i].Handle;
  552. fFrameBuffers[i] := FrameBufferFactory.CreateFrameBuffer;
  553. WriteLn(' handle: ', PtrUInt(fFrameBuffers[i].Handle));
  554. end;
  555. WriteLn(' done');
  556. finally
  557. FreeAndNil(FrameBufferFactory);
  558. end;
  559. //////////////////////////////////////////////////////////////////////////////
  560. WriteLn('flush setup command buffer');
  561. SetupCommandBuffer.EndCommand;
  562. fQueue.Submit([], [], [ SetupCommandBuffer.Handle ], [], VK_INVALID_NDP_HANDLE);
  563. fQueue.WaitIdle;
  564. FreeAndNil(SetupCommandBuffer);
  565. WriteLn(' done');
  566. //////////////////////////////////////////////////////////////////////////////
  567. WriteLn('recreate setup command buffer');
  568. SetupCommandBuffer := TvkuCommandBuffer.Create(
  569. fCommandPool.AllocateCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY),
  570. true, fCommandPool.Handle, fDevice.DeviceCommands);
  571. SetupCommandBuffer.BeginCommand;
  572. WriteLn(' handle: ', PtrUInt(SetupCommandBuffer.Handle));
  573. WriteLn(' done');
  574. //////////////////////////////////////////////////////////////////////////////
  575. BufferFactory := TvkuBufferFactory.Create(fDevice);
  576. try
  577. WriteLn('create vertex data buffer');
  578. BufferFactory.Size := SizeOf(VertexData);
  579. BufferFactory.Usage := [ VK_BUFFER_USAGE_VERTEX_BUFFER_BIT ];
  580. fVertex.DataBuffer := BufferFactory.CreateBuffer;
  581. WriteLn(' buffer handle: ', PtrUInt(fVertex.DataBuffer.Handle));
  582. MemReq := fVertex.DataBuffer.GetMemoryRequirements;
  583. fVertex.DataMemory := TvkuDeviceMemory.Create(
  584. fDevice.AllocateMemory(
  585. MemReq.size,
  586. vkuGetMemoryTypeIndex(
  587. fPhyDevice.GetMemoryProperties,
  588. MemReq.memoryTypeBits,
  589. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT),
  590. @AllocCallbacks),
  591. true,
  592. fDevice.DeviceCommands,
  593. @AllocCallbacks);
  594. WriteLn(' memory handle: ', PtrUInt(fVertex.DataMemory.Handle));
  595. p := fVertex.DataMemory.Map(0, MemReq.size, 0);
  596. try
  597. Move(VertexData, p^, SizeOf(VertexData));
  598. finally
  599. fVertex.DataMemory.Unmap;
  600. end;
  601. fVertex.DataBuffer.BindMemory(fVertex.DataMemory.Handle, 0);
  602. WriteLn(' done');
  603. WriteLn('create vertex index buffer');
  604. BufferFactory.Size := SizeOf(IndexData);
  605. BufferFactory.Usage := [ VK_BUFFER_USAGE_INDEX_BUFFER_BIT ];
  606. fVertex.IndexBuffer := BufferFactory.CreateBuffer;
  607. WriteLn(' buffer handle: ', PtrUInt(fVertex.IndexBuffer.Handle));
  608. MemReq := fVertex.IndexBuffer.GetMemoryRequirements;
  609. fVertex.IndexMemory := TvkuDeviceMemory.Create(
  610. fDevice.AllocateMemory(
  611. MemReq.size,
  612. vkuGetMemoryTypeIndex(
  613. fPhyDevice.GetMemoryProperties,
  614. MemReq.memoryTypeBits,
  615. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT),
  616. @AllocCallbacks),
  617. true,
  618. fDevice.DeviceCommands,
  619. @AllocCallbacks);
  620. WriteLn(' memory handle: ', PtrUInt(fVertex.IndexMemory.Handle));
  621. p := fVertex.IndexMemory.Map(0, MemReq.size, 0);
  622. try
  623. Move(IndexData, p^, SizeOf(IndexData));
  624. finally
  625. fVertex.IndexMemory.Unmap;
  626. end;
  627. fVertex.IndexBuffer.BindMemory(fVertex.IndexMemory.Handle, 0);
  628. WriteLn(' done');
  629. WriteLn('create uniform buffer');
  630. BufferFactory.Size := SizeOf(IndexData);
  631. BufferFactory.Usage := [ VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT ];
  632. fUniform.Buffer := BufferFactory.CreateBuffer;
  633. WriteLn(' buffer handle: ', PtrUInt(fUniform.Buffer.Handle));
  634. MemReq := fUniform.Buffer.GetMemoryRequirements;
  635. fUniform.Memory := TvkuDeviceMemory.Create(
  636. fDevice.AllocateMemory(
  637. MemReq.size,
  638. vkuGetMemoryTypeIndex(
  639. fPhyDevice.GetMemoryProperties,
  640. MemReq.memoryTypeBits,
  641. VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT),
  642. @AllocCallbacks),
  643. true,
  644. fDevice.DeviceCommands,
  645. @AllocCallbacks);
  646. WriteLn(' memory handle: ', PtrUInt(fUniform.Memory.Handle));
  647. fUniform.Buffer.BindMemory(fUniform.Memory.Handle, 0);
  648. UpdateUniformBuffers;
  649. WriteLn(' done');
  650. finally
  651. FreeAndNil(BufferFactory);
  652. end;
  653. //////////////////////////////////////////////////////////////////////////////
  654. WriteLn('create descriptor set layout');
  655. DescSetLayoutFactory := TvkuDescriptorSetLayoutFactory.Create(fDevice);
  656. try
  657. DescSetLayoutFactory.Bindings.Length := 1;
  658. with DescSetLayoutFactory.Bindings[0] do begin
  659. Binding := 0; // binding 0 (Uniform Buffer/Vertex Shader)
  660. DescriptorType := VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  661. DescriptorCount := 1;
  662. StageFlags := [ VK_SHADER_STAGE_VERTEX_BIT ];
  663. end;
  664. DescSetLayoutFactory.AllocHandler := fAllocHandler;
  665. fDescSetLayout := DescSetLayoutFactory.CreateDescriptorSetLayout;
  666. WriteLn(' handle: ', PtrUInt(fDescSetLayout.Handle));
  667. WriteLn(' done');
  668. finally
  669. FreeAndNil(DescSetLayoutFactory);
  670. end;
  671. //////////////////////////////////////////////////////////////////////////////
  672. WriteLn('create pipeline layout');
  673. PipelineLayoutFactory := TvkuPipelineLayoutFactory.Create(fDevice);
  674. try
  675. PipelineLayoutFactory.AllocHandler := fAllocHandler;
  676. PipelineLayoutFactory.SetLayouts.Length := 1;
  677. PipelineLayoutFactory.SetLayouts[0] := fDescSetLayout.Handle;
  678. fPipelineLayout := PipelineLayoutFactory.CreatePipelineLayout;
  679. WriteLn(' handle: ', PtrUInt(fPipelineLayout.Handle));
  680. WriteLn(' done');
  681. finally
  682. FreeAndNil(PipelineLayoutFactory);
  683. end;
  684. //////////////////////////////////////////////////////////////////////////////
  685. WriteLn('create shader modules');
  686. ShaderModuleFactory := TvkuShaderModuleFactory.Create(fDevice);
  687. try
  688. ShaderModuleFactory.AllocHandler := fAllocHandler;
  689. ShaderModuleFactory.LoadSpvCode(ExtractFilePath(Application.ExeName) + '../../data/shaders/triangle.vert.spv');
  690. fVertexShader := ShaderModuleFactory.CreateShaderModule;
  691. WriteLn(' vertex handle: ', PtrUInt(fVertexShader.Handle));
  692. ShaderModuleFactory.LoadSpvCode(ExtractFilePath(Application.ExeName) + '../../data/shaders/triangle.frag.spv');
  693. fFragmentShader := ShaderModuleFactory.CreateShaderModule;
  694. WriteLn(' fragment handle: ', PtrUInt(fFragmentShader.Handle));
  695. WriteLn(' done');
  696. finally
  697. FreeAndNil(ShaderModuleFactory);
  698. end;
  699. //////////////////////////////////////////////////////////////////////////////
  700. WriteLn('create graphics pipeline');
  701. PipelineFactory := TvkuGraphicsPipelineFactory.Create(fDevice);
  702. try
  703. PipelineFactory.AllocHandler := fAllocHandler;
  704. PipelineFactory.Stages.Length := 2;
  705. with PipelineFactory.Stages[0] do begin
  706. Stage := [ VK_SHADER_STAGE_VERTEX_BIT ];
  707. Module := fVertexShader.Handle;
  708. Name := 'main';
  709. end;
  710. with PipelineFactory.Stages[1] do begin
  711. Stage := [ VK_SHADER_STAGE_FRAGMENT_BIT ];
  712. Module := fFragmentShader.Handle;
  713. Name := 'main';
  714. end;
  715. with PipelineFactory.VertexInputState do begin
  716. VertexBindingDescriptions.Length := 1;
  717. VertexBindingDescriptions[0].Binding := VERTEX_BUFFER_BIND_ID;
  718. VertexBindingDescriptions[0].Stride := SizeOf(TVertex);
  719. VertexBindingDescriptions[0].InputRate := VK_VERTEX_INPUT_RATE_VERTEX;
  720. VertexAttributeDescriptions.Length := 2;
  721. // Location 0: Position
  722. VertexAttributeDescriptions[0].Binding := VERTEX_BUFFER_BIND_ID;
  723. VertexAttributeDescriptions[0].Location := 0;
  724. VertexAttributeDescriptions[0].Format := VK_FORMAT_R32G32B32_SFLOAT;
  725. VertexAttributeDescriptions[0].Offset := 0;
  726. VertexAttributeDescriptions[0].Binding := 0;
  727. // Location 1: Color
  728. VertexAttributeDescriptions[1].Binding := VERTEX_BUFFER_BIND_ID;
  729. VertexAttributeDescriptions[1].Location := 1;
  730. VertexAttributeDescriptions[1].Format := VK_FORMAT_R32G32B32_SFLOAT;
  731. VertexAttributeDescriptions[1].Offset := 3 * SizeOf(VkFloat);
  732. VertexAttributeDescriptions[1].Binding := 0;
  733. end;
  734. with PipelineFactory.InputAssemblyState do begin
  735. Topology := VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
  736. end;
  737. with PipelineFactory.RasterizationState do begin
  738. PolygonMode := VK_POLYGON_MODE_FILL;
  739. CullMode := VK_CULL_MODE_NONE;
  740. FrontFace := VK_FRONT_FACE_COUNTER_CLOCKWISE;
  741. DepthClampEnable := false;
  742. RasterizerDiscardEnable := false;
  743. DepthBiasEnable := false;
  744. end;
  745. with PipelineFactory.ColorBlendState do begin
  746. Attachments.Length := 1;
  747. Attachments[0].ColorWriteMask := [
  748. VK_COLOR_COMPONENT_R_BIT,
  749. VK_COLOR_COMPONENT_G_BIT,
  750. VK_COLOR_COMPONENT_B_BIT,
  751. VK_COLOR_COMPONENT_A_BIT];
  752. Attachments[0].BlendEnable := false;
  753. end;
  754. with PipelineFactory.ViewportState do begin
  755. Viewports.Length := 1;
  756. Scissors.Length := 1;
  757. end;
  758. with PipelineFactory.DynamicState do begin
  759. DynamicStates.Length := 2;
  760. DynamicStates[0] := VK_DYNAMIC_STATE_VIEWPORT;
  761. DynamicStates[1] := VK_DYNAMIC_STATE_SCISSOR;
  762. end;
  763. with PipelineFactory.DepthStencilState do begin
  764. DepthTestEnable := true;
  765. DepthWriteEnable := true;
  766. DepthCompareOp := VK_COMPARE_OP_LESS_OR_EQUAL;
  767. DepthBoundsTestEnable := false;
  768. StencilTestEnable := false;
  769. Back.failOp := VK_STENCIL_OP_KEEP;
  770. Back.passOp := VK_STENCIL_OP_KEEP;
  771. Back.compareOp := VK_COMPARE_OP_ALWAYS;
  772. Front := Back;
  773. end;
  774. with PipelineFactory.MultiSampleState do begin
  775. RasterizationSamples := [ VK_SAMPLE_COUNT_1_BIT ];
  776. end;
  777. PipelineFactory.Layout := fPipelineLayout.Handle;
  778. PipelineFactory.RenderPass := fRenderPass.Handle;
  779. PipelineFactory.SubPass := 0;
  780. fPipeline := PipelineFactory.CreateGraphicsPipeline(VK_INVALID_NDP_HANDLE);
  781. WriteLn(' handle: ', PtrUInt(fPipeline.Handle));
  782. WriteLn(' done');
  783. finally
  784. FreeAndNil(PipelineFactory);
  785. end;
  786. //////////////////////////////////////////////////////////////////////////////
  787. WriteLn('create descriptor pool');
  788. DescriptorPoolFactory := TvkuDescriptorPoolFactory.Create(fDevice.DeviceCommands);
  789. try
  790. DescriptorPoolFactory.MaxSets := 1;
  791. DescriptorPoolFactory.PoolSizes.Length := 1;
  792. DescriptorPoolFactory.PoolSizes[0].DescriptorType := VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  793. DescriptorPoolFactory.PoolSizes[0].DescriptorCount := 1;
  794. fDescriptorPool := DescriptorPoolFactory.CreateDescriptorPool;
  795. WriteLn(' handle: ', PtrUInt(fDescriptorPool.Handle));
  796. WriteLn(' done');
  797. finally
  798. FreeAndNil(DescriptorPoolFactory);
  799. end;
  800. //////////////////////////////////////////////////////////////////////////////
  801. WriteLn('setup/update descriptor sets');
  802. fDescriptorSet := TvkuDescriptorSet.Create(
  803. fDescriptorPool.AllocateDescriptorSet(fDescSetLayout.Handle),
  804. true,
  805. fDescriptorPool.Handle,
  806. fDevice.DeviceCommands);
  807. WriteLn(' handle: ', PtrUInt(fDescriptorSet.Handle));
  808. WriteLn(' update descriptor set');
  809. with fDevice.UpdateDescriptorSet do
  810. try
  811. WriteDescriptorSets.Length := 1;
  812. WriteDescriptorSets[0].DstSet := fDescriptorSet.Handle;
  813. WriteDescriptorSets[0].DstBinding := 0;
  814. WriteDescriptorSets[0].DescriptorType := VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
  815. WriteDescriptorSets[0].BufferInfos.Length := 1;
  816. WriteDescriptorSets[0].BufferInfos[0].Buffer := fUniform.Buffer.Handle;
  817. WriteDescriptorSets[0].BufferInfos[0].Offset := 0;
  818. WriteDescriptorSets[0].BufferInfos[0].Range := SizeOf(fUniform.Values);
  819. Execute;
  820. finally
  821. Free;
  822. end;
  823. WriteLn(' done');
  824. //////////////////////////////////////////////////////////////////////////////
  825. WriteLn('build command buffers');
  826. for i := low(fDrawCommandBuffers) to high(fDrawCommandBuffers) do begin
  827. WriteLn(' command buffer: ', PtrUInt(fDrawCommandBuffers[i].Handle));
  828. with fDrawCommandBuffers[i] do begin
  829. BeginCommand;
  830. with BeginRenderPass do
  831. try
  832. RenderPassBeginInfo.RenderPass := fRenderPass.Handle;
  833. RenderPassBeginInfo.Framebuffer := fFrameBuffers[i].Handle;
  834. RenderPassBeginInfo.RenderArea.offset.x := 0;
  835. RenderPassBeginInfo.RenderArea.offset.y := 0;
  836. RenderPassBeginInfo.RenderArea.extent.width := ClientWidth;
  837. RenderPassBeginInfo.RenderArea.extent.height := ClientHeight;
  838. RenderPassBeginInfo.ClearValues.Length := 2;
  839. RenderPassBeginInfo.ClearValues[0] := ClearColor;
  840. RenderPassBeginInfo.ClearValues[1] := ClearDepthStencil;
  841. Execute(VK_SUBPASS_CONTENTS_INLINE);
  842. finally
  843. Free;
  844. end;
  845. FillByte(vp, SizeOf(vp), 0);
  846. vp.height := ClientHeight;
  847. vp.width := ClientWidth;
  848. vp.minDepth := 0.0;
  849. vp.maxDepth := 1.0;
  850. SetViewport(0, [ vp ]);
  851. FillByte(r2D, SizeOf(r2D), 0);
  852. r2D.extent.width := ClientWidth;
  853. r2D.extent.height := ClientHeight;
  854. r2D.offset.x := 0;
  855. r2D.offset.y := 0;
  856. SetScissors(1, [ r2D ]);
  857. BindDescriptorSet(
  858. VK_PIPELINE_BIND_POINT_GRAPHICS,
  859. fPipelineLayout.Handle,
  860. 0,
  861. [ fDescriptorSet.Handle ],
  862. [ ]);
  863. BindPipeline(
  864. VK_PIPELINE_BIND_POINT_GRAPHICS,
  865. fPipeline.Handle);
  866. BindVertexBuffers(
  867. VERTEX_BUFFER_BIND_ID,
  868. [ fVertex.DataBuffer.Handle ],
  869. [ 0 ]);
  870. BindIndexBuffers(
  871. fVertex.IndexBuffer.Handle,
  872. 0,
  873. VK_INDEX_TYPE_UINT32);
  874. DrawIndexed(
  875. 3, 1, 0, 0, 1);
  876. FillByte(ImageMemoryBarrier, SizeOf(ImageMemoryBarrier), 0);
  877. with ImageMemoryBarrier do begin
  878. sType := VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  879. pNext := nil;
  880. srcAccessMask := [ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ];
  881. dstAccessMask := [ ];
  882. oldLayout := VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  883. newLayout := VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  884. srcQueueFamilyIndex := VK_QUEUE_FAMILY_IGNORED;
  885. dstQueueFamilyIndex := VK_QUEUE_FAMILY_IGNORED;
  886. subresourceRange.aspectMask := [ VK_IMAGE_ASPECT_COLOR_BIT ];
  887. subresourceRange.baseMipLevel := 0;
  888. subresourceRange.levelCount := 1;
  889. subresourceRange.baseArrayLayer := 0;
  890. subresourceRange.layerCount := 1;
  891. end;
  892. PipelineBarrier(
  893. [ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT ],
  894. [ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT ],
  895. [],
  896. [],
  897. [],
  898. [ ImageMemoryBarrier ]);
  899. EndCommand;
  900. end;
  901. end;
  902. WriteLn(' done');
  903. finally
  904. FreeAndNil(SetupCommandBuffer);
  905. end;
  906. end;
  907. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  908. procedure TMainForm.ApplicationPropertiesIdle(Sender: TObject; var Done: Boolean);
  909. begin
  910. Render;
  911. end;
  912. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  913. procedure TMainForm.FormDestroy(Sender: TObject);
  914. procedure FreeAndNilFrameBuffers;
  915. var i: Integer;
  916. begin
  917. for i := Low(fFrameBuffers) to High(fFrameBuffers) do
  918. FreeAndNil(fFrameBuffers[i]);
  919. SetLength(fFrameBuffers, 0);
  920. end;
  921. procedure FreeAndNilImages;
  922. var i: Integer;
  923. begin
  924. for i := low(fImages) to high(fImages) do
  925. FreeAndNil(fImages[i]);
  926. SetLength(fImages, 0);
  927. end;
  928. procedure FreeAndNilImageViews;
  929. var i: Integer;
  930. begin
  931. for i := Low(fImageViews) to High(fImageViews) do
  932. FreeAndNil(fImageViews[i]);
  933. SetLength(fImageViews, 0);
  934. end;
  935. procedure FreeAndNilDrawCommandBuffers;
  936. var i: Integer;
  937. begin
  938. for i := Low(fDrawCommandBuffers) to High(fDrawCommandBuffers) do
  939. FreeAndNil(fDrawCommandBuffers[i]);
  940. SetLength(fDrawCommandBuffers, 0);
  941. end;
  942. begin
  943. FreeAndNil(fDescriptorSet);
  944. FreeAndNil(fDescriptorPool);
  945. FreeAndNil(fPipeline);
  946. FreeAndNil(fFragmentShader);
  947. FreeAndNil(fVertexShader);
  948. FreeAndNil(fPipelineLayout);
  949. FreeAndNil(fDescSetLayout);
  950. FreeAndNil(fUniform.Buffer);
  951. FreeAndNil(fUniform.Memory);
  952. FreeAndNil(fVertex.DataBuffer);
  953. FreeAndNil(fVertex.DataMemory);
  954. FreeAndNil(fVertex.IndexBuffer);
  955. FreeAndNil(fVertex.IndexMemory);
  956. FreeAndNilFrameBuffers;
  957. FreeAndNil(fPipelineCache);
  958. FreeAndNil(fRenderPass);
  959. FreeAndNil(fDepthStencilImageView);
  960. FreeAndNil(fDepthStencilImage);
  961. FreeAndNil(fPostPresentCommandBuffer);
  962. FreeAndNilDrawCommandBuffers;
  963. FreeAndNilImageViews;
  964. FreeAndNilImages;
  965. FreeAndNil(fSwapChain);
  966. FreeAndNil(fCommandPool);
  967. FreeAndNil(fSurface);
  968. FreeAndNil(fQueue);
  969. FreeAndNil(fDevice);
  970. FreeAndNil(fPhyDevice);
  971. FreeAndNil(fDebugReporter);
  972. FreeAndNil(fInstance);
  973. FreeAndNil(fAllocHandler);
  974. FreeAndNil(fCamera);
  975. end;
  976. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  977. procedure TMainForm.UpdateUniformBuffers;
  978. var p: PVkVoid;
  979. begin
  980. fCamera.Perspective(45, ClientWidth/ClientHeight, 0.001, 1000);
  981. fCamera.Position := gluMatrixIdentity * gluMatrixTranslate(gluVector3f(0, 0, -5));
  982. fUniform.Values.ProjectionMat := fCamera.ProjMatrix;
  983. fUniform.Values.ModelMatrix := fCamera.Position;
  984. fUniform.Values.ViewMatrix := gluMatrixIdentity;
  985. p := fUniform.Memory.Map(0, SizeOf(fUniform.Values), 0);
  986. try
  987. move(fUniform.Values, p^, SizeOf(fUniform.Values));
  988. finally
  989. fUniform.Memory.Unmap;
  990. end;
  991. end;
  992. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  993. procedure TMainForm.Render;
  994. var
  995. Semaphore: TvkuSemaphore;
  996. AllocCallbacks: TVkAllocationCallbacks;
  997. CurrentImage: VkUint32;
  998. PostPresentBarrier: TVkImageMemoryBarrier;
  999. begin
  1000. fDevice.WaitIdle;
  1001. // present queue
  1002. AllocCallbacks := fAllocHandler.GetStructure;
  1003. Semaphore := TvkuSemaphore.Create(
  1004. VkSemaphoreCreateFlags([ ]),
  1005. fDevice.DeviceCommands,
  1006. @AllocCallbacks);
  1007. try
  1008. CurrentImage := fSwapChain.AcquireNextImage(High(VkUint64), Semaphore.Handle, VK_INVALID_NDP_HANDLE);
  1009. fQueue.Submit(
  1010. [ Semaphore.Handle ],
  1011. [ ],
  1012. [ fDrawCommandBuffers[CurrentImage].Handle ],
  1013. [ ],
  1014. VK_INVALID_NDP_HANDLE);
  1015. fQueue.Present(
  1016. [ ],
  1017. [ fSwapChain.Handle ],
  1018. [ CurrentImage ]);
  1019. finally
  1020. FreeAndNil(Semaphore);
  1021. end;
  1022. // post present image
  1023. PostPresentBarrier := fImages[CurrentImage].GetMemoryBarrier(
  1024. [ VK_IMAGE_ASPECT_COLOR_BIT ],
  1025. VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
  1026. VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
  1027. PostPresentBarrier.srcAccessMask := [];
  1028. PostPresentBarrier.dstAccessMask := [ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ];
  1029. fPostPresentCommandBuffer.BeginCommand;
  1030. try
  1031. fPostPresentCommandBuffer.PipelineBarrier(
  1032. [ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT ],
  1033. [ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT ],
  1034. [ ],
  1035. [ ],
  1036. [ ],
  1037. [ PostPresentBarrier ]);
  1038. finally
  1039. fPostPresentCommandBuffer.EndCommand;
  1040. end;
  1041. // submit queue
  1042. fQueue.Submit(
  1043. [ ],
  1044. [ ],
  1045. [ fPostPresentCommandBuffer.Handle ],
  1046. [ ],
  1047. VK_INVALID_NDP_HANDLE);
  1048. fQueue.WaitIdle;
  1049. fDevice.WaitIdle;
  1050. end;
  1051. end.