void drawFrame()
        {
            int imageIndex;

            Vulkan.vkAcquireNextImageKHR(device, swapChain, long.MaxValue, imageAvailableSemaphore, null, out imageIndex);

            VkSubmitInfo submitInfo = new VkSubmitInfo();

            submitInfo.sType = VkStructureType.VK_STRUCTURE_TYPE_SUBMIT_INFO;

            VkSemaphore[]             waitSemaphores = new VkSemaphore[] { imageAvailableSemaphore };
            VkPipelineStageFlagBits[] waitStages     = new VkPipelineStageFlagBits[] { VkPipelineStageFlagBits.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
            submitInfo.waitSemaphoreCount = 1;
            submitInfo.pWaitSemaphores    = waitSemaphores;
            submitInfo.pWaitDstStageMask  = waitStages;

            submitInfo.commandBufferCount = 1;
            submitInfo.pCommandBuffers    = new VkCommandBuffer[] { commandBuffers[imageIndex] };

            VkSemaphore[] signalSemaphores = new VkSemaphore[] { renderFinishedSemaphore };
            submitInfo.signalSemaphoreCount = 1;
            submitInfo.pSignalSemaphores    = signalSemaphores;

            fpsSubmitQueue.Begin();
            VkResult result = Vulkan.vkQueueSubmit(graphicsQueue, 1, new VkSubmitInfo[] { submitInfo }, null);

            fpsSubmitQueue.End(); fpsSubmitQueue.DebugPeriodicReport();

            if (result != VkResult.VK_SUCCESS)
            {
                throw Program.Throw("failed to submit draw command buffer!");
            }

            VkPresentInfoKHR presentInfo = new VkPresentInfoKHR();

            presentInfo.sType = VkStructureType.VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;

            presentInfo.waitSemaphoreCount = 1;
            presentInfo.pWaitSemaphores    = signalSemaphores;

            VkSwapchainKHR[] swapChains = new VkSwapchainKHR[] { swapChain };
            presentInfo.swapchainCount = 1;
            presentInfo.pSwapchains    = swapChains;
            presentInfo.pImageIndices  = new int[] { imageIndex };

            fpsPresentQueue.Begin();
            Vulkan.vkQueuePresentKHR(presentQueue, presentInfo);
            fpsPresentQueue.End(); fpsPresentQueue.DebugPeriodicReport();

            Vulkan.vkQueueWaitIdle(presentQueue);
        }