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;