2
0

BsVulkanQueue.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  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. }
  54. mActiveBuffers.push_back(SubmitInfo(cmdBuffer, mNextSubmitIdx++, waitSemaphores, semaphoresCount));
  55. }
  56. void VulkanQueue::present(VulkanSwapChain* swapChain, VulkanSemaphore** waitSemaphores, UINT32 semaphoresCount)
  57. {
  58. UINT32 backBufferIdx = swapChain->prepareForPresent();
  59. VkSwapchainKHR vkSwapChain = swapChain->getHandle();
  60. VkPresentInfoKHR presentInfo;
  61. presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  62. presentInfo.pNext = nullptr;
  63. presentInfo.swapchainCount = 1;
  64. presentInfo.pSwapchains = &vkSwapChain;
  65. presentInfo.pImageIndices = &backBufferIdx;
  66. presentInfo.pResults = nullptr;
  67. // Wait before presenting, if required
  68. if (semaphoresCount > 0)
  69. {
  70. for (UINT32 i = 0; i < semaphoresCount; i++)
  71. mSemaphoresTemp[i] = waitSemaphores[i]->getHandle();
  72. presentInfo.pWaitSemaphores = mSemaphoresTemp;
  73. presentInfo.waitSemaphoreCount = semaphoresCount;
  74. }
  75. else
  76. {
  77. presentInfo.pWaitSemaphores = nullptr;
  78. presentInfo.waitSemaphoreCount = 0;
  79. }
  80. VkResult result = vkQueuePresentKHR(mQueue, &presentInfo);
  81. assert(result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR);
  82. for (UINT32 i = 0; i < semaphoresCount; i++)
  83. {
  84. waitSemaphores[i]->notifyBound();
  85. waitSemaphores[i]->notifyUsed(0, 0, VulkanUseFlag::Read | VulkanUseFlag::Write);
  86. }
  87. mActiveBuffers.push_back(SubmitInfo(nullptr, mNextSubmitIdx++, waitSemaphores, semaphoresCount));
  88. }
  89. void VulkanQueue::waitIdle() const
  90. {
  91. VkResult result = vkQueueWaitIdle(mQueue);
  92. assert(result == VK_SUCCESS);
  93. }
  94. void VulkanQueue::refreshStates()
  95. {
  96. UINT32 lastFinishedSubmission = 0;
  97. auto iter = mActiveBuffers.begin();
  98. while (iter != mActiveBuffers.end())
  99. {
  100. VulkanCmdBuffer* cmdBuffer = iter->cmdBuffer;
  101. if (cmdBuffer == nullptr)
  102. continue;
  103. cmdBuffer->refreshFenceStatus();
  104. if (cmdBuffer->isSubmitted())
  105. break; // No chance of any later CBs of being done either
  106. lastFinishedSubmission = iter->submitIdx;
  107. ++iter;
  108. }
  109. iter = mActiveBuffers.begin();
  110. while (iter != mActiveBuffers.end())
  111. {
  112. if (iter->submitIdx > lastFinishedSubmission)
  113. break;
  114. for(UINT32 i = 0; i < iter->numSemaphores; i++)
  115. iter->semaphores[i]->notifyDone(0, VulkanUseFlag::Read | VulkanUseFlag::Write);
  116. iter = mActiveBuffers.erase(iter);
  117. }
  118. }
  119. }