From b5fad52964b7d3b7c26310b0387c51bcd4479f39 Mon Sep 17 00:00:00 2001 From: Bergmann89 Date: Mon, 11 Apr 2016 19:16:43 +0200 Subject: [PATCH] * implemented Sempahore * fixed last errors to get first rendered image :) --- projects/triangle/triangle.lpi | 6 +- projects/triangle/triangle.lpr | 2 +- projects/triangle/triangle.lps | 404 +++++++++++---------- projects/triangle/uMainForm.lfm | 5 + projects/triangle/uMainForm.pas | 86 ++++- projects/utils/VulkanUtils.pas | 94 ++--- projects/utils/uvkuBuffer.pas | 6 +- projects/utils/uvkuBufferView.pas | 2 +- projects/utils/uvkuCommandBuffer.pas | 4 +- projects/utils/uvkuCommandPool.pas | 4 +- projects/utils/uvkuDebugReporter.pas | 2 +- projects/utils/uvkuDescriptorPool.pas | 6 +- projects/utils/uvkuDescriptorSetLayout.pas | 2 +- projects/utils/uvkuDevice.pas | 14 +- projects/utils/uvkuDeviceFactory.pas | 18 +- projects/utils/uvkuDeviceMemory.pas | 4 +- projects/utils/uvkuFrameBuffer.pas | 2 +- projects/utils/uvkuImage.pas | 10 +- projects/utils/uvkuImageView.pas | 2 +- projects/utils/uvkuInstance.pas | 6 +- projects/utils/uvkuPhysicalDevice.pas | 26 +- projects/utils/uvkuPipeline.pas | 4 +- projects/utils/uvkuPipelineCache.pas | 2 +- projects/utils/uvkuPipelineLayout.pas | 2 +- projects/utils/uvkuQueue.pas | 42 ++- projects/utils/uvkuRenderPass.pas | 2 +- projects/utils/uvkuSemaphore.pas | 100 +++++ projects/utils/uvkuShaderModule.pas | 2 +- projects/utils/uvkuSurface.pas | 2 +- projects/utils/uvkuSwapChain.pas | 8 +- projects/utils/uvkuTypes.pas | 1 + 31 files changed, 557 insertions(+), 313 deletions(-) create mode 100644 projects/utils/uvkuSemaphore.pas diff --git a/projects/triangle/triangle.lpi b/projects/triangle/triangle.lpi index 51e0a78..dd9b78b 100644 --- a/projects/triangle/triangle.lpi +++ b/projects/triangle/triangle.lpi @@ -33,7 +33,7 @@ - + @@ -233,6 +233,10 @@ + + + + diff --git a/projects/triangle/triangle.lpr b/projects/triangle/triangle.lpr index a522bec..cf9d70d 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, uvkuDescriptorPool, uvkuDescriptorPoolFactory, uvkuDescriptorSet; + uMainForm, Vulkan, uvkuDescriptorPool, uvkuDescriptorPoolFactory, uvkuDescriptorSet, uvkuSemaphore; {$R *.res} diff --git a/projects/triangle/triangle.lps b/projects/triangle/triangle.lps index 9d62ba7..564cf7c 100644 --- a/projects/triangle/triangle.lps +++ b/projects/triangle/triangle.lps @@ -4,13 +4,13 @@ - + - + @@ -20,39 +20,41 @@ - - + + - + - - - + + + - + - - - + + + + + @@ -60,7 +62,7 @@ - + @@ -68,7 +70,7 @@ - + @@ -76,23 +78,24 @@ - + - - - + + + - - - - + + + + + @@ -100,7 +103,7 @@ - + @@ -108,22 +111,23 @@ - + - + - - - - + + + + + @@ -131,22 +135,23 @@ - + - + - - - - + + + + + @@ -154,7 +159,7 @@ - + @@ -162,7 +167,7 @@ - + @@ -170,7 +175,7 @@ - + @@ -178,15 +183,15 @@ - + - - + + @@ -195,7 +200,7 @@ - + @@ -203,14 +208,14 @@ - + - + @@ -218,7 +223,7 @@ - + @@ -226,32 +231,33 @@ - + - - - - + + + + - - - - + + + + + - - - - + + + + @@ -260,7 +266,7 @@ - + @@ -268,7 +274,7 @@ - + @@ -276,7 +282,7 @@ - + @@ -284,7 +290,7 @@ - + @@ -292,7 +298,7 @@ - + @@ -300,14 +306,14 @@ - + - + @@ -315,7 +321,7 @@ - + @@ -323,7 +329,7 @@ - + @@ -331,7 +337,7 @@ - + @@ -339,7 +345,7 @@ - + @@ -347,7 +353,7 @@ - + @@ -355,13 +361,13 @@ - + - + @@ -369,7 +375,7 @@ - + @@ -377,7 +383,7 @@ - + @@ -385,7 +391,7 @@ - + @@ -393,7 +399,7 @@ - + @@ -401,7 +407,7 @@ - + @@ -409,287 +415,291 @@ - + + + + + + + + + + - - - + + + - + - - + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - + + + + + + - - - + + + - - - + + + - - - + + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - + - + - + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - - + + - - + + - + - - + + - + - - + + - - + + - + - - + + - - + + - + - + + + + + - - - - - - - - - diff --git a/projects/triangle/uMainForm.lfm b/projects/triangle/uMainForm.lfm index 17e7600..bec341e 100644 --- a/projects/triangle/uMainForm.lfm +++ b/projects/triangle/uMainForm.lfm @@ -18,4 +18,9 @@ object MainForm: TMainForm BevelOuter = bvNone TabOrder = 0 end + object ApplicationProperties: TApplicationProperties + OnIdle = ApplicationPropertiesIdle + left = 56 + top = 24 + end end diff --git a/projects/triangle/uMainForm.pas b/projects/triangle/uMainForm.pas index f3f81e4..5135b91 100644 --- a/projects/triangle/uMainForm.pas +++ b/projects/triangle/uMainForm.pas @@ -27,7 +27,9 @@ type end; TMainForm = class(TForm) + ApplicationProperties: TApplicationProperties; RenderPanel: TPanel; + procedure ApplicationPropertiesIdle(Sender: TObject; var Done: Boolean); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); private @@ -77,6 +79,7 @@ type end; procedure UpdateUniformBuffers; + procedure Render; end; var @@ -179,9 +182,10 @@ var r2D: TVkRect2D; begin try - fCamera := TglcCamera.Create; - fAllocHandler := TCustomAllocHandler.Create; - AllocCallbacks := fAllocHandler.GetStructure; + SetupCommandBuffer := nil; + fCamera := TglcCamera.Create; + fAllocHandler := TCustomAllocHandler.Create; + AllocCallbacks := fAllocHandler.GetStructure; ////////////////////////////////////////////////////////////////////////////// WriteLn('create instance: '); @@ -237,7 +241,7 @@ begin DeviceFactory := TvkuDeviceFactory.Create(fInstance); try DeviceFactory.AllocHandler := fAllocHandler; - DeviceFactory.EnabledExtensions.Add('VK_KHR_swapchain'); + DeviceFactory.EnabledExtensionNames.Add('VK_KHR_swapchain'); DeviceFactory.QueueCreateInfos.Length := 1; with DeviceFactory.QueueCreateInfos[0] do begin Flags := 0; @@ -936,6 +940,9 @@ begin 0, [ fDescriptorSet.Handle ], [ ]); + BindPipeline( + VK_PIPELINE_BIND_POINT_GRAPHICS, + fPipeline.Handle); BindVertexBuffers( VERTEX_BUFFER_BIND_ID, [ fVertex.DataBuffer.Handle ], @@ -980,6 +987,12 @@ begin end; end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TMainForm.ApplicationPropertiesIdle(Sender: TObject; var Done: Boolean); +begin + Render; +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TMainForm.FormDestroy(Sender: TObject); @@ -1069,5 +1082,70 @@ begin end; end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TMainForm.Render; +var + Semaphore: TvkuSemaphore; + AllocCallbacks: TVkAllocationCallbacks; + CurrentImage: VkUint32; + PostPresentBarrier: TVkImageMemoryBarrier; +begin + fDevice.WaitIdle; + + // present queue + AllocCallbacks := fAllocHandler.GetStructure; + Semaphore := TvkuSemaphore.Create( + VkSemaphoreCreateFlags([ VK_FENCE_CREATE_SIGNALED_BIT ]), + fDevice.DeviceCommands, + @AllocCallbacks); + try + CurrentImage := fSwapChain.AcquireNextImage(High(VkUint64), Semaphore.Handle, VK_INVALID_NDP_HANDLE); + fQueue.Submit( + [ Semaphore.Handle ], + [ ], + [ fDrawCommandBuffers[CurrentImage].Handle ], + [ ], + VK_INVALID_NDP_HANDLE); + fQueue.Present( + [ ], + [ fSwapChain.Handle ], + [ CurrentImage ]); + finally + FreeAndNil(Semaphore); + end; + + // post present image + PostPresentBarrier := fImages[CurrentImage].GetMemoryBarrier( + [ VK_IMAGE_ASPECT_COLOR_BIT ], + VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + PostPresentBarrier.srcAccessMask := []; + PostPresentBarrier.dstAccessMask := [ VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT ]; + + fPostPresentCommandBuffer.BeginCommand; + try + fPostPresentCommandBuffer.PipelineBarrier( + [ VK_PIPELINE_STAGE_ALL_COMMANDS_BIT ], + [ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT ], + [ ], + [ ], + [ ], + [ PostPresentBarrier ]); + finally + fPostPresentCommandBuffer.EndCommand; + end; + + // submit queue + fQueue.Submit( + [ ], + [ ], + [ fPostPresentCommandBuffer.Handle ], + [ ], + VK_INVALID_NDP_HANDLE); + fQueue.WaitIdle; + + fDevice.WaitIdle; +end; + end. diff --git a/projects/utils/VulkanUtils.pas b/projects/utils/VulkanUtils.pas index 105de20..07da1d6 100644 --- a/projects/utils/VulkanUtils.pas +++ b/projects/utils/VulkanUtils.pas @@ -21,6 +21,7 @@ uses uvkuShaderModule, uvkuShaderModuleFactory, uvkuPipelineLayout, uvkuPipelineLayoutFactory, uvkuPipelineCache, uvkuPipelineCacheFactory, uvkuPipeline, uvkuPipelineFactory, uvkuDescriptorPool, uvkuDescriptorPoolFactory, uvkuDescriptorSet, + uvkuSemaphore, uvkuUtils; type @@ -62,77 +63,80 @@ type TvkuConsoleDebugReporter = uvkuDebugReporter.TvkuConsoleDebugReporter; { Instance } - TvkuInstance = uvkuInstance.TvkuInstance; - TvkuInstanceFactory = uvkuInstanceFactory.TvkuInstanceFactory; + TvkuInstance = uvkuInstance.TvkuInstance; + TvkuInstanceFactory = uvkuInstanceFactory.TvkuInstanceFactory; { Device } - TvkuPhysicalDevice = uvkuPhysicalDevice.TvkuPhysicalDevice; - TvkuDevice = uvkuDevice.TvkuDevice; - TvkuDeviceFactory = uvkuDeviceFactory.TvkuDeviceFactory; - TvkuDeviceMemory = uvkuDeviceMemory.TvkuDeviceMemory; - TvkuQueue = uvkuQueue.TvkuQueue; + TvkuPhysicalDevice = uvkuPhysicalDevice.TvkuPhysicalDevice; + TvkuDevice = uvkuDevice.TvkuDevice; + TvkuDeviceFactory = uvkuDeviceFactory.TvkuDeviceFactory; + TvkuDeviceMemory = uvkuDeviceMemory.TvkuDeviceMemory; + TvkuQueue = uvkuQueue.TvkuQueue; { Surface } - TvkuSurface = uvkuSurface.TvkuSurface; - TvkuSurfaceFactory = uvkuSurfaceFactory.TvkuSurfaceFactory; + TvkuSurface = uvkuSurface.TvkuSurface; + TvkuSurfaceFactory = uvkuSurfaceFactory.TvkuSurfaceFactory; { SwapChain } - TvkuSwapChain = uvkuSwapChain.TvkuSwapChain; - TvkuSwapChainFactory = uvkuSwapChainFactory.TvkuSwapChainFactory; + TvkuSwapChain = uvkuSwapChain.TvkuSwapChain; + TvkuSwapChainFactory = uvkuSwapChainFactory.TvkuSwapChainFactory; { Image } - TvkuImage = uvkuImage.TvkuImage; - TvkuImageFactory = uvkuImageFactory.TvkuImageFactory; - TvkuImageView = uvkuImageView.TvkuImageView; - TvkuImageViewFactory = uvkuImageViewFactory.TvkuImageViewFactory; + TvkuImage = uvkuImage.TvkuImage; + TvkuImageFactory = uvkuImageFactory.TvkuImageFactory; + TvkuImageView = uvkuImageView.TvkuImageView; + TvkuImageViewFactory = uvkuImageViewFactory.TvkuImageViewFactory; { Buffer } - TvkuBuffer = uvkuBuffer.TvkuBuffer; - TvkuBufferFactory = uvkuBufferFactory.TvkuBufferFactory; - TvkuBufferView = uvkuBufferView.TvkuBufferView; - TvkuBufferViewFactory = uvkuBufferViewFactory.TvkuBufferViewFactory; + TvkuBuffer = uvkuBuffer.TvkuBuffer; + TvkuBufferFactory = uvkuBufferFactory.TvkuBufferFactory; + TvkuBufferView = uvkuBufferView.TvkuBufferView; + TvkuBufferViewFactory = uvkuBufferViewFactory.TvkuBufferViewFactory; { Commands } - TvkuCommandPool = uvkuCommandPool.TvkuCommandPool; - TvkuCommandPoolFactory = uvkuCommandPoolFactory.TvkuCommandPoolFactory; - TvkuCommandBuffer = uvkuCommandBuffer.TvkuCommandBuffer; + TvkuCommandPool = uvkuCommandPool.TvkuCommandPool; + TvkuCommandPoolFactory = uvkuCommandPoolFactory.TvkuCommandPoolFactory; + TvkuCommandBuffer = uvkuCommandBuffer.TvkuCommandBuffer; { RenderPass } - TvkuRenderPass = uvkuRenderPass.TvkuRenderPass; - TvkuRenderPassFactory = uvkuRenderPassFactory.TvkuRenderPassFactory; + TvkuRenderPass = uvkuRenderPass.TvkuRenderPass; + TvkuRenderPassFactory = uvkuRenderPassFactory.TvkuRenderPassFactory; { FrameBuffer } - TvkuFrameBuffer = uvkuFrameBuffer.TvkuFrameBuffer; - TvkuFrameBufferFactory = uvkuFrameBufferFactory.TvkuFrameBufferFactory; + TvkuFrameBuffer = uvkuFrameBuffer.TvkuFrameBuffer; + TvkuFrameBufferFactory = uvkuFrameBufferFactory.TvkuFrameBufferFactory; { DescriptorSetLayout } - TvkuDescriptorSetLayout = uvkuDescriptorSetLayout.TvkuDescriptorSetLayout; - TvkuDescriptorSetLayoutFactory = uvkuDescriptorSetLayoutFactory.TvkuDescriptorSetLayoutFactory; + TvkuDescriptorSetLayout = uvkuDescriptorSetLayout.TvkuDescriptorSetLayout; + TvkuDescriptorSetLayoutFactory = uvkuDescriptorSetLayoutFactory.TvkuDescriptorSetLayoutFactory; { Shader Modules } - TvkuShaderModule = uvkuShaderModule.TvkuShaderModule; - TvkuShaderModuleFactory = uvkuShaderModuleFactory.TvkuShaderModuleFactory; + TvkuShaderModule = uvkuShaderModule.TvkuShaderModule; + TvkuShaderModuleFactory = uvkuShaderModuleFactory.TvkuShaderModuleFactory; { Pipeline } - TvkuPipelineLayout = uvkuPipelineLayout.TvkuPipelineLayout; - TvkuPipelineLayoutFactory = uvkuPipelineLayoutFactory.TvkuPipelineLayoutFactory; - TvkuPipelineCache = uvkuPipelineCache.TvkuPipelineCache; - TvkuPipelineCacheFactory = uvkuPipelineCacheFactory.TvkuPipelineCacheFactory; - TvkuPipeline = uvkuPipeline.TvkuPipeline; - TvkuGraphicsPipeline = uvkuPipeline.TvkuGraphicsPipeline; - TvkuGraphicsPipelineFactory = uvkuPipelineFactory.TvkuGraphicsPipelineFactory; - TvkuComputePipeline = uvkuPipeline.TvkuComputePipeline; - TvkuComputePipelineFactory = uvkuPipelineFactory.TvkuComputePipelineFactory; + TvkuPipelineLayout = uvkuPipelineLayout.TvkuPipelineLayout; + TvkuPipelineLayoutFactory = uvkuPipelineLayoutFactory.TvkuPipelineLayoutFactory; + TvkuPipelineCache = uvkuPipelineCache.TvkuPipelineCache; + TvkuPipelineCacheFactory = uvkuPipelineCacheFactory.TvkuPipelineCacheFactory; + TvkuPipeline = uvkuPipeline.TvkuPipeline; + TvkuGraphicsPipeline = uvkuPipeline.TvkuGraphicsPipeline; + TvkuGraphicsPipelineFactory = uvkuPipelineFactory.TvkuGraphicsPipelineFactory; + TvkuComputePipeline = uvkuPipeline.TvkuComputePipeline; + TvkuComputePipelineFactory = uvkuPipelineFactory.TvkuComputePipelineFactory; { DescriptorPool } - TvkuDescriptorPool = uvkuDescriptorPool.TvkuDescriptorPool; - TvkuDescriptorPoolFactory = uvkuDescriptorPoolFactory.TvkuDescriptorPoolFactory; - TvkuDescriptorSet = uvkuDescriptorSet.TvkuDescriptorSet; + TvkuDescriptorPool = uvkuDescriptorPool.TvkuDescriptorPool; + TvkuDescriptorPoolFactory = uvkuDescriptorPoolFactory.TvkuDescriptorPoolFactory; + TvkuDescriptorSet = uvkuDescriptorSet.TvkuDescriptorSet; + + { Semaphore } + TvkuSemaphore = uvkuSemaphore.TvkuSemaphore; { Utils } - TvkuException = uvkuUtils.TvkuException; - TvkuErrorException = uvkuUtils.TvkuErrorException; - TvkuInvalidFuncPtrException = uvkuUtils.TvkuInvalidFuncPtrException; + TvkuException = uvkuUtils.TvkuException; + TvkuErrorException = uvkuUtils.TvkuErrorException; + TvkuInvalidFuncPtrException = uvkuUtils.TvkuInvalidFuncPtrException; function vkExtent2D(const X, Y: VkUint32): TVkExtent2D; function vkExtent3D(const X, Y, Z: VkUint32): TVkExtent3D; diff --git a/projects/utils/uvkuBuffer.pas b/projects/utils/uvkuBuffer.pas index b46390e..d8a1ff3 100644 --- a/projects/utils/uvkuBuffer.pas +++ b/projects/utils/uvkuBuffer.pas @@ -56,7 +56,7 @@ procedure TvkuBuffer.CreateHandle(const aCreateInfo: TVkBufferCreateInfo); var err: TVkResult; begin err := fDeviceCommands.vkCreateBuffer(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create buffer', err); end; @@ -65,7 +65,7 @@ procedure TvkuBuffer.BindMemory(const aMemory: VkDeviceMemory; const aOffset: Vk var err: TVkResult; begin err := fDeviceCommands.vkBindBufferMemory(fDeviceCommands.Device, fHandle, aMemory, aOffset); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to bind buffer memory', err); fMemory := aMemory; end; @@ -102,7 +102,7 @@ begin if not Assigned(aAllocCallbacks) then aAllocCallbacks := AllocCallbacks; err := fDeviceCommands.vkAllocateMemory(fDeviceCommands.Device, @MemAllocInfo, aAllocCallbacks, @Mem); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to allocate buffer memory', err); fBufferMemory := TvkuDeviceMemory.Create(Mem, true, fDeviceCommands, aAllocCallbacks); BindMemory(fBufferMemory.Handle, 0); diff --git a/projects/utils/uvkuBufferView.pas b/projects/utils/uvkuBufferView.pas index 3c85465..1e4cbd9 100644 --- a/projects/utils/uvkuBufferView.pas +++ b/projects/utils/uvkuBufferView.pas @@ -44,7 +44,7 @@ procedure TvkuBufferView.CreateHandle(const aCreateInfo: TVkBufferViewCreateInfo var err: TVkResult; begin err := fDeviceCommands.vkCreateBufferView(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create buffer view', err); end; diff --git a/projects/utils/uvkuCommandBuffer.pas b/projects/utils/uvkuCommandBuffer.pas index d407c3b..687af57 100644 --- a/projects/utils/uvkuCommandBuffer.pas +++ b/projects/utils/uvkuCommandBuffer.pas @@ -186,7 +186,7 @@ begin Info.flags := []; // TODO Info.pInheritanceInfo := nil; // TODO err := DeviceCommands.vkBeginCommandBuffer(fHandle, @Info); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to begin command buffer', err); end; @@ -195,7 +195,7 @@ procedure TvkuCommandBuffer.EndCommand; var err: TVkResult; begin err := fDeviceCommands.vkEndCommandBuffer(fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to end command buffer', err); end; diff --git a/projects/utils/uvkuCommandPool.pas b/projects/utils/uvkuCommandPool.pas index 43400f9..81f487d 100644 --- a/projects/utils/uvkuCommandPool.pas +++ b/projects/utils/uvkuCommandPool.pas @@ -54,7 +54,7 @@ procedure TvkuCommandPool.CreateHandle(const aCreateInfo: TVkCommandPoolCreateIn var err: TVkResult; begin err := fDeviceCommands.vkCreateCommandPool(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create command pool', err); end; @@ -78,7 +78,7 @@ begin AllocInfo.commandBufferCount := aCount; SetLength(result, aCount); err := fDeviceCommands.vkAllocateCommandBuffers(fDeviceCommands.Device, @AllocInfo, @result[0]); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create command buffers', err); end; diff --git a/projects/utils/uvkuDebugReporter.pas b/projects/utils/uvkuDebugReporter.pas index 1948fa0..e62b1a7 100644 --- a/projects/utils/uvkuDebugReporter.pas +++ b/projects/utils/uvkuDebugReporter.pas @@ -107,7 +107,7 @@ begin VK_DEBUG_REPORT_DEBUG_BIT_EXT ]; err := fInstanceCommands.vkCreateDebugReportCallbackEXT(fInstanceCommands.Instance, @CreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create debug report handle', err); end; diff --git a/projects/utils/uvkuDescriptorPool.pas b/projects/utils/uvkuDescriptorPool.pas index 5c7bf8b..a94fe84 100644 --- a/projects/utils/uvkuDescriptorPool.pas +++ b/projects/utils/uvkuDescriptorPool.pas @@ -55,7 +55,7 @@ begin if not Assigned(fDeviceCommands.vkCreateDescriptorPool) then raise TvkuInvalidFuncPtrException.Create('vkCreateDescriptorPool'); err := fDeviceCommands.vkCreateDescriptorPool(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create descriptor pool', err); end; @@ -81,7 +81,7 @@ begin AllocInfo.pSetLayouts := @aDescriptorSetLayouts[0]; SetLength(result, AllocInfo.descriptorSetCount); err := fDeviceCommands.vkAllocateDescriptorSets(fDeviceCommands.Device, @AllocInfo, @result[0]); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to allocate descriptor sets', err); end; @@ -98,7 +98,7 @@ begin if not Assigned(fDeviceCommands.vkFreeDescriptorSets) then raise TvkuInvalidFuncPtrException.Create('vkFreeDescriptorSets'); err := fDeviceCommands.vkFreeDescriptorSets(fDeviceCommands.Device, fHandle, Length(aDescriptorSets), @aDescriptorSets[0]); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to free descriptor sets', err); end; diff --git a/projects/utils/uvkuDescriptorSetLayout.pas b/projects/utils/uvkuDescriptorSetLayout.pas index a3b5a52..f811775 100644 --- a/projects/utils/uvkuDescriptorSetLayout.pas +++ b/projects/utils/uvkuDescriptorSetLayout.pas @@ -46,7 +46,7 @@ begin if not Assigned(fDeviceCommands.vkCreateDescriptorSetLayout) then raise TvkuInvalidFuncPtrException.Create('vkCreateDescriptorSetLayout'); err := fDeviceCommands.vkCreateDescriptorSetLayout(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create descriptor set layout', err); end; diff --git a/projects/utils/uvkuDevice.pas b/projects/utils/uvkuDevice.pas index 7159e33..3f8a072 100644 --- a/projects/utils/uvkuDevice.pas +++ b/projects/utils/uvkuDevice.pas @@ -113,6 +113,7 @@ type procedure FreeMemory( const aMemory: VkDeviceMemory; aAllocCallbacks: PVkAllocationCallbacks = nil); + procedure WaitIdle; function UpdateDescriptorSet: TvkuUpdateDescriptorSetHelper; @@ -333,7 +334,7 @@ begin if not Assigned(fInstanceCommands.vkCreateDevice) then raise TvkuInvalidFuncPtrException.Create('vkCreateDevice'); err := fInstanceCommands.vkCreateDevice(aPhyDevice, aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create device', err); fDeviceCommands := LoadDeviceCommands(fInstanceCommands.Instance, fHandle); if not Assigned(fDeviceCommands) then @@ -365,7 +366,7 @@ begin if not Assigned(aAllocCallbacks) then aAllocCallbacks := AllocCallbacks; err := fDeviceCommands.vkAllocateMemory(fHandle, @AllocInfo, aAllocCallbacks, @result); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to allocate device memory', err); end; @@ -377,6 +378,15 @@ begin fDeviceCommands.vkFreeMemory(fHandle, aMemory, aAllocCallbacks); end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuDevice.WaitIdle; +var err: TVkResult; +begin + err := fDeviceCommands.vkDeviceWaitIdle(fHandle); + if (err <> VK_SUCCESS) then + raise TvkuErrorException.Create('unable to wait for device idle', err); +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// function TvkuDevice.UpdateDescriptorSet: TvkuUpdateDescriptorSetHelper; begin diff --git a/projects/utils/uvkuDeviceFactory.pas b/projects/utils/uvkuDeviceFactory.pas index 6d6db35..0152e45 100644 --- a/projects/utils/uvkuDeviceFactory.pas +++ b/projects/utils/uvkuDeviceFactory.pas @@ -103,14 +103,14 @@ type fvkEnabledExtensionNames: array of PVkChar; fvkQueueCreateInfos: array of TVkDeviceQueueCreateInfo; - function GetLayers: TStrings; - function GetExtensions: TStrings; + function GetEnabledLayerNames: TStrings; + function GetEnabledExtensionNames: TStrings; public - property Flags: VkDeviceCreateFlags read fFlags write fFlags; - property EnabledLayers: TStrings read GetLayers; - property EnabledExtensions: TStrings read GetExtensions; - property EnabledFeatures: TvkuPhysicalDeviceFeatures read fEnabledFeatures; - property QueueCreateInfos: TvkuQueueCreateInfoList read fQueueCreateInfos; + property Flags: VkDeviceCreateFlags read fFlags write fFlags; + property EnabledLayerNames: TStrings read GetEnabledLayerNames; + property EnabledExtensionNames: TStrings read GetEnabledExtensionNames; + property EnabledFeatures: TvkuPhysicalDeviceFeatures read fEnabledFeatures; + property QueueCreateInfos: TvkuQueueCreateInfoList read fQueueCreateInfos; function GetStructure: TVkDeviceCreateInfo; procedure SetStructure(const aData: TVkDeviceCreateInfo); @@ -288,13 +288,13 @@ end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //TvkuDeviceFactory////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuDeviceFactory.GetLayers: TStrings; +function TvkuDeviceFactory.GetEnabledLayerNames: TStrings; begin result := fEnabledLayerNames; end; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -function TvkuDeviceFactory.GetExtensions: TStrings; +function TvkuDeviceFactory.GetEnabledExtensionNames: TStrings; begin result := fEnabledExtensionNames; end; diff --git a/projects/utils/uvkuDeviceMemory.pas b/projects/utils/uvkuDeviceMemory.pas index 7cc6ed3..b3b1a40 100644 --- a/projects/utils/uvkuDeviceMemory.pas +++ b/projects/utils/uvkuDeviceMemory.pas @@ -47,7 +47,7 @@ begin if not Assigned(fDeviceCommands.vkAllocateMemory) then raise TvkuInvalidFuncPtrException.Create('vkAllocateMemory'); err := fDeviceCommands.vkAllocateMemory(fDeviceCommands.Device, @aAllocInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to allocate device memory', err); end; @@ -56,7 +56,7 @@ function TvkuDeviceMemory.Map(const aOffset: VkDeviceSize; aSize: VkDeviceSize; var err: TVkResult; begin err := fDeviceCommands.vkMapMemory(fDeviceCommands.Device, fHandle, aOffset, aSize, aFlags, @result); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to map device memory', err); end; diff --git a/projects/utils/uvkuFrameBuffer.pas b/projects/utils/uvkuFrameBuffer.pas index 3dde8b6..5a779bb 100644 --- a/projects/utils/uvkuFrameBuffer.pas +++ b/projects/utils/uvkuFrameBuffer.pas @@ -46,7 +46,7 @@ begin if not Assigned(fDeviceCommands.vkCreateFramebuffer) then raise TvkuInvalidFuncPtrException.Create('vkCreateFramebuffer'); err := fDeviceCommands.vkCreateFramebuffer(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create frame buffer', err); end; diff --git a/projects/utils/uvkuImage.pas b/projects/utils/uvkuImage.pas index 37bf80e..fa85e68 100644 --- a/projects/utils/uvkuImage.pas +++ b/projects/utils/uvkuImage.pas @@ -60,7 +60,7 @@ procedure TvkuImage.CreateHandle(const aCreateInfo: TVkImageCreateInfo); var err: TVkResult; begin err := fDeviceCommands.vkCreateImage(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then TvkuErrorException.Create('unable to create image', err); end; @@ -86,8 +86,8 @@ begin result.dstAccessMask := []; result.oldLayout := aOldLayout; result.newLayout := aNewLayout; - result.srcQueueFamilyIndex := 0; - result.dstQueueFamilyIndex := 0; + result.srcQueueFamilyIndex := VK_QUEUE_FAMILY_IGNORED; + result.dstQueueFamilyIndex := VK_QUEUE_FAMILY_IGNORED; result.image := fHandle; result.subresourceRange := range; @@ -159,7 +159,7 @@ procedure TvkuImage.BindMemory(const aMemory: VkDeviceMemory; const aOffset: VkD var err: TVkResult; begin err := fDeviceCommands.vkBindImageMemory(fDeviceCommands.Device, fHandle, aMemory, aOffset); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then TvkuErrorException.Create('unable to bind image memory', err); fMemory := aMemory; end; @@ -195,7 +195,7 @@ begin if not Assigned(aAllocCallbacks) then aAllocCallbacks := AllocCallbacks; err := fDeviceCommands.vkAllocateMemory(fDeviceCommands.Device, @MemAllocInfo, aAllocCallbacks, @Mem); - if (err < VK_SUCCESS) then + 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); diff --git a/projects/utils/uvkuImageView.pas b/projects/utils/uvkuImageView.pas index e4ec45a..c955574 100644 --- a/projects/utils/uvkuImageView.pas +++ b/projects/utils/uvkuImageView.pas @@ -46,7 +46,7 @@ begin if not Assigned(fDeviceCommands.vkCreateImageView) then raise TvkuInvalidFuncPtrException.Create('vkCreateImageView'); err := fDeviceCommands.vkCreateImageView(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create image view', err); end; diff --git a/projects/utils/uvkuInstance.pas b/projects/utils/uvkuInstance.pas index bb00a81..6c64fed 100644 --- a/projects/utils/uvkuInstance.pas +++ b/projects/utils/uvkuInstance.pas @@ -52,12 +52,12 @@ begin exit; err := InstanceCommands.vkEnumeratePhysicalDevices(fHandle, @c, nil); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device number', err); SetLength(fPhysicalDevices, c); err := InstanceCommands.vkEnumeratePhysicalDevices(fHandle, @c, @fPhysicalDevices[0]); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical devices', err); end; @@ -66,7 +66,7 @@ procedure TvkuInstance.CreateHandle(const aCreateInfo: PVkInstanceCreateInfo); var e: TVkResult; begin e := vkCreateInstance(aCreateInfo, AllocCallbacks, @fHandle); - if (e < VK_SUCCESS) then + if (e <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create vulkan instance', e); fInstanceCommands := LoadInstanceCommands(fHandle); if not Assigned(InstanceCommands) then diff --git a/projects/utils/uvkuPhysicalDevice.pas b/projects/utils/uvkuPhysicalDevice.pas index 33ce6d5..70dd4fb 100644 --- a/projects/utils/uvkuPhysicalDevice.pas +++ b/projects/utils/uvkuPhysicalDevice.pas @@ -114,7 +114,7 @@ begin if not Assigned(fInstanceCommands.vkGetPhysicalDeviceImageFormatProperties) then raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceImageFormatProperties'); err := fInstanceCommands.vkGetPhysicalDeviceImageFormatProperties(fHandle, aFormat, aImageType, aTiling, aUsage, aFlags, @result); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device image format properties', err); end; @@ -140,7 +140,7 @@ begin if not Assigned(fInstanceCommands.vkGetPhysicalDeviceSurfaceSupportKHR) then raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceSurfaceSupportKHR', 'VK_KHR_surface'); err := fInstanceCommands.vkGetPhysicalDeviceSurfaceSupportKHR(fHandle, aQueueFamilyIndex, aSurface, @b); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device surface support', err); result := (b <> 0); end; @@ -153,7 +153,7 @@ begin if not Assigned(fInstanceCommands.vkGetPhysicalDeviceSurfaceCapabilitiesKHR) then raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceSurfaceCapabilitiesKHR', 'VK_KHR_surface'); err := fInstanceCommands.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(fHandle, aSurface, @result); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device surface capabilities', err); end; @@ -179,11 +179,11 @@ begin if not Assigned(fInstanceCommands.vkGetPhysicalDeviceSurfacePresentModesKHR) then raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceSurfacePresentModesKHR', 'VK_KHR_surface'); err := fInstanceCommands.vkGetPhysicalDeviceSurfacePresentModesKHR(fHandle, aSurface, @c, nil); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device surface present mode count', err); SetLength(result, c); err := fInstanceCommands.vkGetPhysicalDeviceSurfacePresentModesKHR(fHandle, aSurface, @c, @result[0]); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device surface present modes', err); end; @@ -197,11 +197,11 @@ begin if not Assigned(fInstanceCommands.vkGetPhysicalDeviceDisplayPropertiesKHR) then raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceDisplayPropertiesKHR', 'VK_KHR_display'); err := fInstanceCommands.vkGetPhysicalDeviceDisplayPropertiesKHR(fHandle, @c, nil); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device display property count', err); SetLength(result, c); err := fInstanceCommands.vkGetPhysicalDeviceDisplayPropertiesKHR(fHandle, @c, @result[0]); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device display properties', err); end; @@ -215,11 +215,11 @@ begin if not Assigned(fInstanceCommands.vkGetPhysicalDeviceDisplayPlanePropertiesKHR) then raise TvkuInvalidFuncPtrException.Create('vkGetPhysicalDeviceDisplayPlanePropertiesKHR', 'VK_KHR_display'); err := fInstanceCommands.vkGetPhysicalDeviceDisplayPlanePropertiesKHR(fHandle, @c, nil); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device display plane property count', err); SetLength(result, c); err := fInstanceCommands.vkGetPhysicalDeviceDisplayPlanePropertiesKHR(fHandle, @c, @result[0]); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get physical device display plane properties', err); end; @@ -233,11 +233,11 @@ begin if not Assigned(fInstanceCommands.vkGetDisplayPlaneSupportedDisplaysKHR) then raise TvkuInvalidFuncPtrException.Create('vkGetDisplayPlaneSupportedDisplaysKHR', 'VK_KHR_display'); err := fInstanceCommands.vkGetDisplayPlaneSupportedDisplaysKHR(fHandle, aPlaneIndex, @c, nil); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get supported display plane count', err); SetLength(result, c); err := fInstanceCommands.vkGetDisplayPlaneSupportedDisplaysKHR(fHandle, aPlaneIndex, @c, @result[0]); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get supported display planes', err); end; @@ -251,11 +251,11 @@ begin if not Assigned(fInstanceCommands.vkGetDisplayModePropertiesKHR) then raise TvkuInvalidFuncPtrException.Create('vkGetDisplayModePropertiesKHR', 'VK_KHR_display'); err := fInstanceCommands.vkGetDisplayModePropertiesKHR(fHandle, aDisplay, @c, nil); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get display mode property count', err); SetLength(result, c); err := fInstanceCommands.vkGetDisplayModePropertiesKHR(fHandle, aDisplay, @c, @result[0]); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get display mode properties', err); end; diff --git a/projects/utils/uvkuPipeline.pas b/projects/utils/uvkuPipeline.pas index af9c186..e83010d 100644 --- a/projects/utils/uvkuPipeline.pas +++ b/projects/utils/uvkuPipeline.pas @@ -87,7 +87,7 @@ begin if not Assigned(fDeviceCommands.vkCreateGraphicsPipelines) then raise TvkuInvalidFuncPtrException.Create('vkCreateGraphicsPipelines'); err := fDeviceCommands.vkCreateGraphicsPipelines(fDeviceCommands.Device, aPipelineCache, 1, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create graphics pipeline', err); end; @@ -110,7 +110,7 @@ begin if not Assigned(fDeviceCommands.vkCreateComputePipelines) then raise TvkuInvalidFuncPtrException.Create('vkCreateComputePipelines'); err := fDeviceCommands.vkCreateComputePipelines(fDeviceCommands.Device, aPipelineCache, 1, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create compute pipeline', err); end; diff --git a/projects/utils/uvkuPipelineCache.pas b/projects/utils/uvkuPipelineCache.pas index 38bc57c..60f9ef0 100644 --- a/projects/utils/uvkuPipelineCache.pas +++ b/projects/utils/uvkuPipelineCache.pas @@ -44,7 +44,7 @@ procedure TvkuPipelineCache.CreateHandle(const aCreateInfo: TVkPipelineCacheCrea var err: TVkResult; begin err := fDeviceCommands.vkCreatePipelineCache(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then TvkuErrorException.Create('unable to create pipeline cache', err); end; diff --git a/projects/utils/uvkuPipelineLayout.pas b/projects/utils/uvkuPipelineLayout.pas index e02aa14..4e9931b 100644 --- a/projects/utils/uvkuPipelineLayout.pas +++ b/projects/utils/uvkuPipelineLayout.pas @@ -46,7 +46,7 @@ begin if not Assigned(fDeviceCommands.vkCreatePipelineLayout) then raise TvkuInvalidFuncPtrException.Create('vkCreatePipelineLayout'); err := fDeviceCommands.vkCreatePipelineLayout(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create pipeline layout', err); end; diff --git a/projects/utils/uvkuQueue.pas b/projects/utils/uvkuQueue.pas index 0391359..999d343 100644 --- a/projects/utils/uvkuQueue.pas +++ b/projects/utils/uvkuQueue.pas @@ -6,7 +6,7 @@ interface uses Classes, SysUtils, - Vulkan, uvkuBase; + Vulkan, uvkuBase, uvkuTypes; type ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -24,6 +24,10 @@ type const aCommandBuffers: array of VkCommandBuffer; const aSignalSemaphores: array of VkSemaphore; const aFence: VkFence); + function Present( + const aWaitSemaphore: array of VkSemaphore; + const aSwapChains: array of VkSwapchainKHR; + const aImageIndices: array of VkUint32): TVkResultArr; procedure WaitIdle; constructor Create( @@ -49,8 +53,9 @@ 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'); + if (Length(aWaitSemaphores) <> Length(aWaitDstStageMask)) + and (Length(aWaitDstStageMask) <> 0) then + raise TvkuException.Create('aWaitDstStageMask must have the same number of elements as aWaitSemaphores or must be empty'); FillByte(SubmitInfo, SizeOf(SubmitInfo), 0); SubmitInfo.sType := VK_STRUCTURE_TYPE_SUBMIT_INFO; @@ -63,16 +68,43 @@ begin SubmitInfo.signalSemaphoreCount := Length(aSignalSemaphores); SubmitInfo.pSignalSemaphores := @aSignalSemaphores[0]; err := fDeviceCommands.vkQueueSubmit(fHandle, 1, @SubmitInfo, aFence); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to submit queue', err); end; +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +function TvkuQueue.Present( + const aWaitSemaphore: array of VkSemaphore; + const aSwapChains: array of VkSwapchainKHR; + const aImageIndices: array of VkUint32): TVkResultArr; +var + info: TVkPresentInfoKHR; + err: TVkResult; +begin + if (Length(aSwapChains) <> Length(aImageIndices)) then + raise TvkuException.Create('aSwapChains and aImageIndices must have the same number of elements'); + + SetLength(result, Length(aSwapChains)); + FillByte(info, SizeOf(info), 0); + info.sType := VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + info.pNext := nil; + info.waitSemaphoreCount := Length(aWaitSemaphore); + info.pWaitSemaphores := @aWaitSemaphore[0]; + info.swapchainCount := Length(aSwapChains); + info.pSwapchains := @aSwapChains[0]; + info.pImageIndices := @aImageIndices[0]; + info.pResults := @result[0]; + err := fDeviceCommands.vkQueuePresentKHR(fHandle, @info); + if (err <> VK_SUCCESS) then + raise TvkuErrorException.Create('unable to present queue', err); +end; + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// procedure TvkuQueue.WaitIdle; var err: TVkResult; begin err := fDeviceCommands.vkQueueWaitIdle(fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('error while waiting for queue', err); end; diff --git a/projects/utils/uvkuRenderPass.pas b/projects/utils/uvkuRenderPass.pas index 861f15e..a5a7ca9 100644 --- a/projects/utils/uvkuRenderPass.pas +++ b/projects/utils/uvkuRenderPass.pas @@ -46,7 +46,7 @@ begin if not Assigned(fDeviceCommands.vkCreateRenderPass) then raise TvkuInvalidFuncPtrException.Create('vkCreateRenderPass'); err := fDeviceCommands.vkCreateRenderPass(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create render pass', err); end; diff --git a/projects/utils/uvkuSemaphore.pas b/projects/utils/uvkuSemaphore.pas new file mode 100644 index 0000000..db6d43f --- /dev/null +++ b/projects/utils/uvkuSemaphore.pas @@ -0,0 +1,100 @@ +unit uvkuSemaphore; + +{$mode objfpc}{$H+} + +interface + +uses + Classes, SysUtils, + Vulkan, uvkuBase; + +type +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + TvkuSemaphore = class(TvkuAllocHandle) + private + fHandle: VkSemaphore; + fDeviceCommands: TVkDeviceCommands; + + procedure CreateHandle(const aCreateInfo: TVkSemaphoreCreateInfo); + public + property Handle: VkSemaphore read fHandle; + property DeviceCommands: TVkDeviceCommands read fDeviceCommands; + + constructor Create( + const aFlags: VkSemaphoreCreateFlags; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + constructor Create( + const aCreateInfo: TVkSemaphoreCreateInfo; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + constructor Create( + const aHandle: VkSemaphore; + const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks = nil); + destructor Destroy; override; + end; + +implementation + +uses + uvkuUtils; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//TvkuSemaphore////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +procedure TvkuSemaphore.CreateHandle(const aCreateInfo: TVkSemaphoreCreateInfo); +var err: TVkResult; +begin + if not Assigned(fDeviceCommands.vkCreateSemaphore) then + raise TvkuInvalidFuncPtrException.Create('vkCreateSemaphore'); + err := fDeviceCommands.vkCreateSemaphore(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); + if (err <> VK_SUCCESS) then + raise TvkuErrorException.Create('unable to create semaphore', err); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuSemaphore.Create(const aFlags: VkSemaphoreCreateFlags; const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks); +var CreateInfo: TVkSemaphoreCreateInfo; +begin + FillByte(CreateInfo, SizeOf(CreateInfo), 0); + CreateInfo.sType := VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + CreateInfo.pNext := nil; + CreateInfo.flags := aFlags; + Create(CreateInfo, aDeviceCommands, aAllocCallbacks); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuSemaphore.Create(const aCreateInfo: TVkSemaphoreCreateInfo; const aDeviceCommands: TVkDeviceCommands; + const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fDeviceCommands := aDeviceCommands; + SetAllocCallbacks(aAllocCallbacks); + CreateHandle(aCreateInfo); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +constructor TvkuSemaphore.Create(const aHandle: VkSemaphore; const aOwnsHandle: Boolean; + const aDeviceCommands: TVkDeviceCommands; const aAllocCallbacks: PVkAllocationCallbacks); +begin + inherited Create; + fHandle := aHandle; + fDeviceCommands := aDeviceCommands; + OwnsHandle := aOwnsHandle; + SetAllocCallbacks(aAllocCallbacks); +end; + +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +destructor TvkuSemaphore.Destroy; +begin + if OwnsHandle and (fHandle <> VK_INVALID_NDP_HANDLE) then + fDeviceCommands.vkDestroySemaphore(fDeviceCommands.Device, fHandle, AllocCallbacks); + fHandle := VK_INVALID_NDP_HANDLE; + inherited Destroy; +end; + +end. + diff --git a/projects/utils/uvkuShaderModule.pas b/projects/utils/uvkuShaderModule.pas index 0834d11..d5e1f3d 100644 --- a/projects/utils/uvkuShaderModule.pas +++ b/projects/utils/uvkuShaderModule.pas @@ -46,7 +46,7 @@ begin if not Assigned(fDeviceCommands.vkCreateShaderModule) then raise TvkuInvalidFuncPtrException.Create('vkCreateShaderModule'); err := fDeviceCommands.vkCreateShaderModule(fDeviceCommands.Device, @aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create shader module', err); end; diff --git a/projects/utils/uvkuSurface.pas b/projects/utils/uvkuSurface.pas index ddb5dd8..b8ac585 100644 --- a/projects/utils/uvkuSurface.pas +++ b/projects/utils/uvkuSurface.pas @@ -56,7 +56,7 @@ begin raise TvkuInvalidFuncPtrException.Create('vkCreateWin32SurfaceKHR', 'VK_KHR_win32_surface'); err := fInstanceCommands.vkCreateWin32SurfaceKHR(fInstanceCommands.Instance, aCreateInfo, AllocCallbacks, @fHandle); {$ENDIF} - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create surface', err); end; diff --git a/projects/utils/uvkuSwapChain.pas b/projects/utils/uvkuSwapChain.pas index 6d5e2b6..3195e3b 100644 --- a/projects/utils/uvkuSwapChain.pas +++ b/projects/utils/uvkuSwapChain.pas @@ -49,7 +49,7 @@ begin if not Assigned(fDeviceCommands.vkCreateSwapchainKHR) then raise TvkuException.Create('invalid function pointer: vkCreateSwapchainKHR; did you enabled the VK_KHR_swapchain extension?'); err := fDeviceCommands.vkCreateSwapchainKHR(fDeviceCommands.Device, aCreateInfo, AllocCallbacks, @fHandle); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to create swap chain', err); end; @@ -62,11 +62,11 @@ begin if not Assigned(fDeviceCommands.vkGetSwapchainImagesKHR) then raise TvkuInvalidFuncPtrException.Create('vkGetSwapchainImagesKHR', 'VK_KHR_swapchain'); err := fDeviceCommands.vkGetSwapchainImagesKHR(fDeviceCommands.Device, fHandle, @c, nil); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get swap chain image count', err); SetLength(result, c); err := fDeviceCommands.vkGetSwapchainImagesKHR(fDeviceCommands.Device, fHandle, @c, @result[0]); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to get swap chain images', err); end; @@ -78,7 +78,7 @@ begin if not Assigned(fDeviceCommands.vkAcquireNextImageKHR) then raise TvkuInvalidFuncPtrException.Create('vkAcquireNextImageKHR', 'VK_KHR_swapchain'); err := fDeviceCommands.vkAcquireNextImageKHR(fDeviceCommands.Device, fHandle, aTimeout, aSemaphore, aFence, @result); - if (err < VK_SUCCESS) then + if (err <> VK_SUCCESS) then raise TvkuErrorException.Create('unable to aquire next image', err); end; diff --git a/projects/utils/uvkuTypes.pas b/projects/utils/uvkuTypes.pas index 52aa47c..c6b7231 100644 --- a/projects/utils/uvkuTypes.pas +++ b/projects/utils/uvkuTypes.pas @@ -97,6 +97,7 @@ type TVkDescriptorImageInfoArr = array of TVkDescriptorImageInfo; TVkDescriptorBufferInfoArr = array of TVkDescriptorBufferInfo; TVkClearValueArr = array of TVkClearValue; + TVkResultArr = array of TVkResult; TVkUint32List = specialize TvkuList; TVkFloatList = specialize TvkuList;