BsVulkanQueue.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsVulkanQueue.h"
  4. #include "BsVulkanCommandBuffer.h"
  5. #include "BsVulkanSwapChain.h"
  6. namespace bs
  7. {
  8. VulkanQueue::VulkanQueue(VulkanDevice& device, VkQueue queue, GpuQueueType type, UINT32 index)
  9. :mDevice(device), mQueue(queue), mType(type), mIndex(index), mLastCommandBuffer(nullptr), mNextSubmitIdx(1)
  10. {
  11. for (UINT32 i = 0; i < BS_MAX_UNIQUE_QUEUES; i++)
  12. mSubmitDstWaitMask[i] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
  13. }
  14. bool VulkanQueue::isExecuting() const
  15. {
  16. if (mLastCommandBuffer == nullptr)
  17. return false;
  18. return mLastCommandBuffer->isSubmitted();
  19. }
  20. void VulkanQueue::submit(VulkanCmdBuffer* cmdBuffer, VulkanSemaphore** waitSemaphores, UINT32 semaphoresCount)
  21. {
  22. VkCommandBuffer vkCmdBuffer = cmdBuffer->getHandle();
  23. VulkanSemaphore* semaphore = cmdBuffer->allocateSemaphore();
  24. VkSemaphore vkSemaphore = semaphore->getHandle();
  25. VkSubmitInfo submitInfo;
  26. submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  27. submitInfo.pNext = nullptr;
  28. submitInfo.commandBufferCount = 1;
  29. submitInfo.pCommandBuffers = &vkCmdBuffer;
  30. submitInfo.signalSemaphoreCount = 1;
  31. submitInfo.pSignalSemaphores = &vkSemaphore;
  32. submitInfo.waitSemaphoreCount = semaphoresCount;
  33. if (semaphoresCount > 0)
  34. {
  35. for (UINT32 i = 0; i < semaphoresCount; i++)
  36. mSemaphoresTemp[i] = waitSemaphores[i]->getHandle();
  37. submitInfo.pWaitSemaphores = mSemaphoresTemp;
  38. submitInfo.pWaitDstStageMask = mSubmitDstWaitMask;
  39. }
  40. else
  41. {
  42. submitInfo.pWaitSemaphores = nullptr;
  43. submitInfo.pWaitDstStageMask = nullptr;
  44. }
  45. VkResult result = vkQueueSubmit(mQueue, 1, &submitInfo, cmdBuffer->getFence());
  46. assert(result == VK_SUCCESS);
  47. cmdBuffer->setIsSubmitted();
  48. mLastCommandBuffer = cmdBuffer;
  49. for (UINT32 i = 0; i < semaphoresCount; i++)
  50. {
  51. waitSemaphores[i]->notifyBound();
  52. waitSemaphores[i]->notifyUsed(0, 0, VulkanUseFlag::Read | VulkanUseFlag::Write);
  53. mActiveSemaphores.push(waitSemaphores[i]);
  54. }
  55. mActiveBuffers.push_back(SubmitInfo(cmdBuffer, mNextSubmitIdx++, semaphoresCount));
  56. }
  57. void VulkanQueue::present(VulkanSwapChain* swapChain, VulkanSemaphore** waitSemaphores, UINT32 semaphoresCount)
  58. {
  59. UINT32 backBufferIdx = swapChain->prepareForPresent();
  60. VkSwapchainKHR vkSwapChain = swapChain->getHandle();
  61. VkPresentInfoKHR presentInfo;
  62. presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  63. presentInfo.pNext = nullptr;
  64. presentInfo.swapchainCount = 1;
  65. presentInfo.pSwapchains = &vkSwapChain;
  66. presentInfo.pImageIndices = &backBufferIdx;
  67. presentInfo.pResults = nullptr;
  68. // Wait before presenting, if required
  69. if (semaphoresCount > 0)
  70. {
  71. for (UINT32 i = 0; i < semaphoresCount; i++)
  72. mSemaphoresTemp[i] = waitSemaphores[i]->getHandle();
  73. presentInfo.pWaitSemaphores = mSemaphoresTemp;
  74. presentInfo.waitSemaphoreCount = semaphoresCount;
  75. }
  76. else
  77. {
  78. presentInfo.pWaitSemaphores = nullptr;
  79. presentInfo.waitSemaphoreCount = 0;
  80. }
  81. VkResult result = vkQueuePresentKHR(mQueue, &presentInfo);
  82. assert(result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR);
  83. for (UINT32 i = 0; i < semaphoresCount; i++)
  84. {
  85. waitSemaphores[i]->notifyBound();
  86. waitSemaphores[i]->notifyUsed(0, 0, VulkanUseFlag::Read | VulkanUseFlag::Write);
  87. mActiveSemaphores.push(waitSemaphores[i]);
  88. }
  89. mActiveBuffers.push_back(SubmitInfo(nullptr, mNextSubmitIdx++, semaphoresCount));
  90. }
  91. void VulkanQueue::waitIdle() const
  92. {
  93. VkResult result = vkQueueWaitIdle(mQueue);
  94. assert(result == VK_SUCCESS);
  95. }
  96. void VulkanQueue::refreshStates()
  97. {
  98. UINT32 lastFinishedSubmission = 0;
  99. auto iter = mActiveBuffers.begin();
  100. while (iter != mActiveBuffers.end())
  101. {
  102. VulkanCmdBuffer* cmdBuffer = iter->cmdBuffer;
  103. if (cmdBuffer == nullptr)
  104. {
  105. ++iter;
  106. continue;
  107. }
  108. cmdBuffer->refreshFenceStatus();
  109. if (cmdBuffer->isSubmitted())
  110. break; // No chance of any later CBs of being done either
  111. lastFinishedSubmission = iter->submitIdx;
  112. ++iter;
  113. }
  114. iter = mActiveBuffers.begin();
  115. while (iter != mActiveBuffers.end())
  116. {
  117. if (iter->submitIdx > lastFinishedSubmission)
  118. break;
  119. for (UINT32 i = 0; i < iter->numSemaphores; i++)
  120. {
  121. VulkanSemaphore* semaphore = mActiveSemaphores.front();
  122. mActiveSemaphores.pop();
  123. semaphore->notifyDone(0, VulkanUseFlag::Read | VulkanUseFlag::Write);
  124. }
  125. iter = mActiveBuffers.erase(iter);
  126. }
  127. }
  128. }