Guest User

Vulkan nVidia Presentation Queue Fail Case

a guest
May 21st, 2016
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 18.10 KB | None | 0 0
  1. /*
  2.  *  Minimum test case I could come up with. No return values checked, no error handling,
  3.  *  no cleanup, and assumes the exact capabilities of my setup (detailed below). And yeah,
  4.  *  it's still pretty big. Yay Vulkan verbosity.
  5.  *
  6.  * Problem:
  7.  *  When using more than two different queues (one after another, no multi-threading
  8.  *  needed) for the presenting of swapchain images, things grind to a halt. I first
  9.  *  encountered this using multiple swapchains with multiple surfaces, using one unique
  10.  *  queue per swapchain. But the same trouble occurs when using only a single swapchain.
  11.  *  The first six frames render properly, no matter the combination of swapchain size
  12.  *  and number of queues used.
  13.  *
  14.  * Update:
  15.  *  By replacing vkQueueWaitIdle() with an empty vkQueueSubmit() and vkWaitForFences()
  16.  *  the program is now stable with three queues, but breaks at four queues or more. For
  17.  *  some reason this also causes one more successful frame to render before stalling, i.e.
  18.  *  seven instead of six. Behavior is otherwise identical to the previous version.
  19.  *
  20.  *  See the comments for the two defines QUEUECOUNT and SWAPCHAINSIZE, and change their
  21.  *  values to test the breaking cases. Changing presentation modes has had no effect
  22.  *  other than immediate mode finishing the first six frames more quickly than FIFO mode,
  23.  *  before stalling.
  24.  *
  25.  *  Problem found on a GTX 780, with nVidia drivers 364.19 for Linux, Linux kernel 4.5.4,
  26.  *  on X11 with Xfce as display manager. And a 4Ghz Intel i7 CPU, in case it's a timing
  27.  *  issue for the first few presented images. Compiled with GCC 5.3.0.
  28.  *
  29.  *  Build depends on SDL2, X11, and Vulkan.
  30.  *
  31.  * Compiled with:
  32.  *  g++ -std=c++14 -O3 -I/path/to/vulkan/include/ -lSDL2 -lvulkan -o broken main.cpp
  33.  *
  34.  *  Different optimization levels had no effect.
  35.  *
  36.  *  Warning: When left to its own devices with 4 or more queues, this program makes my
  37.  *  machine completely unresponsive. Use something like the Linux 'timeout' tool to send
  38.  *  a SIGKILL after a minute or two, or you're gonna end up power cycling.
  39.  */
  40.  
  41. #include <iostream>
  42.  
  43. #include "SDL2/SDL.h"
  44. #include "SDL2/SDL_syswm.h"
  45. #define VK_USE_PLATFORM_XLIB_KHR
  46. #include "vulkan/vulkan.h"
  47.  
  48. /* Works fine with a queue count of 1, 2 or 3, breaks at 4 or anything higher. */
  49. #define QUEUECOUNT 4
  50. /*
  51.  * Failure behavior seems affected by the number of images in the swapchain.
  52.  * At 2 images, the program hangs while waiting for the command buffer fence.
  53.  * At 3 or more images, the program exits with a device lost error on command submit.
  54.  */
  55. #define SWAPCHAINSIZE 2
  56.  
  57. // Global all the things.
  58. VkDevice renderDevice;
  59. VkSwapchainKHR swapchains[1];
  60. VkSemaphore swapchainSemaphores[1];
  61. VkSemaphore signalSemaphores[1];
  62. VkFence fences[1];
  63. VkFence idlewaitfence[1];
  64. VkCommandBuffer commandBuffer[1];
  65.  
  66. // Prototypes so you don't have to scroll all the way down to main. You're welcome.
  67. bool shouldTerminate();
  68. void init();
  69. SDL_Window* initSDL();
  70. VkInstance initVulkanInstance();
  71. VkSurfaceKHR initVulkanSurface(VkInstance instance, SDL_Window* sdlwindow);
  72. void initVulkanRenderDevice(VkInstance instance);
  73. void initVulkanSwapchain(VkSurfaceKHR surface);
  74. void initVulkanCommandBuffers();
  75. void initVulkanSynchronizationPrimitives();
  76.  
  77. /* Look at me, I'm important! */
  78. int main(int, const char**)
  79. {
  80.     init();
  81.  
  82.     // Bunch of variable filling, blah blah, skip to the loop below this.
  83.     uint32_t imageIndex = 0, roundRobin = 0, frameCount = 0;
  84.     VkClearColorValue clearColor = {{0.6, 0.2, 0.2, 1.0}};
  85.     VkImage imageArray[SWAPCHAINSIZE];
  86.     uint32_t imageCount = SWAPCHAINSIZE;
  87.     vkGetSwapchainImagesKHR(renderDevice, swapchains[0], &imageCount, imageArray);
  88.     VkPipelineStageFlags stages[1] = {VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT};
  89.     VkCommandBufferBeginInfo bufferBeginInfo;
  90.     bufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  91.     bufferBeginInfo.pNext = NULL;
  92.     bufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
  93.     bufferBeginInfo.pInheritanceInfo = NULL;
  94.     VkImageSubresourceRange subRanges;
  95.     subRanges.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  96.     subRanges.baseMipLevel = 0;
  97.     subRanges.levelCount = 1;
  98.     subRanges.baseArrayLayer = 0;
  99.     subRanges.layerCount = 1;
  100.     VkImageMemoryBarrier imageBarriers[1];
  101.     imageBarriers[0].sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  102.     imageBarriers[0].pNext = NULL;
  103.     imageBarriers[0].srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  104.     imageBarriers[0].dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  105.     imageBarriers[0].image = imageArray[imageIndex];
  106.     imageBarriers[0].subresourceRange = subRanges;
  107.     VkSubmitInfo submitInfo;
  108.     submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  109.     submitInfo.pNext = NULL;
  110.     submitInfo.waitSemaphoreCount = 1;
  111.     submitInfo.pWaitSemaphores = swapchainSemaphores;
  112.     submitInfo.pWaitDstStageMask = stages;
  113.     submitInfo.commandBufferCount = 1;
  114.     submitInfo.signalSemaphoreCount = 1;
  115.     submitInfo.pSignalSemaphores = signalSemaphores;
  116.     VkPresentInfoKHR presentInfo;
  117.     presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  118.     presentInfo.pNext = NULL;
  119.     presentInfo.waitSemaphoreCount = 1;
  120.     presentInfo.pWaitSemaphores = signalSemaphores;
  121.     presentInfo.swapchainCount = 1;
  122.     presentInfo.pSwapchains = swapchains;
  123.     presentInfo.pResults = NULL;
  124.  
  125.     VkQueue queues[16];
  126.  
  127.     // Prefetch handles for all queues.
  128.     for (int i = 0; i < 16; ++i)
  129.         vkGetDeviceQueue(renderDevice, 0, i, &queues[i]);
  130.  
  131.     // Run until escape is pressed, the window is closed, VK_ERROR_DEVICE_LOST is encountered,
  132.     // or, well, forever, if we hang on the fence.
  133.     while (!shouldTerminate())
  134.     {
  135.         // Reset the buffer, fetch the image (which never blocks), and record the simple commands to clear the image.
  136.         vkResetCommandBuffer(commandBuffer[0], 0);
  137.         vkAcquireNextImageKHR(renderDevice, swapchains[0], 0, swapchainSemaphores[0], VK_NULL_HANDLE, &imageIndex);
  138.         vkBeginCommandBuffer(commandBuffer[0], &bufferBeginInfo);
  139.         imageBarriers[0].srcAccessMask = 0;
  140.         imageBarriers[0].dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  141.         imageBarriers[0].oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  142.         imageBarriers[0].newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  143.         vkCmdPipelineBarrier(commandBuffer[0], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
  144.                              0, 0, NULL, 0, NULL, 1, imageBarriers);
  145.         vkCmdClearColorImage(commandBuffer[0], imageArray[imageIndex], VK_IMAGE_LAYOUT_GENERAL,
  146.                              &clearColor, 1, &subRanges);
  147.         imageBarriers[0].srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
  148.         imageBarriers[0].dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
  149.         imageBarriers[0].oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
  150.         imageBarriers[0].newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  151.         vkCmdPipelineBarrier(commandBuffer[0], VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
  152.                              0, 0, NULL, 0, NULL, 1, imageBarriers);
  153.         vkEndCommandBuffer(commandBuffer[0]);
  154.  
  155.         submitInfo.pCommandBuffers = commandBuffer;
  156.         VkQueue queue = queues[roundRobin];
  157.  
  158.         if (vkQueueSubmit(queue, 1, &submitInfo, fences[0]) == VK_ERROR_DEVICE_LOST)
  159.         {
  160.             std::cout << "vkQueueSubmit() returned VK_ERROR_DEVICE_LOST\n" << std::endl;
  161.             abort();
  162.         }
  163.  
  164.         // When this hangs, it hangs. The GPU seems to lock right up, so be sure to have a watchdog that
  165.         // kills the program after some sane period.
  166.         std::cout << "Waiting for fence... " << std::flush;
  167.         while (vkWaitForFences(renderDevice, 1, fences, VK_TRUE, 100) == VK_TIMEOUT);
  168.         std::cout << "Done.\n";
  169.  
  170.         vkResetFences(renderDevice, 1, fences);
  171.  
  172.         uint32_t imageIndices[1] = {imageIndex};
  173.         presentInfo.pImageIndices = imageIndices;
  174.  
  175.         // This is the most common point of stalling when using more than three queues for presentation.
  176.         std::cout << "Waiting for present... " << std::flush;
  177.         if (vkQueuePresentKHR(queue, &presentInfo) == VK_ERROR_DEVICE_LOST)
  178.         {
  179.             std::cout << "Failed.\nvkQueuePresentKHR() returned VK_ERROR_DEVICE_LOST\n" << std::endl;;
  180.             abort();
  181.         }
  182.         std::cout << "Done.\n";
  183.  
  184.         // This replaces an earlier vkQueueWaitIdle(), and gives us one more queue to use before breaking.
  185.         std::cout << "Waiting for queue completion fence... " << std::flush;
  186.         vkQueueSubmit(queue, 0, NULL, idlewaitfence[0]);
  187.         while (vkWaitForFences(renderDevice, 1, idlewaitfence, VK_TRUE, 10) == VK_TIMEOUT);
  188.         vkResetFences(renderDevice, 1, idlewaitfence);
  189.         std::cout << "Done.\n";
  190.  
  191.         ++frameCount;
  192.         std::cout << "Finished frame " << frameCount << " on queue " << roundRobin << " for image with index "
  193.                   << imageIndex << "\n" << std::endl;
  194.  
  195.         ++roundRobin;
  196.         if (roundRobin >= QUEUECOUNT)
  197.             roundRobin = 0;
  198.     }
  199.  
  200.     return 0;
  201. }
  202.  
  203. bool shouldTerminate()
  204. {
  205.     SDL_Event event;
  206.  
  207.     while (SDL_PollEvent(&event))
  208.     {
  209.         switch (event.type)
  210.         {
  211.             case SDL_KEYUP:
  212.                 if (event.key.keysym.sym == SDLK_ESCAPE)
  213.                     return true;
  214.                 break;
  215.             case SDL_WINDOWEVENT:
  216.                 if (event.window.event == SDL_WINDOWEVENT_CLOSE)
  217.                     return true;
  218.                 break;
  219.             default:
  220.                 break;
  221.         }
  222.     }
  223.  
  224.     return false;
  225. }
  226.  
  227. void init()
  228. {
  229.     SDL_Window* sdlwindow = initSDL();
  230.     VkInstance instance = initVulkanInstance();
  231.     VkSurfaceKHR surface = initVulkanSurface(instance, sdlwindow);
  232.     initVulkanRenderDevice(instance);
  233.     initVulkanSwapchain(surface);
  234.     initVulkanCommandBuffers();
  235.     initVulkanSynchronizationPrimitives();
  236. }
  237.  
  238. SDL_Window* initSDL()
  239. {
  240.     SDL_Init(SDL_INIT_EVENTS | SDL_INIT_VIDEO);
  241.     SDL_Window* sdlwindow = SDL_CreateWindow("Broken", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 640, 480, 0);
  242.  
  243.     return sdlwindow;
  244. }
  245.  
  246. VkInstance initVulkanInstance()
  247. {
  248.     VkApplicationInfo appInfo = {};
  249.     appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  250.     appInfo.pNext = NULL;
  251.     appInfo.pApplicationName = NULL;
  252.     appInfo.applicationVersion = 0;
  253.     appInfo.pEngineName = NULL;
  254.     appInfo.engineVersion = 0;
  255.     appInfo.apiVersion = VK_API_VERSION_1_0;
  256.  
  257.     const char* extensions[2] = {VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_XLIB_SURFACE_EXTENSION_NAME};
  258.  
  259.     VkInstanceCreateInfo instanceCreateInfo = {};
  260.     instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  261.     instanceCreateInfo.pNext = NULL;
  262.     instanceCreateInfo.flags = 0;
  263.     instanceCreateInfo.pApplicationInfo = &appInfo;
  264.     instanceCreateInfo.enabledLayerCount = 0;
  265.     instanceCreateInfo.ppEnabledLayerNames = NULL;
  266.     instanceCreateInfo.enabledExtensionCount = 2;
  267.     instanceCreateInfo.ppEnabledExtensionNames = extensions;
  268.  
  269.     VkInstance instance;
  270.  
  271.     vkCreateInstance(&instanceCreateInfo, nullptr, &instance);
  272.  
  273.     return instance;
  274. }
  275.  
  276. VkSurfaceKHR initVulkanSurface(VkInstance instance, SDL_Window* sdlwindow)
  277. {
  278.     SDL_SysWMinfo info;
  279.     SDL_GetVersion(&info.version);
  280.     SDL_GetWindowWMInfo(sdlwindow, &info);
  281.     Display* x11display = info.info.x11.display;
  282.     Window x11window = info.info.x11.window;
  283.  
  284.     VkXlibSurfaceCreateInfoKHR surfaceInfo;
  285.     surfaceInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
  286.     surfaceInfo.pNext = NULL;
  287.     surfaceInfo.flags = 0;
  288.     surfaceInfo.dpy = x11display;
  289.     surfaceInfo.window = x11window;
  290.  
  291.     VkSurfaceKHR surface;
  292.  
  293.     vkCreateXlibSurfaceKHR(instance, &surfaceInfo, NULL, &surface);
  294.  
  295.     return surface;
  296. }
  297.  
  298. void initVulkanRenderDevice(VkInstance instance)
  299. {
  300.     uint32_t deviceCount = 0;
  301.     vkEnumeratePhysicalDevices(instance, &deviceCount, NULL);
  302.     VkPhysicalDevice devices[deviceCount];
  303.     vkEnumeratePhysicalDevices(instance, &deviceCount, devices);
  304.  
  305.     float queuePriorities[1] = {1.0};
  306.  
  307.     VkDeviceQueueCreateInfo queueInfos[1];
  308.     queueInfos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  309.     queueInfos[0].pNext = NULL;
  310.     queueInfos[0].flags = 0;
  311.     queueInfos[0].queueFamilyIndex = 0;
  312.     queueInfos[0].queueCount = 16;
  313.     queueInfos[0].pQueuePriorities = queuePriorities;
  314.  
  315.     VkPhysicalDeviceFeatures features;
  316.     features.robustBufferAccess = VK_FALSE;
  317.     features.fullDrawIndexUint32 = VK_FALSE;
  318.     features.imageCubeArray = VK_FALSE;
  319.     features.independentBlend = VK_FALSE;
  320.     features.geometryShader = VK_TRUE;
  321.     features.tessellationShader = VK_TRUE;
  322.     features.sampleRateShading = VK_FALSE;
  323.     features.dualSrcBlend = VK_FALSE;
  324.     features.logicOp = VK_FALSE;
  325.     features.multiDrawIndirect = VK_FALSE;
  326.     features.drawIndirectFirstInstance = VK_FALSE;
  327.     features.depthClamp = VK_FALSE;
  328.     features.depthBiasClamp = VK_FALSE;
  329.     features.fillModeNonSolid = VK_FALSE;
  330.     features.depthBounds = VK_FALSE;
  331.     features.wideLines = VK_FALSE;
  332.     features.largePoints = VK_FALSE;
  333.     features.alphaToOne = VK_FALSE;
  334.     features.multiViewport = VK_TRUE;
  335.     features.samplerAnisotropy = VK_TRUE;
  336.     features.textureCompressionETC2 = VK_FALSE;
  337.     features.textureCompressionASTC_LDR = VK_FALSE;
  338.     features.textureCompressionBC = VK_FALSE;
  339.     features.occlusionQueryPrecise = VK_FALSE;
  340.     features.pipelineStatisticsQuery = VK_FALSE;
  341.     features.vertexPipelineStoresAndAtomics = VK_FALSE;
  342.     features.fragmentStoresAndAtomics = VK_FALSE;
  343.     features.shaderTessellationAndGeometryPointSize = VK_FALSE;
  344.     features.shaderImageGatherExtended = VK_FALSE;
  345.     features.shaderStorageImageExtendedFormats = VK_FALSE;
  346.     features.shaderStorageImageMultisample = VK_FALSE;
  347.     features.shaderStorageImageReadWithoutFormat = VK_FALSE;
  348.     features.shaderStorageImageWriteWithoutFormat = VK_FALSE;
  349.     features.shaderUniformBufferArrayDynamicIndexing = VK_FALSE;
  350.     features.shaderSampledImageArrayDynamicIndexing = VK_FALSE;
  351.     features.shaderStorageBufferArrayDynamicIndexing = VK_FALSE;
  352.     features.shaderStorageImageArrayDynamicIndexing = VK_FALSE;
  353.     features.shaderClipDistance = VK_FALSE;
  354.     features.shaderCullDistance = VK_FALSE;
  355.     features.shaderFloat64 = VK_FALSE;
  356.     features.shaderInt64 = VK_FALSE;
  357.     features.shaderInt16 = VK_FALSE;
  358.     features.shaderResourceResidency = VK_FALSE;
  359.     features.shaderResourceMinLod = VK_FALSE;
  360.     features.sparseBinding = VK_FALSE;
  361.     features.sparseResidencyBuffer = VK_FALSE;
  362.     features.sparseResidencyImage2D = VK_FALSE;
  363.     features.sparseResidencyImage3D = VK_FALSE;
  364.     features.sparseResidency2Samples = VK_FALSE;
  365.     features.sparseResidency4Samples = VK_FALSE;
  366.     features.sparseResidency8Samples = VK_FALSE;
  367.     features.sparseResidency16Samples = VK_FALSE;
  368.     features.sparseResidencyAliased = VK_FALSE;
  369.     features.variableMultisampleRate = VK_FALSE;
  370.     features.inheritedQueries = VK_FALSE;
  371.  
  372.     const char* extensions[1] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
  373.  
  374.     VkDeviceCreateInfo deviceInfo;
  375.     deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  376.     deviceInfo.pNext = NULL;
  377.     deviceInfo.flags = 0;
  378.     deviceInfo.queueCreateInfoCount = 1;
  379.     deviceInfo.pQueueCreateInfos = queueInfos;
  380.     deviceInfo.enabledLayerCount = 0;
  381.     deviceInfo.ppEnabledLayerNames = NULL;
  382.     deviceInfo.enabledExtensionCount = 1;
  383.     deviceInfo.ppEnabledExtensionNames = extensions;
  384.     deviceInfo.pEnabledFeatures = &features;
  385.  
  386.     vkCreateDevice(devices[0], &deviceInfo, NULL, &renderDevice);
  387. }
  388.  
  389. void initVulkanSwapchain(VkSurfaceKHR surface)
  390. {
  391.     VkSwapchainCreateInfoKHR chainInfo;
  392.     chainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  393.     chainInfo.pNext = NULL;
  394.     chainInfo.flags = 0;
  395.     chainInfo.surface = surface;
  396.     chainInfo.minImageCount = SWAPCHAINSIZE;
  397.     chainInfo.imageFormat = VK_FORMAT_B8G8R8A8_UNORM;
  398.     chainInfo.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
  399.     chainInfo.imageExtent = {640, 480};
  400.     chainInfo.imageArrayLayers = 1;
  401.     chainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  402.     chainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  403.     chainInfo.queueFamilyIndexCount = 0;
  404.     chainInfo.pQueueFamilyIndices = NULL;
  405.     chainInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
  406.     chainInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
  407.     // chainInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR;
  408.     chainInfo.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR; // Doesn't influence the results.
  409.     chainInfo.clipped = VK_FALSE;
  410.     chainInfo.oldSwapchain = NULL;
  411.  
  412.     vkCreateSwapchainKHR(renderDevice, &chainInfo, NULL, &swapchains[0]);
  413. }
  414.  
  415. void initVulkanCommandBuffers()
  416. {
  417.     VkCommandPoolCreateInfo poolInfo;
  418.     poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  419.     poolInfo.pNext = NULL;
  420.     poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
  421.     poolInfo.queueFamilyIndex = 0;
  422.  
  423.     VkCommandPool commandPool;
  424.     vkCreateCommandPool(renderDevice, &poolInfo, NULL, &commandPool);
  425.  
  426.     VkCommandBufferAllocateInfo bufferInfo;
  427.     bufferInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  428.     bufferInfo.pNext = NULL;
  429.     bufferInfo.commandPool = commandPool;
  430.     bufferInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  431.     bufferInfo.commandBufferCount = 1;
  432.  
  433.     vkAllocateCommandBuffers(renderDevice, &bufferInfo, commandBuffer);
  434. }
  435.  
  436. void initVulkanSynchronizationPrimitives()
  437. {
  438.     VkSemaphoreCreateInfo semaphoreInfo;
  439.     semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
  440.     semaphoreInfo.pNext = NULL;
  441.     semaphoreInfo.flags = 0;
  442.  
  443.     vkCreateSemaphore(renderDevice, &semaphoreInfo, NULL, &swapchainSemaphores[0]);
  444.     vkCreateSemaphore(renderDevice, &semaphoreInfo, NULL, &signalSemaphores[0]);
  445.  
  446.     VkFenceCreateInfo fenceInfo[1];
  447.     fenceInfo[0].sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
  448.     fenceInfo[0].pNext = NULL;
  449.     fenceInfo[0].flags = 0;
  450.  
  451.     vkCreateFence(renderDevice, fenceInfo, NULL, &fences[0]);
  452.     vkCreateFence(renderDevice, fenceInfo, NULL, &idlewaitfence[0]);
  453. }
Add Comment
Please, Sign In to add comment