From 68b70540ae39232c922bfc56da3a551fbed129c3 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Thu, 31 Mar 2016 22:13:11 +0200 Subject: [PATCH] * implemented pipeline cache * created command buffers for rendering * created depth stencil buffer/image --- projects/triangle/triangle.lpi | 10 +- projects/triangle/triangle.lpr | 2 +- projects/triangle/triangle.lps | 408 +++++----- projects/triangle/uMainForm.pas | 813 ++++++++++++-------- projects/utils/VulkanUtils.pas | 34 +- projects/utils/uvkuAllocationHandler.pas | 4 +- projects/utils/uvkuCommandBuffer.pas | 35 +- projects/utils/uvkuDebugReporter.pas | 2 +- projects/utils/uvkuDevice.pas | 40 +- projects/utils/uvkuFactoryBase.pas | 2 +- projects/utils/uvkuImage.pas | 65 +- projects/utils/uvkuPipelineCache.pas | 82 ++ projects/utils/uvkuPipelineCacheFactory.pas | 65 ++ projects/utils/uvkuQueue.pas | 49 ++ projects/utils/uvkuTypes.pas | 3 + 15 files changed, 1079 insertions(+), 535 deletions(-) create mode 100644 projects/utils/uvkuPipelineCache.pas create mode 100644 projects/utils/uvkuPipelineCacheFactory.pas diff --git a/projects/triangle/triangle.lpi b/projects/triangle/triangle.lpi index 8a68b03..eda8166 100644 --- a/projects/triangle/triangle.lpi +++ b/projects/triangle/triangle.lpi @@ -33,7 +33,7 @@ - + @@ -213,6 +213,14 @@ + + + + + + + + diff --git a/projects/triangle/triangle.lpr b/projects/triangle/triangle.lpr index 49b8a7b..69901a7 100644 --- a/projects/triangle/triangle.lpr +++ b/projects/triangle/triangle.lpr @@ -8,7 +8,7 @@ uses cthreads, {$ENDIF}{$ENDIF} SysUtils, Interfaces, Dialogs, Forms, - uMainForm, Vulkan, uvkuDebugReporter; + uMainForm, Vulkan, uvkuDebugReporter, uvkuPipelineCache, uvkuPipelineCacheFactory; {$R *.res} diff --git a/projects/triangle/triangle.lps b/projects/triangle/triangle.lps index 6596f79..0a052d6 100644 --- a/projects/triangle/triangle.lps +++ b/projects/triangle/triangle.lps @@ -4,13 +4,13 @@ - + - + @@ -19,25 +19,33 @@ - - - - + + + + + + + + + + + + - - - + + + - + @@ -45,7 +53,7 @@ - + @@ -53,7 +61,7 @@ - + @@ -61,23 +69,24 @@ - + - - - + + + - - - - + + + + + @@ -85,7 +94,7 @@ - + @@ -93,7 +102,7 @@ - + @@ -101,14 +110,14 @@ - + - + - + @@ -117,7 +126,7 @@ - + @@ -125,7 +134,7 @@ - + @@ -133,32 +142,33 @@ - + - - - - + + + + + - - - - + + + + - - - - + + + + @@ -166,23 +176,25 @@ - + - - - - + + + + + - - - - + + + + + @@ -190,7 +202,7 @@ - + @@ -198,57 +210,58 @@ - + - + - - - - + + + + - + - + - - - - + + + + - - - - + + + + + - - - - + + + + @@ -256,29 +269,30 @@ - + - + - + - + - - + + + @@ -286,7 +300,7 @@ - + @@ -294,14 +308,14 @@ - + - + @@ -309,7 +323,7 @@ - + @@ -317,7 +331,7 @@ - + @@ -325,7 +339,7 @@ - + @@ -333,7 +347,7 @@ - + @@ -341,7 +355,7 @@ - + @@ -349,7 +363,7 @@ - + @@ -357,280 +371,298 @@ - + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - - + + + - - - - + + + + - + + + + + + + + + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - - + + - + - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + - - + + - - + + - + - - + + - - + + - - + + diff --git a/projects/triangle/uMainForm.pas b/projects/triangle/uMainForm.pas index dc5ded3..fc6a091 100644 --- a/projects/triangle/uMainForm.pas +++ b/projects/triangle/uMainForm.pas @@ -28,6 +28,7 @@ type fPresentQueueNodeIndex: VkUint32; fSurfaceFormat: TVkFormat; fSurfaceColorSpace: TVkColorSpaceKHR; + fDepthFormat: TVkFormat; fAllocHandler: TCustomAllocHandler; fDebugReporter: TvkuConsoleDebugReporter; @@ -37,6 +38,7 @@ type fQueue: TvkuQueue; fSurface: TvkuSurface; fSwapChain: TvkuSwapChain; + fImages: array of TvkuImage; fImageViews: array of TvkuImageView; fRenderPass: TvkuRenderPass; fFrameBuffers: array of TvkuFrameBuffer; @@ -46,7 +48,11 @@ type fFragmentShader: TvkuShaderModule; fPipeline: TvkuGraphicsPipeline; fCommandPool: TvkuCommandPool; - fCommandBuffer: TvkuCommandBuffer; + fDrawCommandBuffers: array of TvkuCommandBuffer; + fPostPresentCommandBuffer: TvkuCommandBuffer; + fDepthStencilImage: TvkuImage; + fDepthStencilImageView: TvkuImageView; + fPipelineCache: TvkuPipelineCache; end; var @@ -93,6 +99,7 @@ var SurfaceFactory: TvkuSurfaceFactory; CommandPoolFactory: TvkuCommandPoolFactory; SwapChainFactory: TvkuSwapChainFactory; + ImageFactory: TvkuImageFactory; ImageViewFactory: TvkuImageViewFactory; RenderPassFactory: TvkuRenderPassFactory; FrameBufferFactory: TvkuFrameBufferFactory; @@ -100,9 +107,10 @@ var PipelineLayoutFactory: TvkuPipelineLayoutFactory; ShaderModuleFactory: TvkuShaderModuleFactory; PipelineFactory: TvkuGraphicsPipelineFactory; + PipelineCacheFactory: TvkuPipelineCacheFactory; + SetupCommandBuffer: TvkuCommandBuffer; QueueFamProps: TVkQueueFamilyPropertiesArr; - DepthFormat: TVkFormat; f: TVkFormat; i: Integer; SrfFormats: TVkSurfaceFormatArr; @@ -110,385 +118,495 @@ var PresentModes: TVkPresentModeArr; pm: TVkPresentModeKHR; Images: TVkImageArr; - ComponentMapping: TVkComponentMapping; + AllocCallbacks: TVkAllocationCallbacks; + ImageMemoryBarrier: TVkImageMemoryBarrier; + CommandBuffers: TVkCommandBufferArr; begin - fAllocHandler := TCustomAllocHandler.Create; - - ////////////////////////////////////////////////////////////////////////////// - WriteLn('create instance: '); - InstanceFactory := TvkuInstanceFactory.Create; try - InstanceFactory.AllocHandler := fAllocHandler; - InstanceFactory.EnabledExtensionNames.Add(VK_KHR_SURFACE_EXTENSION_NAME); - InstanceFactory.EnabledExtensionNames.Add(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); - InstanceFactory.EnabledExtensionNames.Add(TvkuSurface.GetPlatformSurfaceExtensionName); - fInstance := InstanceFactory.CreateInstance; - WriteLn(' handle: ', PtrUInt(fInstance.Handle)); - WriteLn(' done'); - finally - FreeAndNil(InstanceFactory); - end; - - fDebugReporter := TvkuConsoleDebugReporter.Create(fInstance.InstanceCommands, fAllocHandler); - - ////////////////////////////////////////////////////////////////////////////// - WriteLn('find suitable physical device'); - PhyDevices := fInstance.GetPhysicalDevices; - if (Length(PhyDevices) <= 0) then - raise TvkuException.Create('unable to get physical device'); - fPhyDevice := TvkuPhysicalDevice.Create(PhyDevices[0], fInstance.InstanceCommands); - WriteLn(' handle: ', PtrUInt(fPhyDevice.Handle)); - - Write(' find suitable graphics queue index... '); - QueueFamProps := fPhyDevice.GetQueueFamilyProperties; - fGraphicsQueueFamilyIndex := high(fGraphicsQueueFamilyIndex); - for i := low(QueueFamProps) to high(QueueFamProps) do begin - if (VK_QUEUE_GRAPHICS_BIT in QueueFamProps[i].queueFlags) then begin - fGraphicsQueueFamilyIndex := i; - WriteLn(fGraphicsQueueFamilyIndex); - break; - end; - end; - if (fGraphicsQueueFamilyIndex = high(fGraphicsQueueFamilyIndex)) then - raise TvkuException.Create('unable to find graphics queue index'); - - Write(' find suitable depth format... '); - f := VK_FORMAT_UNDEFINED; - for f in [ VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D16_UNORM ] do begin - if (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT in fPhyDevice.GetFormatProperties(f).optimalTilingFeatures) then begin - DepthFormat := f; - break; + fAllocHandler := TCustomAllocHandler.Create; + AllocCallbacks := fAllocHandler.GetStructure; + + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create instance: '); + InstanceFactory := TvkuInstanceFactory.Create; + try + InstanceFactory.AllocHandler := fAllocHandler; + InstanceFactory.EnabledExtensionNames.Add(VK_KHR_SURFACE_EXTENSION_NAME); + InstanceFactory.EnabledExtensionNames.Add(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); + InstanceFactory.EnabledExtensionNames.Add(TvkuSurface.GetPlatformSurfaceExtensionName); + fInstance := InstanceFactory.CreateInstance; + WriteLn(' handle: ', PtrUInt(fInstance.Handle)); + WriteLn(' done'); + finally + FreeAndNil(InstanceFactory); end; - end; - WriteLn(DepthFormat); - WriteLn(' done'); - ////////////////////////////////////////////////////////////////////////////// - WriteLn('create device'); - DeviceFactory := TvkuDeviceFactory.Create(fInstance); - try - DeviceFactory.AllocHandler := fAllocHandler; - DeviceFactory.EnabledExtensions.Add('VK_KHR_swapchain'); - DeviceFactory.QueueCreateInfos.Length := 1; - with DeviceFactory.QueueCreateInfos[0] do begin - Flags := 0; - QueueFamilyIndex := fGraphicsQueueFamilyIndex; - QueuePriorities.Length := 1; - QueuePriorities[0] := 1.0; - end; - fDevice := DeviceFactory.CreateDevice(fPhyDevice.Handle); - WriteLn(' handle: ', PtrUInt(fDevice.Handle)); - WriteLn(' done'); - finally - FreeAndNil(DeviceFactory); - end; + fDebugReporter := TvkuConsoleDebugReporter.Create(fInstance.InstanceCommands, fAllocHandler); - ////////////////////////////////////////////////////////////////////////////// - WriteLn('find suitable queue'); - fQueue := TvkuQueue.Create(fDevice.GetQueue(fGraphicsQueueFamilyIndex, 0), fDevice.DeviceCommands); - WriteLn(' handle: ', PtrUInt(fQueue.Handle)); - WriteLn(' done'); + ////////////////////////////////////////////////////////////////////////////// + WriteLn('find suitable physical device'); + PhyDevices := fInstance.GetPhysicalDevices; + if (Length(PhyDevices) <= 0) then + raise TvkuException.Create('unable to get physical device'); + fPhyDevice := TvkuPhysicalDevice.Create(PhyDevices[0], fInstance.InstanceCommands); + WriteLn(' handle: ', PtrUInt(fPhyDevice.Handle)); - ////////////////////////////////////////////////////////////////////////////// - WriteLn('create surface: '); - SurfaceFactory := TvkuSurfaceFactory.Create(fInstance); - try - SurfaceFactory.AllocHandler := fAllocHandler; - SurfaceFactory.WinControl := RenderPanel; - fSurface := SurfaceFactory.CreateSurface; - WriteLn(' handle: ', PtrUInt(fSurface.Handle)); - - WriteLn(' find suitable graphics and present queue node index'); - fGraphicsQueueNodeIndex := high(fGraphicsQueueNodeIndex); - fPresentQueueNodeIndex := high(fPresentQueueNodeIndex); - QueueFamProps := fPhyDevice.GetQueueFamilyProperties; + Write(' find suitable graphics queue index... '); + QueueFamProps := fPhyDevice.GetQueueFamilyProperties; + fGraphicsQueueFamilyIndex := high(fGraphicsQueueFamilyIndex); for i := low(QueueFamProps) to high(QueueFamProps) do begin - if (VK_QUEUE_GRAPHICS_BIT in QueueFamProps[i].queueFlags) then - fGraphicsQueueNodeIndex := i; - - if fPhyDevice.GetSurfaceSupport(i, fSurface.Handle) then begin - fGraphicsQueueNodeIndex := i; - fPresentQueueNodeIndex := i; + if (VK_QUEUE_GRAPHICS_BIT in QueueFamProps[i].queueFlags) then begin + fGraphicsQueueFamilyIndex := i; + WriteLn(fGraphicsQueueFamilyIndex); break; end; end; - if (fPresentQueueNodeIndex = high(fPresentQueueNodeIndex)) then begin - for i := low(QueueFamProps) to high(QueueFamProps) do begin - if fPhyDevice.GetSurfaceSupport(i, fSurface.Handle) then begin - fPresentQueueNodeIndex := i; - break; - end; + if (fGraphicsQueueFamilyIndex = high(fGraphicsQueueFamilyIndex)) then + raise TvkuException.Create('unable to find graphics queue index'); + + Write(' find suitable depth format... '); + f := VK_FORMAT_UNDEFINED; + for f in [ VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D16_UNORM ] do begin + if (VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT in fPhyDevice.GetFormatProperties(f).optimalTilingFeatures) then begin + fDepthFormat := f; + break; end; end; - WriteLn(' graphics queue node index: ', fGraphicsQueueNodeIndex); - WriteLn(' present queue node index: ', fPresentQueueNodeIndex); - if (fGraphicsQueueNodeIndex = high(fGraphicsQueueNodeIndex)) or - (fPresentQueueNodeIndex = high(fPresentQueueNodeIndex)) or - (fPresentQueueNodeIndex <> fGraphicsQueueNodeIndex) then - raise TvkuException.Create('different graphic and present queue node index is not supported yet'); - - WriteLn(' find suitable image format'); - SrfFormats := fPhyDevice.GetSurfaceFormats(fSurface.Handle); - if (Length(SrfFormats) = 0) then - raise TvkuException.Create('no suitable formats found'); - if (Length(SrfFormats) = 1) and (SrfFormats[0].format = VK_FORMAT_UNDEFINED) then begin - fSurfaceFormat := VK_FORMAT_R8G8B8A8_UNORM; - fSurfaceColorSpace := VK_COLORSPACE_SRGB_NONLINEAR_KHR; - end else begin - fSurfaceFormat := SrfFormats[0].format; - fSurfaceColorSpace := SrfFormats[0].colorSpace; + WriteLn(fDepthFormat); + WriteLn(' done'); + + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create device'); + DeviceFactory := TvkuDeviceFactory.Create(fInstance); + try + DeviceFactory.AllocHandler := fAllocHandler; + DeviceFactory.EnabledExtensions.Add('VK_KHR_swapchain'); + DeviceFactory.QueueCreateInfos.Length := 1; + with DeviceFactory.QueueCreateInfos[0] do begin + Flags := 0; + QueueFamilyIndex := fGraphicsQueueFamilyIndex; + QueuePriorities.Length := 1; + QueuePriorities[0] := 1.0; + end; + fDevice := DeviceFactory.CreateDevice(fPhyDevice.Handle); + WriteLn(' handle: ', PtrUInt(fDevice.Handle)); + WriteLn(' done'); + finally + FreeAndNil(DeviceFactory); end; - WriteLn(' format: ', fSurfaceFormat); - WriteLn(' color space: ', fSurfaceColorSpace); + ////////////////////////////////////////////////////////////////////////////// + WriteLn('find suitable queue'); + fQueue := TvkuQueue.Create(fDevice.GetQueue(fGraphicsQueueFamilyIndex, 0), fDevice.DeviceCommands); + WriteLn(' handle: ', PtrUInt(fQueue.Handle)); WriteLn(' done'); - finally - FreeAndNil(SurfaceFactory); - end; - ////////////////////////////////////////////////////////////////////////////// - WriteLn('create command pool'); - CommandPoolFactory := TvkuCommandPoolFactory.Create(fDevice); - try - CommandPoolFactory.Flags := [ VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT ]; - CommandPoolFactory.QueueFamilyIndex := fGraphicsQueueNodeIndex; - fCommandPool := CommandPoolFactory.CreateCommandPool; - WriteLn(' handle: ', PtrUInt(fCommandPool.Handle)); + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create surface: '); + SurfaceFactory := TvkuSurfaceFactory.Create(fInstance); + try + SurfaceFactory.AllocHandler := fAllocHandler; + SurfaceFactory.WinControl := RenderPanel; + fSurface := SurfaceFactory.CreateSurface; + WriteLn(' handle: ', PtrUInt(fSurface.Handle)); + + WriteLn(' find suitable graphics and present queue node index'); + fGraphicsQueueNodeIndex := high(fGraphicsQueueNodeIndex); + fPresentQueueNodeIndex := high(fPresentQueueNodeIndex); + QueueFamProps := fPhyDevice.GetQueueFamilyProperties; + for i := low(QueueFamProps) to high(QueueFamProps) do begin + if (VK_QUEUE_GRAPHICS_BIT in QueueFamProps[i].queueFlags) then + fGraphicsQueueNodeIndex := i; - WriteLn(' alloc command buffer'); - fCommandBuffer := TvkuCommandBuffer.Create( - fCommandPool.CreateCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY), - true, fCommandPool.Handle, fDevice.DeviceCommands); - WriteLn(' handle: ', PtrUInt(fCommandBuffer.Handle)); - WriteLn(' done'); - finally - FreeAndNil(CommandPoolFactory); - end; + if fPhyDevice.GetSurfaceSupport(i, fSurface.Handle) then begin + fGraphicsQueueNodeIndex := i; + fPresentQueueNodeIndex := i; + break; + end; + end; + if (fPresentQueueNodeIndex = high(fPresentQueueNodeIndex)) then begin + for i := low(QueueFamProps) to high(QueueFamProps) do begin + if fPhyDevice.GetSurfaceSupport(i, fSurface.Handle) then begin + fPresentQueueNodeIndex := i; + break; + end; + end; + end; + WriteLn(' graphics queue node index: ', fGraphicsQueueNodeIndex); + WriteLn(' present queue node index: ', fPresentQueueNodeIndex); + if (fGraphicsQueueNodeIndex = high(fGraphicsQueueNodeIndex)) or + (fPresentQueueNodeIndex = high(fPresentQueueNodeIndex)) or + (fPresentQueueNodeIndex <> fGraphicsQueueNodeIndex) then + raise TvkuException.Create('different graphic and present queue node index is not supported yet'); + + WriteLn(' find suitable image format'); + SrfFormats := fPhyDevice.GetSurfaceFormats(fSurface.Handle); + if (Length(SrfFormats) = 0) then + raise TvkuException.Create('no suitable formats found'); + if (Length(SrfFormats) = 1) and (SrfFormats[0].format = VK_FORMAT_UNDEFINED) then begin + fSurfaceFormat := VK_FORMAT_R8G8B8A8_UNORM; + fSurfaceColorSpace := VK_COLORSPACE_SRGB_NONLINEAR_KHR; + end else begin + fSurfaceFormat := SrfFormats[0].format; + fSurfaceColorSpace := SrfFormats[0].colorSpace; + end; + WriteLn(' format: ', fSurfaceFormat); + WriteLn(' color space: ', fSurfaceColorSpace); - ////////////////////////////////////////////////////////////////////////////// - WriteLn('create swap chain'); - SwapChainFactory := TvkuSwapChainFactory.Create(fDevice); - try - SwapChainFactory.AllocHandler := fAllocHandler; - SwapChainFactory.Surface := fSurface.Handle; - SwapChainFactory.ImageUsage := [ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ]; - SwapChainFactory.ImageArrayLayers := 1; - SwapChainFactory.ImageSharingMode := VK_SHARING_MODE_EXCLUSIVE; - SwapChainFactory.Clipped := true; - SwapChainFactory.ComposideAlpha := [ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR ]; - SwapChainFactory.ImageFormat := fSurfaceFormat; - SwapChainFactory.ImageColorSpace := fSurfaceColorSpace; - - WriteLn(' get surface capabilities'); - SurfaceCapabilities := fPhyDevice.GetSurfaceCapabilities(fSurface.Handle); - if (SurfaceCapabilities.currentExtent.width = High(VkUint32)) then begin - SurfaceCapabilities.currentExtent.width := ClientWidth; - SurfaceCapabilities.currentExtent.height := ClientHeight; - end else begin - ClientWidth := SurfaceCapabilities.currentExtent.width; - ClientHeight := SurfaceCapabilities.currentExtent.height; + WriteLn(' done'); + finally + FreeAndNil(SurfaceFactory); end; - WriteLn(' width: ', SurfaceCapabilities.currentExtent.width); - WriteLn(' height: ', SurfaceCapabilities.currentExtent.height); - SwapChainFactory.ImageExtent := SurfaceCapabilities.currentExtent; - - Write(' set min image count... '); - SwapChainFactory.MinImageCount := SurfaceCapabilities.minImageCount + 1; - if (SurfaceCapabilities.maxImageCount > 0) and - (SwapChainFactory.MinImageCount > SurfaceCapabilities.maxImageCount) then - SwapChainFactory.MinImageCount := SurfaceCapabilities.maxImageCount; - WriteLn(SwapChainFactory.MinImageCount); - - WriteLn(' set pre transform...'); - SwapChainFactory.PreTransform := SurfaceCapabilities.currentTransform; - if (VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR in SurfaceCapabilities.supportedTransforms) then - SwapChainFactory.PreTransform := [ VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ]; - - Write(' find suitable present mode... '); - PresentModes := fPhyDevice.GetSurfacePresentModes(fSurface.Handle); - if (Length(PresentModes) = 0) then - raise TvkuException.Create('unable to get present modes'); - for pm in PresentModes do begin - if (pm = VK_PRESENT_MODE_MAILBOX_KHR) then begin - SwapChainFactory.PresentMode := pm; - break; - end; + + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create command pool'); + CommandPoolFactory := TvkuCommandPoolFactory.Create(fDevice); + try + CommandPoolFactory.Flags := [ VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT ]; + CommandPoolFactory.QueueFamilyIndex := fGraphicsQueueNodeIndex; + fCommandPool := CommandPoolFactory.CreateCommandPool; + WriteLn(' handle: ', PtrUInt(fCommandPool.Handle)); + + WriteLn(' alloc setup command buffer'); + SetupCommandBuffer := TvkuCommandBuffer.Create( + fCommandPool.CreateCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY), + true, fCommandPool.Handle, fDevice.DeviceCommands); + SetupCommandBuffer.BeginCommand; + WriteLn(' handle: ', PtrUInt(SetupCommandBuffer.Handle)); + WriteLn(' done'); + finally + FreeAndNil(CommandPoolFactory); end; - WriteLn(SwapChainFactory.PresentMode); - fSwapChain := SwapChainFactory.CreateSwapchain; - WriteLn(' handle: ', PtrUInt(fSwapChain.Handle)); - WriteLn(' done'); - finally - FreeAndNil(SwapChainFactory); - end; + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create swap chain'); + SwapChainFactory := TvkuSwapChainFactory.Create(fDevice); + try + SwapChainFactory.AllocHandler := fAllocHandler; + SwapChainFactory.Surface := fSurface.Handle; + SwapChainFactory.ImageUsage := [ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT ]; + SwapChainFactory.ImageArrayLayers := 1; + SwapChainFactory.ImageSharingMode := VK_SHARING_MODE_EXCLUSIVE; + SwapChainFactory.Clipped := true; + SwapChainFactory.ComposideAlpha := [ VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR ]; + SwapChainFactory.ImageFormat := fSurfaceFormat; + SwapChainFactory.ImageColorSpace := fSurfaceColorSpace; + + WriteLn(' get surface capabilities'); + SurfaceCapabilities := fPhyDevice.GetSurfaceCapabilities(fSurface.Handle); + if (SurfaceCapabilities.currentExtent.width = High(VkUint32)) then begin + SurfaceCapabilities.currentExtent.width := ClientWidth; + SurfaceCapabilities.currentExtent.height := ClientHeight; + end else begin + ClientWidth := SurfaceCapabilities.currentExtent.width; + ClientHeight := SurfaceCapabilities.currentExtent.height; + end; + WriteLn(' width: ', SurfaceCapabilities.currentExtent.width); + WriteLn(' height: ', SurfaceCapabilities.currentExtent.height); + SwapChainFactory.ImageExtent := SurfaceCapabilities.currentExtent; + + Write(' set min image count... '); + SwapChainFactory.MinImageCount := SurfaceCapabilities.minImageCount + 1; + if (SurfaceCapabilities.maxImageCount > 0) and + (SwapChainFactory.MinImageCount > SurfaceCapabilities.maxImageCount) then + SwapChainFactory.MinImageCount := SurfaceCapabilities.maxImageCount; + WriteLn(SwapChainFactory.MinImageCount); + + WriteLn(' set pre transform...'); + SwapChainFactory.PreTransform := SurfaceCapabilities.currentTransform; + if (VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR in SurfaceCapabilities.supportedTransforms) then + SwapChainFactory.PreTransform := [ VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR ]; + + Write(' find suitable present mode... '); + PresentModes := fPhyDevice.GetSurfacePresentModes(fSurface.Handle); + if (Length(PresentModes) = 0) then + raise TvkuException.Create('unable to get present modes'); + for pm in PresentModes do begin + if (pm = VK_PRESENT_MODE_MAILBOX_KHR) then begin + SwapChainFactory.PresentMode := pm; + break; + end; + end; + WriteLn(SwapChainFactory.PresentMode); - ////////////////////////////////////////////////////////////////////////////// - WriteLn('create image views'); - Images := fSwapChain.GetImages; - SetLength(fImageViews, Length(Images)); - ImageViewFactory := TvkuImageViewFactory.Create(fDevice); - try - ImageViewFactory.AllocHandler := fAllocHandler; - ImageViewFactory.Format := fSurfaceFormat; - ImageViewFactory.ViewType := VK_IMAGE_VIEW_TYPE_2D; - with ImageViewFactory.SubresourceRange do begin - AspectMask := [ VK_IMAGE_ASPECT_COLOR_BIT ]; - BaseMipLevel := 0; - LevelCount := 1; - BaseArrayLayer := 0; - LayerCount := 1; + fSwapChain := SwapChainFactory.CreateSwapchain; + WriteLn(' handle: ', PtrUInt(fSwapChain.Handle)); + WriteLn(' done'); + finally + FreeAndNil(SwapChainFactory); end; - with ImageViewFactory.Components do begin - r := VK_COMPONENT_SWIZZLE_R; - g := VK_COMPONENT_SWIZZLE_G; - b := VK_COMPONENT_SWIZZLE_B; - a := VK_COMPONENT_SWIZZLE_A; + + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create images and image views'); + Images := fSwapChain.GetImages; + SetLength(fImages, Length(Images)); + SetLength(fImageViews, Length(Images)); + ImageViewFactory := TvkuImageViewFactory.Create(fDevice); + try + ImageViewFactory.AllocHandler := fAllocHandler; + ImageViewFactory.Format := fSurfaceFormat; + ImageViewFactory.ViewType := VK_IMAGE_VIEW_TYPE_2D; + with ImageViewFactory.SubresourceRange do begin + AspectMask := [ VK_IMAGE_ASPECT_COLOR_BIT ]; + BaseMipLevel := 0; + LevelCount := 1; + BaseArrayLayer := 0; + LayerCount := 1; + end; + with ImageViewFactory.Components do begin + r := VK_COMPONENT_SWIZZLE_R; + g := VK_COMPONENT_SWIZZLE_G; + b := VK_COMPONENT_SWIZZLE_B; + a := VK_COMPONENT_SWIZZLE_A; + end; + for i := Low(fImageViews) to High(fImageViews) do begin + fImages[i] := TvkuImage.Create(Images[i], false, fDevice.DeviceCommands, @AllocCallbacks); + WriteLn(' image handle: ', PtrUInt(fImages[i].Handle)); + ImageMemoryBarrier := fImages[i].GetMemoryBarrier( + [ VK_IMAGE_ASPECT_COLOR_BIT ], + VK_IMAGE_LAYOUT_UNDEFINED, + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR); + SetupCommandBuffer.PipelineBarrier( + [ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT ], + [ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT ], + [], + [], + [], + [ ImageMemoryBarrier ]); + + ImageViewFactory.Image := fImages[i].Handle; + fImageViews[i] := ImageViewFactory.CreateImageView; + WriteLn(' view handle: ', PtrUInt(fImageViews[i].Handle)); + end; + WriteLn(' done'); + finally + FreeAndNil(ImageViewFactory); end; - for i := Low(fImageViews) to High(fImageViews) do begin - // TODO create image barrier - ImageViewFactory.Image := Images[i]; - fImageViews[i] := ImageViewFactory.CreateImageView; - WriteLn(' handle: ', PtrUInt(fImageViews[i].Handle)); + + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create draw command buffers'); + SetLength(fDrawCommandBuffers, Length(fImageViews)); + CommandBuffers := fCommandPool.CreateCommandBuffers( + VK_COMMAND_BUFFER_LEVEL_PRIMARY, + Length(fDrawCommandBuffers)); + for i := low(CommandBuffers) to high(CommandBuffers) do begin + fDrawCommandBuffers[i] := TvkuCommandBuffer.Create( + CommandBuffers[i], + true, + fCommandPool.Handle, + fDevice.DeviceCommands); + WriteLn(' handle: ', PtrUInt(fDrawCommandBuffers[i].Handle)); end; WriteLn(' done'); - finally - FreeAndNil(ImageViewFactory); - end; - ////////////////////////////////////////////////////////////////////////////// - WriteLn('create render pass'); - RenderPassFactory := TvkuRenderPassFactory.Create(fDevice); - try - RenderPassFactory.Attachments.Length := 2; - with RenderPassFactory.Attachments[0] do begin - Format := fSurfaceFormat; - Samples := [ VK_SAMPLE_COUNT_1_BIT ]; - LoadOp := VK_ATTACHMENT_LOAD_OP_CLEAR; - StoreOp := VK_ATTACHMENT_STORE_OP_STORE; - StencilLoadOp := VK_ATTACHMENT_LOAD_OP_DONT_CARE; - StencilStoreOp := VK_ATTACHMENT_STORE_OP_DONT_CARE; - InitialLayout := VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - FinalLayout := VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - end; + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create post present command buffers'); + fPostPresentCommandBuffer := TvkuCommandBuffer.Create( + fCommandPool.CreateCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY), + true, + fCommandPool.Handle, + fDevice.DeviceCommands); + WriteLn(' handle: ', PtrUInt(fPostPresentCommandBuffer.Handle)); + WriteLn(' done'); + + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create depth stencil image and image view'); + ImageFactory := TvkuImageFactory.Create(fDevice); + ImageViewFactory := TvkuImageViewFactory.Create(fDevice); + try + ImageFactory.ImageType := VK_IMAGE_TYPE_2D; + ImageFactory.Format := fDepthFormat; + ImageFactory.Extent := vkExtent3D( + SurfaceCapabilities.currentExtent.width, + SurfaceCapabilities.currentExtent.height, + 1); + ImageFactory.MipLevels := 1; + ImageFactory.ArrayLayers := 1; + ImageFactory.Samples := [ VK_SAMPLE_COUNT_1_BIT ]; + ImageFactory.Tiling := VK_IMAGE_TILING_OPTIMAL; + ImageFactory.Usage := [ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ]; + fDepthStencilImage := ImageFactory.CreateImage; + fDepthStencilImage.AllocateAndBindImageMemory( + fPhyDevice.GetMemoryProperties, + @AllocCallbacks); + WriteLn(' image handle: ', PtrUInt(fDepthStencilImage.Handle)); + + ImageViewFactory.Image := fDepthStencilImage.Handle; + ImageViewFactory.ViewType := VK_IMAGE_VIEW_TYPE_2D; + ImageViewFactory.Format := fDepthFormat; + with ImageViewFactory.SubresourceRange do begin + AspectMask := [ VK_IMAGE_ASPECT_DEPTH_BIT, VK_IMAGE_ASPECT_STENCIL_BIT ]; + BaseMipLevel := 0; + LevelCount := 1; + BaseArrayLayer := 0; + LayerCount := 1; + end; + fDepthStencilImageView := ImageViewFactory.CreateImageView; + WriteLn(' view handle: ', PtrUInt(fDepthStencilImageView.Handle)); - with RenderPassFactory.Attachments[1] do begin - Format := DepthFormat; - Samples := [ VK_SAMPLE_COUNT_1_BIT ]; - LoadOp := VK_ATTACHMENT_LOAD_OP_CLEAR; - StoreOp := VK_ATTACHMENT_STORE_OP_STORE; - StencilLoadOp := VK_ATTACHMENT_LOAD_OP_DONT_CARE; - StencilStoreOp := VK_ATTACHMENT_STORE_OP_DONT_CARE; - InitialLayout := VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - FinalLayout := VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + WriteLn(' done'); + finally + FreeAndNil(ImageViewFactory); + FreeAndNil(ImageFactory); end; - RenderPassFactory.Subpasses.Length := 1; - with RenderPassFactory.Subpasses[0] do begin - PipelineBindPoint := VK_PIPELINE_BIND_POINT_GRAPHICS; + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create render pass'); + RenderPassFactory := TvkuRenderPassFactory.Create(fDevice); + try + RenderPassFactory.Attachments.Length := 2; + with RenderPassFactory.Attachments[0] do begin + Format := fSurfaceFormat; + Samples := [ VK_SAMPLE_COUNT_1_BIT ]; + LoadOp := VK_ATTACHMENT_LOAD_OP_CLEAR; + StoreOp := VK_ATTACHMENT_STORE_OP_STORE; + StencilLoadOp := VK_ATTACHMENT_LOAD_OP_DONT_CARE; + StencilStoreOp := VK_ATTACHMENT_STORE_OP_DONT_CARE; + InitialLayout := VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + FinalLayout := VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + end; + + with RenderPassFactory.Attachments[1] do begin + Format := fDepthFormat; + Samples := [ VK_SAMPLE_COUNT_1_BIT ]; + LoadOp := VK_ATTACHMENT_LOAD_OP_CLEAR; + StoreOp := VK_ATTACHMENT_STORE_OP_STORE; + StencilLoadOp := VK_ATTACHMENT_LOAD_OP_DONT_CARE; + StencilStoreOp := VK_ATTACHMENT_STORE_OP_DONT_CARE; + InitialLayout := VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + FinalLayout := VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + end; - ColorAttachments.Length := 1; - ColorAttachments[0].Attachment := 0; - ColorAttachments[0].Layout := VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + RenderPassFactory.Subpasses.Length := 1; + with RenderPassFactory.Subpasses[0] do begin + PipelineBindPoint := VK_PIPELINE_BIND_POINT_GRAPHICS; - DepthStencilAttachments.Length := 1; - DepthStencilAttachments[0].Attachment := 1; - DepthStencilAttachments[0].Layout := VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - end; + ColorAttachments.Length := 1; + ColorAttachments[0].Attachment := 0; + ColorAttachments[0].Layout := VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - RenderPassFactory.AllocHandler := fAllocHandler; - fRenderPass := RenderPassFactory.CreateRenderPass; + DepthStencilAttachments.Length := 1; + DepthStencilAttachments[0].Attachment := 1; + DepthStencilAttachments[0].Layout := VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; + end; - WriteLn(' handle: ', PtrUInt(fRenderPass.Handle)); - WriteLn(' done'); - finally - FreeAndNil(RenderPassFactory); - end; + RenderPassFactory.AllocHandler := fAllocHandler; + fRenderPass := RenderPassFactory.CreateRenderPass; - ////////////////////////////////////////////////////////////////////////////// - WriteLn('create frame buffers'); - FrameBufferFactory := TvkuFrameBufferFactory.Create(fDevice); - try - SetLength(fFrameBuffers, Length(fImageViews)); - - FrameBufferFactory.AllocHandler := fAllocHandler; - FrameBufferFactory.RenderPass := fRenderPass.Handle; - FrameBufferFactory.Width := SurfaceCapabilities.currentExtent.width; - FrameBufferFactory.Height := SurfaceCapabilities.currentExtent.height; - FrameBufferFactory.Layers := 1; - FrameBufferFactory.Attachments.Length := 1; - - for i := low(fFrameBuffers) to high(fFrameBuffers) do begin - FrameBufferFactory.Attachments[0] := fImageViews[i].Handle; - fFrameBuffers[i] := FrameBufferFactory.CreateFrameBuffer; - WriteLn(' handle: ', PtrUInt(fFrameBuffers[i].Handle)); + WriteLn(' handle: ', PtrUInt(fRenderPass.Handle)); + WriteLn(' done'); + finally + FreeAndNil(RenderPassFactory); end; - WriteLn(' done'); - finally - FreeAndNil(FrameBufferFactory); - end; - ////////////////////////////////////////////////////////////////////////////// - WriteLn('create descriptor set layout'); - DescSetLayoutFactory := TvkuDescriptorSetLayoutFactory.Create(fDevice); - try - DescSetLayoutFactory.Bindings.Length := 1; - with DescSetLayoutFactory.Bindings[0] do begin - Binding := 0; // binding 0 (Uniform Buffer/Vertex Shader) - DescriptorType := VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - DescriptorCount := 1; - StageFlags := [ VK_SHADER_STAGE_VERTEX_BIT ]; + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create pipeline cache'); + PipelineCacheFactory := TvkuPipelineCacheFactory.Create(fDevice); + try + fPipelineCache := PipelineCacheFactory.CreatePipelineCache; + WriteLn(' handle: ', PtrUInt(fPipelineCache.Handle)); + WriteLn(' done'); + finally + FreeAndNil(PipelineCacheFactory); end; - DescSetLayoutFactory.AllocHandler := fAllocHandler; + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create frame buffers'); + FrameBufferFactory := TvkuFrameBufferFactory.Create(fDevice); + try + SetLength(fFrameBuffers, Length(fImageViews)); + + FrameBufferFactory.AllocHandler := fAllocHandler; + FrameBufferFactory.RenderPass := fRenderPass.Handle; + FrameBufferFactory.Width := SurfaceCapabilities.currentExtent.width; + FrameBufferFactory.Height := SurfaceCapabilities.currentExtent.height; + FrameBufferFactory.Layers := 1; + FrameBufferFactory.Attachments.Length := 2; + FrameBufferFactory.Attachments[1] := fDepthStencilImageView.Handle; + + for i := low(fFrameBuffers) to high(fFrameBuffers) do begin + FrameBufferFactory.Attachments[0] := fImageViews[i].Handle; + fFrameBuffers[i] := FrameBufferFactory.CreateFrameBuffer; + WriteLn(' handle: ', PtrUInt(fFrameBuffers[i].Handle)); + end; + WriteLn(' done'); + finally + FreeAndNil(FrameBufferFactory); + end; - fDescSetLayout := DescSetLayoutFactory.CreateDescriptorSetLayout; - WriteLn(' handle: ', PtrUInt(fDescSetLayout.Handle)); + ////////////////////////////////////////////////////////////////////////////// + WriteLn('flush setup command buffer'); + SetupCommandBuffer.EndCommand; + fQueue.Submit([], [], [ SetupCommandBuffer.Handle ], [], VK_INVALID_NDP_HANDLE); + fQueue.WaitIdle; + FreeAndNil(SetupCommandBuffer); WriteLn(' done'); - finally - FreeAndNil(DescSetLayoutFactory); - end; - ////////////////////////////////////////////////////////////////////////////// - WriteLn('create pipeline layout'); - PipelineLayoutFactory := TvkuPipelineLayoutFactory.Create(fDevice); - try - PipelineLayoutFactory.AllocHandler := fAllocHandler; - PipelineLayoutFactory.SetLayouts.Length := 1; - PipelineLayoutFactory.SetLayouts[0] := fDescSetLayout.Handle; - fPipelineLayout := PipelineLayoutFactory.CreatePipelineLayout; - WriteLn(' handle: ', PtrUInt(fPipelineLayout.Handle)); - WriteLn(' done'); - finally - FreeAndNil(PipelineLayoutFactory); - end; + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create descriptor set layout'); + DescSetLayoutFactory := TvkuDescriptorSetLayoutFactory.Create(fDevice); + try + DescSetLayoutFactory.Bindings.Length := 1; + with DescSetLayoutFactory.Bindings[0] do begin + Binding := 0; // binding 0 (Uniform Buffer/Vertex Shader) + DescriptorType := VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + DescriptorCount := 1; + StageFlags := [ VK_SHADER_STAGE_VERTEX_BIT ]; + end; - ////////////////////////////////////////////////////////////////////////////// - WriteLn('create shader modules'); - ShaderModuleFactory := TvkuShaderModuleFactory.Create(fDevice); - try - ShaderModuleFactory.AllocHandler := fAllocHandler; + DescSetLayoutFactory.AllocHandler := fAllocHandler; - ShaderModuleFactory.LoadGlslCode(ExtractFilePath(Application.ExeName) + '../../data/shaders/triangle.vert', [ VK_SHADER_STAGE_VERTEX_BIT ]); - fVertexShader := ShaderModuleFactory.CreateShaderModule; - WriteLn(' vertex handle: ', PtrUInt(fVertexShader.Handle)); + fDescSetLayout := DescSetLayoutFactory.CreateDescriptorSetLayout; + WriteLn(' handle: ', PtrUInt(fDescSetLayout.Handle)); + WriteLn(' done'); + finally + FreeAndNil(DescSetLayoutFactory); + end; - ShaderModuleFactory.LoadGlslCode(ExtractFilePath(Application.ExeName) + '../../data/shaders/triangle.frag', [ VK_SHADER_STAGE_FRAGMENT_BIT ]); - fFragmentShader := ShaderModuleFactory.CreateShaderModule; - WriteLn(' fragment handle: ', PtrUInt(fFragmentShader.Handle)); - WriteLn(' done'); - finally - FreeAndNil(ShaderModuleFactory); - end; + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create pipeline layout'); + PipelineLayoutFactory := TvkuPipelineLayoutFactory.Create(fDevice); + try + PipelineLayoutFactory.AllocHandler := fAllocHandler; + PipelineLayoutFactory.SetLayouts.Length := 1; + PipelineLayoutFactory.SetLayouts[0] := fDescSetLayout.Handle; + fPipelineLayout := PipelineLayoutFactory.CreatePipelineLayout; + WriteLn(' handle: ', PtrUInt(fPipelineLayout.Handle)); + WriteLn(' done'); + finally + FreeAndNil(PipelineLayoutFactory); + end; + + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create shader modules'); + ShaderModuleFactory := TvkuShaderModuleFactory.Create(fDevice); + try + ShaderModuleFactory.AllocHandler := fAllocHandler; + + ShaderModuleFactory.LoadGlslCode(ExtractFilePath(Application.ExeName) + '../../data/shaders/triangle.vert', [ VK_SHADER_STAGE_VERTEX_BIT ]); + fVertexShader := ShaderModuleFactory.CreateShaderModule; + WriteLn(' vertex handle: ', PtrUInt(fVertexShader.Handle)); + + ShaderModuleFactory.LoadGlslCode(ExtractFilePath(Application.ExeName) + '../../data/shaders/triangle.frag', [ VK_SHADER_STAGE_FRAGMENT_BIT ]); + fFragmentShader := ShaderModuleFactory.CreateShaderModule; + WriteLn(' fragment handle: ', PtrUInt(fFragmentShader.Handle)); + WriteLn(' done'); + finally + FreeAndNil(ShaderModuleFactory); + end; + + ////////////////////////////////////////////////////////////////////////////// + WriteLn('create graphics pipeline'); + PipelineFactory := TvkuGraphicsPipelineFactory.Create(fDevice); + try + PipelineFactory.AllocHandler := fAllocHandler; + // TODO fPipeline := PipelineFactory.CreateGraphicsPipeline(VK_INVALID_NDP_HANDLE); + finally + FreeAndNil(PipelineFactory); + end; - ////////////////////////////////////////////////////////////////////////////// - WriteLn('create graphics pipeline'); - PipelineFactory := TvkuGraphicsPipelineFactory.Create(fDevice); - try - PipelineFactory.AllocHandler := fAllocHandler; - // TODO fPipeline := PipelineFactory.CreateGraphicsPipeline(VK_INVALID_NDP_HANDLE); finally - FreeAndNil(PipelineFactory); + FreeAndNil(SetupCommandBuffer); end; end; @@ -503,12 +621,28 @@ procedure TMainForm.FormDestroy(Sender: TObject); SetLength(fFrameBuffers, 0); end; + procedure FreeAndNilImages; + var i: Integer; + begin + for i := low(fImages) to high(fImages) do + FreeAndNil(fImages[i]); + SetLength(fImages, 0); + end; + procedure FreeAndNilImageViews; var i: Integer; begin for i := Low(fImageViews) to High(fImageViews) do - FreeAndNil(fImageViews[i]); - SetLength(fImageViews, 0); + FreeAndNil(fImageViews[i]); + SetLength(fImageViews, 0); + end; + + procedure FreeAndNilDrawCommandBuffers; + var i: Integer; + begin + for i := Low(fDrawCommandBuffers) to High(fDrawCommandBuffers) do + FreeAndNil(fDrawCommandBuffers[i]); + SetLength(fDrawCommandBuffers, 0); end; begin @@ -518,9 +652,16 @@ begin FreeAndNil(fPipelineLayout); FreeAndNil(fDescSetLayout); FreeAndNilFrameBuffers; + FreeAndNil(fPipelineCache); FreeAndNil(fRenderPass); + FreeAndNil(fDepthStencilImageView); + FreeAndNil(fDepthStencilImage); + FreeAndNil(fPostPresentCommandBuffer); + FreeAndNilDrawCommandBuffers; FreeAndNilImageViews; + FreeAndNilImages; FreeAndNil(fSwapChain); + FreeAndNil(fCommandPool); FreeAndNil(fSurface); FreeAndNil(fQueue); FreeAndNil(fDevice); diff --git a/projects/utils/VulkanUtils.pas b/projects/utils/VulkanUtils.pas index 7142ce1..d0957f4 100644 --- a/projects/utils/VulkanUtils.pas +++ b/projects/utils/VulkanUtils.pas @@ -6,6 +6,7 @@ interface uses Classes, SysUtils, + Vulkan, uvkuTypes, uvkuAllocationHandler, uvkuDebugReporter, uvkuInstance, uvkuInstanceFactory, uvkuPhysicalDevice, uvkuDevice, uvkuDeviceFactory, uvkuDeviceMemory, uvkuQueue, @@ -18,7 +19,7 @@ uses uvkuFrameBuffer, uvkuFrameBufferFactory, uvkuDescriptorSetLayout, uvkuDescriptorSetLayoutFactory, uvkuShaderModule, uvkuShaderModuleFactory, - uvkuPipelineLayout, uvkuPipelineLayoutFactory, uvkuPipeline, uvkuPipelineFactory, + uvkuPipelineLayout, uvkuPipelineLayoutFactory, uvkuPipelineCache, uvkuPipelineCacheFactory, uvkuPipeline, uvkuPipelineFactory, uvkuUtils; type @@ -40,6 +41,19 @@ type TVkPushConstantRangeArr = uvkuTypes.TVkPushConstantRangeArr; TVkPipelineShaderStageCreateInfoArr = uvkuTypes.TVkPipelineShaderStageCreateInfoArr; TVkPipelineVertexInputStateCreateInfoArr = uvkuTypes.TVkPipelineVertexInputStateCreateInfoArr; + TVkAttachmentDescriptionArr = uvkuTypes.TVkAttachmentDescriptionArr; + TVkSubpassDescriptionArr = uvkuTypes.TVkSubpassDescriptionArr; + TVkSubpassDependencyArr = uvkuTypes.TVkSubpassDependencyArr; + TVkAttachmentReferenceArr = uvkuTypes.TVkAttachmentReferenceArr; + TVkMemoryBarrierArr = uvkuTypes.TVkMemoryBarrierArr; + TVkBufferMemoryBarrierArr = uvkuTypes.TVkBufferMemoryBarrierArr; + TVkImageMemoryBarrierArr = uvkuTypes.TVkImageMemoryBarrierArr; + + TVkUint32List = uvkuTypes.TVkUint32List; + TVkFloatList = uvkuTypes.TVkFloatList; + TVkImageViewList = uvkuTypes.TVkImageViewList; + TVkSamplerList = uvkuTypes.TVkSamplerList; + TVkDescriptorSetLayoutList = uvkuTypes.TVkDescriptorSetLayoutList; TvkuAllocationHandler = uvkuAllocationHandler.TvkuAllocationHandler; @@ -101,6 +115,8 @@ type { Pipeline } TvkuPipelineLayout = uvkuPipelineLayout.TvkuPipelineLayout; TvkuPipelineLayoutFactory = uvkuPipelineLayoutFactory.TvkuPipelineLayoutFactory; + TvkuPipelineCache = uvkuPipelineCache.TvkuPipelineCache; + TvkuPipelineCacheFactory = uvkuPipelineCacheFactory.TvkuPipelineCacheFactory; TvkuPipeline = uvkuPipeline.TvkuPipeline; TvkuGraphicsPipeline = uvkuPipeline.TvkuGraphicsPipeline; TvkuGraphicsPipelineFactory = uvkuPipelineFactory.TvkuGraphicsPipelineFactory; @@ -112,7 +128,23 @@ type TvkuErrorException = uvkuUtils.TvkuErrorException; TvkuInvalidFuncPtrException = uvkuUtils.TvkuInvalidFuncPtrException; + function vkExtent2D(const X, Y: VkUint32): TVkExtent2D; + function vkExtent3D(const X, Y, Z: VkUint32): TVkExtent3D; + implementation +function vkExtent2D(const X, Y: VkUint32): TVkExtent2D; +begin + result.width := x; + result.height := y; +end; + +function vkExtent3D(const X, Y, Z: VkUint32): TVkExtent3D; +begin + result.width := x; + result.height := y; + result.depth := z; +end; + end. diff --git a/projects/utils/uvkuAllocationHandler.pas b/projects/utils/uvkuAllocationHandler.pas index 7e1512f..1f75393 100644 --- a/projects/utils/uvkuAllocationHandler.pas +++ b/projects/utils/uvkuAllocationHandler.pas @@ -20,7 +20,7 @@ type procedure InternalAllocationNotification(const aSize: VkSize; const aType: TVkInternalAllocationType; const aScope: TVkSystemAllocationScope); procedure InternalFreeNotification(const aSize: VkSize; const aType: TVkInternalAllocationType; const aScope: TVkSystemAllocationScope); public - function MakeStructure: TVkAllocationCallbacks; + function GetStructure: TVkAllocationCallbacks; end; implementation @@ -107,7 +107,7 @@ begin end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuAllocationHandler.MakeStructure: TVkAllocationCallbacks; +function TvkuAllocationHandler.GetStructure: TVkAllocationCallbacks; begin FillByte(result, SizeOf(result), 0); result.pUserData := self; diff --git a/projects/utils/uvkuCommandBuffer.pas b/projects/utils/uvkuCommandBuffer.pas index 73f9138..535d3f8 100644 --- a/projects/utils/uvkuCommandBuffer.pas +++ b/projects/utils/uvkuCommandBuffer.pas @@ -6,7 +6,7 @@ interface uses Classes, SysUtils, - Vulkan, uvkuBase; + Vulkan, uvkuBase, uvkuTypes; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -21,6 +21,14 @@ type property DeviceCommands: TVkDeviceCommands read fDeviceCommands; procedure BeginCommand; + procedure EndCommand; + procedure PipelineBarrier( + const aSrcStageMask: VkPipelineStageFlags; + const aDstStageMask: VkPipelineStageFlags; + const aDependencyFlags: VkDependencyFlags; + const aMemoryBarriers: array of TVkMemoryBarrier; + const aBufferMemoryBarriers: array of TVkBufferMemoryBarrier; + const aImageMemoryBarriers: array of TVkImageMemoryBarrier); constructor Create( const aHandle: VkCommandBuffer; @@ -53,6 +61,31 @@ begin raise TvkuErrorException.Create('unable to begin command buffer', err); end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuCommandBuffer.EndCommand; +var err: TVkResult; +begin + err := fDeviceCommands.vkEndCommandBuffer(fHandle); + if (err < VK_SUCCESS) then + raise TvkuErrorException.Create('unable to end command buffer', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuCommandBuffer.PipelineBarrier(const aSrcStageMask: VkPipelineStageFlags; + const aDstStageMask: VkPipelineStageFlags; const aDependencyFlags: VkDependencyFlags; + const aMemoryBarriers: array of TVkMemoryBarrier; const aBufferMemoryBarriers: array of TVkBufferMemoryBarrier; + const aImageMemoryBarriers: array of TVkImageMemoryBarrier); +begin + DeviceCommands.vkCmdPipelineBarrier( + fHandle, + aSrcStageMask, + aDstStageMask, + aDependencyFlags, + Length(aMemoryBarriers), @aMemoryBarriers[0], + Length(aBufferMemoryBarriers), @aBufferMemoryBarriers[0], + Length(aImageMemoryBarriers), @aImageMemoryBarriers[0]); +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuCommandBuffer.Create(const aHandle: VkCommandBuffer; const aOwnsHandle: Boolean; const aCommandPool: VkCommandPool; const aDeviceCommands: TVkDeviceCommands); diff --git a/projects/utils/uvkuDebugReporter.pas b/projects/utils/uvkuDebugReporter.pas index 498cc00..1948fa0 100644 --- a/projects/utils/uvkuDebugReporter.pas +++ b/projects/utils/uvkuDebugReporter.pas @@ -91,7 +91,7 @@ var begin inherited Create; if Assigned(aAllocHandler) then - SetAllocCallbacks(aAllocHandler.MakeStructure); + SetAllocCallbacks(aAllocHandler.GetStructure); fInstanceCommands := aInstanceCommands; FillByte(CreateInfo, SizeOf(CreateInfo), 0); diff --git a/projects/utils/uvkuDevice.pas b/projects/utils/uvkuDevice.pas index d3dcd23..bd1a052 100644 --- a/projects/utils/uvkuDevice.pas +++ b/projects/utils/uvkuDevice.pas @@ -23,7 +23,16 @@ type property Handle: VkDevice read fHandle; property DeviceCommands: TVkDeviceCommands read fDeviceCommands; - function GetQueue(const aQueueFamilyIndex, aQueueIndex: VkUint32): VkQueue; + function GetQueue( + const aQueueFamilyIndex: VkUint32; + const aQueueIndex: VkUint32): VkQueue; + function AllocateMemory( + const aSize: VkUint32; + const aMemoryTypeIndex: VkUint32; + aAllocCallbacks: PVkAllocationCallbacks = nil): VkDeviceMemory; + procedure FreeMemory( + const aMemory: VkDeviceMemory; + aAllocCallbacks: PVkAllocationCallbacks = nil); constructor Create( const aPhysicalDevice: VkPhysicalDevice; @@ -60,7 +69,7 @@ begin end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuDevice.GetQueue(const aQueueFamilyIndex, aQueueIndex: VkUint32): VkQueue; +function TvkuDevice.GetQueue(const aQueueFamilyIndex: VkUint32; const aQueueIndex: VkUint32): VkQueue; begin if not Assigned(fDeviceCommands.vkGetDeviceQueue) then raise TvkuInvalidFuncPtrException.Create('vkGetDeviceQueue'); @@ -69,6 +78,33 @@ begin raise TvkuException.Create('unable to get device queue'); end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuDevice.AllocateMemory(const aSize: VkUint32; const aMemoryTypeIndex: VkUint32; + aAllocCallbacks: PVkAllocationCallbacks): VkDeviceMemory; +var + AllocInfo: TVkMemoryAllocateInfo; + err: TVkResult; +begin + FillByte(AllocInfo, SizeOf(AllocInfo), 0); + AllocInfo.sType := VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + AllocInfo.pNext := nil; + AllocInfo.allocationSize := aSize; + AllocInfo.memoryTypeIndex := aMemoryTypeIndex; + if not Assigned(aAllocCallbacks) then + aAllocCallbacks := AllocCallbacks; + err := fDeviceCommands.vkAllocateMemory(fHandle, @AllocInfo, aAllocCallbacks, @result); + if (err < VK_SUCCESS) then + raise TvkuErrorException.Create('unable to allocate device memory', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuDevice.FreeMemory(const aMemory: VkDeviceMemory; aAllocCallbacks: PVkAllocationCallbacks); +begin + if not Assigned(aAllocCallbacks) then + aAllocCallbacks := AllocCallbacks; + fDeviceCommands.vkFreeMemory(fHandle, aMemory, aAllocCallbacks); +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuDevice.Create(const aPhysicalDevice: VkPhysicalDevice; const aCreateInfo: TVkDeviceCreateInfo; const aInstanceCommands: TVkInstanceCommands; const aAllocCallbacks: PVkAllocationCallbacks); diff --git a/projects/utils/uvkuFactoryBase.pas b/projects/utils/uvkuFactoryBase.pas index ab25fc4..3923a2d 100644 --- a/projects/utils/uvkuFactoryBase.pas +++ b/projects/utils/uvkuFactoryBase.pas @@ -85,7 +85,7 @@ begin if Assigned(fAllocHandler) then begin new(fAllocCallbacks); fOwnsAllocCallbacks := true; - fAllocCallbacks^ := fAllocHandler.MakeStructure; + fAllocCallbacks^ := fAllocHandler.GetStructure; end; end; diff --git a/projects/utils/uvkuImage.pas b/projects/utils/uvkuImage.pas index eca9d36..77dcbc7 100644 --- a/projects/utils/uvkuImage.pas +++ b/projects/utils/uvkuImage.pas @@ -6,7 +6,7 @@ interface uses Classes, SysUtils, - Vulkan, uvkuBase; + Vulkan, uvkuBase, uvkuDeviceMemory; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -14,6 +14,7 @@ type private fHandle: VkImage; fDeviceCommands: TVkDeviceCommands; + fImageMemory: TvkuDeviceMemory; procedure CreateHandle(const aCreateInfo: TVkImageCreateInfo); public @@ -24,6 +25,14 @@ type const aAspectMask: VkImageAspectFlags; const aOldLayout: TVkImageLayout; const aNewLayout: TVkImageLayout): TVkImageMemoryBarrier; + procedure BindMemory( + const aMemory: VkDeviceMemory; + const aOffset: VkDeviceSize); + function GetMemoryRequirements: TVkMemoryRequirements; + + procedure AllocateAndBindImageMemory( + const aMemoryProperties: TVkPhysicalDeviceMemoryProperties; + aAllocCallbacks: PVkAllocationCallbacks = nil); constructor Create( const aCreateInfo: TVkImageCreateInfo; @@ -143,6 +152,59 @@ begin end; end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuImage.BindMemory(const aMemory: VkDeviceMemory; const aOffset: VkDeviceSize); +var err: TVkResult; +begin + err := fDeviceCommands.vkBindImageMemory(fDeviceCommands.Device, fHandle, aMemory, aOffset); + if (err < VK_SUCCESS) then + TvkuErrorException.Create('unable to bind image memory', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuImage.GetMemoryRequirements: TVkMemoryRequirements; +begin + fDeviceCommands.vkGetImageMemoryRequirements(fDeviceCommands.Device, fHandle, @result); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuImage.AllocateAndBindImageMemory(const aMemoryProperties: TVkPhysicalDeviceMemoryProperties; + aAllocCallbacks: PVkAllocationCallbacks); +var + i: Integer; + bits: VkUint32; + MemReq: TVkMemoryRequirements; + Mem: VkDeviceMemory; + MemAllocInfo: TVkMemoryAllocateInfo; + err: TVkResult; +begin + MemReq := GetMemoryRequirements; + + FillByte(MemAllocInfo, SizeOf(MemAllocInfo), 0); + MemAllocInfo.sType := VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + MemAllocInfo.pNext := nil; + MemAllocInfo.allocationSize := MemReq.size; + + bits := MemReq.memoryTypeBits; + for i := 0 to VK_MAX_MEMORY_TYPES-1 do begin + if ((bits and 1) = 1) and + (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT in aMemoryProperties.memoryTypes[i].propertyFlags) then + begin + MemAllocInfo.memoryTypeIndex := i; + break; + end; + bits := bits shr 1; + end; + + if not Assigned(aAllocCallbacks) then + aAllocCallbacks := AllocCallbacks; + err := fDeviceCommands.vkAllocateMemory(fDeviceCommands.Device, @MemAllocInfo, aAllocCallbacks, @Mem); + if (err < VK_SUCCESS) then + raise TvkuErrorException.Create('unable to allocate image memory', err); + fImageMemory := TvkuDeviceMemory.Create(Mem, true, fDeviceCommands, aAllocCallbacks); + BindMemory(fImageMemory.Handle, 0); +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuImage.Create(const aCreateInfo: TVkImageCreateInfo; const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks); @@ -170,6 +232,7 @@ begin if OwnsHandle and (fHandle <> VK_INVALID_NDP_HANDLE) then fDeviceCommands.vkDestroyImage(fDeviceCommands.Device, fHandle, AllocCallbacks); fHandle := VK_INVALID_NDP_HANDLE; + FreeAndNil(fImageMemory); inherited Destroy; end; diff --git a/projects/utils/uvkuPipelineCache.pas b/projects/utils/uvkuPipelineCache.pas new file mode 100644 index 0000000..38bc57c --- /dev/null +++ b/projects/utils/uvkuPipelineCache.pas @@ -0,0 +1,82 @@ +unit uvkuPipelineCache; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuBase; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuPipelineCache = class(TvkuAllocHandle) + private + fHandle: VkPipelineCache; + fDeviceCommands: TVkDeviceCommands; + + procedure CreateHandle(const aCreateInfo: TVkPipelineCacheCreateInfo); + public + property Handle: VkPipelineCache read fHandle; + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + + constructor Create( + const aCreateInfo: TVkPipelineCacheCreateInfo; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + constructor Create( + const aHandle: VkPipelineCache; + const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + destructor Destroy; override; + end; + +implementation + +uses + uvkuUtils; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuPipelineCache////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuPipelineCache.CreateHandle(const aCreateInfo: TVkPipelineCacheCreateInfo); +var err: TVkResult; +begin + err := fDeviceCommands.vkCreatePipelineCache(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); + if (err < VK_SUCCESS) then + TvkuErrorException.Create('unable to create pipeline cache', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuPipelineCache.Create(const aCreateInfo: TVkPipelineCacheCreateInfo; + const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fDeviceCommands := aDeviceCommands; + SetAllocCallbacks(aAllocCallbacks); + CreateHandle(aCreateInfo); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuPipelineCache.Create(const aHandle: VkPipelineCache; const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fHandle := aHandle; + fDeviceCommands := aDeviceCommands; + OwnsHandle := aOwnsHandle; + SetAllocCallbacks(aAllocCallbacks); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuPipelineCache.Destroy; +begin + if OwnsHandle and (fHandle <> VK_INVALID_NDP_HANDLE) then + fDeviceCommands.vkDestroyPipelineCache(fDeviceCommands.Device, fHandle, AllocCallbacks); + fHandle := VK_INVALID_NDP_HANDLE; + inherited Destroy; +end; + +end. + diff --git a/projects/utils/uvkuPipelineCacheFactory.pas b/projects/utils/uvkuPipelineCacheFactory.pas new file mode 100644 index 0000000..ebcd915 --- /dev/null +++ b/projects/utils/uvkuPipelineCacheFactory.pas @@ -0,0 +1,65 @@ +unit uvkuPipelineCacheFactory; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuFactoryBase, uvkuPipelineCache; + +type + TvkuPipelineCacheFactory = class(TvkuDeviceObjFactory) + private + fFlags: VkPipelineCacheCreateFlags; + fInitialDataSize: VkSize; + fInitialData: PVkVoid; + public + property Flags: VkPipelineCacheCreateFlags read fFlags write fFlags; + + procedure SetInitalData(const aData: PVkVoid; const aSize: VkSize); + + function GetStructure: TVkPipelineCacheCreateInfo; + procedure SetStructure(const aData: TVkPipelineCacheCreateInfo); + + function CreatePipelineCache: TvkuPipelineCache; + end; + +implementation + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuPipelineCacheFactory/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuPipelineCacheFactory.SetInitalData(const aData: PVkVoid; const aSize: VkSize); +begin + fInitialData := aData; + fInitialDataSize := aSize; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuPipelineCacheFactory.GetStructure: TVkPipelineCacheCreateInfo; +begin + FillByte(result, SizeOf(result), 0); + result.sType := VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; + result.pNext := nil; + result.flags := fFlags; + result.initialDataSize := fInitialDataSize; + result.pInitialData := fInitialData; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuPipelineCacheFactory.SetStructure(const aData: TVkPipelineCacheCreateInfo); +begin + fFlags := aData.flags; + fInitialDataSize := aData.initialDataSize; + fInitialData := aData.pInitialData; +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuPipelineCacheFactory.CreatePipelineCache: TvkuPipelineCache; +begin + result := TvkuPipelineCache.Create(GetStructure, DeviceCommands, AllocCallbacks); +end; + +end. + diff --git a/projects/utils/uvkuQueue.pas b/projects/utils/uvkuQueue.pas index d36f3ab..0391359 100644 --- a/projects/utils/uvkuQueue.pas +++ b/projects/utils/uvkuQueue.pas @@ -18,6 +18,14 @@ type property Handle: VkQueue read fHandle; property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + procedure Submit( + const aWaitSemaphores: array of VkSemaphore; + const aWaitDstStageMask: array of VkSemaphore; + const aCommandBuffers: array of VkCommandBuffer; + const aSignalSemaphores: array of VkSemaphore; + const aFence: VkFence); + procedure WaitIdle; + constructor Create( const aHandle: VkQueue; const aDeviceCommands: TVkDeviceCommands); @@ -25,8 +33,49 @@ type implementation +uses + uvkuUtils; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuQueue////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuQueue.Submit( + const aWaitSemaphores: array of VkSemaphore; + const aWaitDstStageMask: array of VkSemaphore; + const aCommandBuffers: array of VkCommandBuffer; + const aSignalSemaphores: array of VkSemaphore; + const aFence: VkFence); +var + SubmitInfo: TVkSubmitInfo; + err: TVkResult; +begin + if Length(aWaitSemaphores) <> Length(aWaitDstStageMask) then + raise TvkuException.Create('aWaitSemaphores and aWaitDstStageMask must have the same number of elements'); + + FillByte(SubmitInfo, SizeOf(SubmitInfo), 0); + SubmitInfo.sType := VK_STRUCTURE_TYPE_SUBMIT_INFO; + SubmitInfo.pNext := nil; + SubmitInfo.waitSemaphoreCount := Length(aWaitSemaphores); + SubmitInfo.pWaitSemaphores := @aWaitSemaphores[0]; + SubmitInfo.pWaitDstStageMask := @aWaitDstStageMask[0]; + SubmitInfo.commandBufferCount := Length(aCommandBuffers); + SubmitInfo.pCommandBuffers := @aCommandBuffers[0]; + SubmitInfo.signalSemaphoreCount := Length(aSignalSemaphores); + SubmitInfo.pSignalSemaphores := @aSignalSemaphores[0]; + err := fDeviceCommands.vkQueueSubmit(fHandle, 1, @SubmitInfo, aFence); + if (err < VK_SUCCESS) then + raise TvkuErrorException.Create('unable to submit queue', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuQueue.WaitIdle; +var err: TVkResult; +begin + err := fDeviceCommands.vkQueueWaitIdle(fHandle); + if (err < VK_SUCCESS) then + raise TvkuErrorException.Create('error while waiting for queue', err); +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// constructor TvkuQueue.Create(const aHandle: VkQueue; const aDeviceCommands: TVkDeviceCommands); begin diff --git a/projects/utils/uvkuTypes.pas b/projects/utils/uvkuTypes.pas index 4d915d6..8dc0858 100644 --- a/projects/utils/uvkuTypes.pas +++ b/projects/utils/uvkuTypes.pas @@ -74,6 +74,9 @@ type TVkSubpassDescriptionArr = array of TVkSubpassDescription; TVkSubpassDependencyArr = array of TVkSubpassDependency; TVkAttachmentReferenceArr = array of TVkAttachmentReference; + TVkMemoryBarrierArr = array of TVkMemoryBarrier; + TVkBufferMemoryBarrierArr = array of TVkBufferMemoryBarrier; + TVkImageMemoryBarrierArr = array of TVkImageMemoryBarrier; TVkUint32List = specialize TvkuList; TVkFloatList = specialize TvkuList;