BsVulkanDevice.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "BsVulkanDevice.h"
  4. namespace BansheeEngine
  5. {
  6. VulkanDevice::VulkanDevice(VkPhysicalDevice device)
  7. :mPhysicalDevice(device), mLogicalDevice(nullptr), mQueueInfos{}
  8. {
  9. vkGetPhysicalDeviceProperties(device, &mDeviceProperties);
  10. vkGetPhysicalDeviceFeatures(device, &mDeviceFeatures);
  11. vkGetPhysicalDeviceMemoryProperties(device, &mMemoryProperties);
  12. uint32_t numQueueFamilies;
  13. vkGetPhysicalDeviceQueueFamilyProperties(device, &numQueueFamilies, nullptr);
  14. Vector<VkQueueFamilyProperties> queueFamilyProperties(numQueueFamilies);
  15. vkGetPhysicalDeviceQueueFamilyProperties(device, &numQueueFamilies, queueFamilyProperties.data());
  16. // Create queues
  17. const float defaultQueuePriorities[BS_MAX_VULKAN_QUEUES_PER_TYPE] = { 0.0f };
  18. Vector<VkDeviceQueueCreateInfo> queueCreateInfos;
  19. auto populateQueueInfo = [&](VulkanQueueType type, uint32_t familyIdx)
  20. {
  21. queueCreateInfos.push_back(VkDeviceQueueCreateInfo());
  22. VkDeviceQueueCreateInfo& createInfo = queueCreateInfos.back();
  23. createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  24. createInfo.pNext = nullptr;
  25. createInfo.flags = 0;
  26. createInfo.queueFamilyIndex = familyIdx;
  27. createInfo.queueCount = std::min(queueFamilyProperties[familyIdx].queueCount, (uint32_t)BS_MAX_VULKAN_QUEUES_PER_TYPE);
  28. createInfo.pQueuePriorities = defaultQueuePriorities;
  29. mQueueInfos[type].familyIdx = familyIdx;
  30. mQueueInfos[type].queues.resize(createInfo.queueCount);
  31. };
  32. // Look for dedicated compute queues
  33. for (UINT32 i = 0; i < (UINT32)queueFamilyProperties.size(); i++)
  34. {
  35. if ((queueFamilyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) && (queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)
  36. {
  37. populateQueueInfo(VQT_COMPUTE, i);
  38. break;
  39. }
  40. }
  41. // Look for dedicated upload queues
  42. for (UINT32 i = 0; i < (UINT32)queueFamilyProperties.size(); i++)
  43. {
  44. if ((queueFamilyProperties[i].queueFlags & VK_QUEUE_TRANSFER_BIT) &&
  45. ((queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0) &&
  46. ((queueFamilyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0))
  47. {
  48. populateQueueInfo(VQT_UPLOAD, i);
  49. break;
  50. }
  51. }
  52. // Looks for graphics queues
  53. for (UINT32 i = 0; i < (UINT32)queueFamilyProperties.size(); i++)
  54. {
  55. if (queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
  56. {
  57. populateQueueInfo(VQT_GRAPHICS, i);
  58. break;
  59. }
  60. }
  61. // Create logical device
  62. const char* extensions[] = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
  63. uint32_t numExtensions = sizeof(extensions) / sizeof(extensions[0]);
  64. VkDeviceCreateInfo deviceInfo;
  65. deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  66. deviceInfo.pNext = nullptr;
  67. deviceInfo.flags = 0;
  68. deviceInfo.queueCreateInfoCount = (uint32_t)queueCreateInfos.size();
  69. deviceInfo.pQueueCreateInfos = queueCreateInfos.data();
  70. deviceInfo.pEnabledFeatures = &mDeviceFeatures;
  71. deviceInfo.enabledExtensionCount = numExtensions;
  72. deviceInfo.ppEnabledExtensionNames = extensions;
  73. deviceInfo.enabledLayerCount = 0;
  74. deviceInfo.ppEnabledLayerNames = nullptr;
  75. VkResult result = vkCreateDevice(device, &deviceInfo, gVulkanAllocator, &mLogicalDevice);
  76. assert(result == VK_SUCCESS);
  77. // Retrieve queues
  78. for(UINT32 i = 0; i < VQT_COUNT; i++)
  79. {
  80. UINT32 numQueues = (UINT32)mQueueInfos[i].queues.size();
  81. for(UINT32 j = 0; j < numQueues; j++)
  82. vkGetDeviceQueue(mLogicalDevice, mQueueInfos[i].familyIdx, j, &mQueueInfos[i].queues[j]);
  83. }
  84. }
  85. VulkanDevice::~VulkanDevice()
  86. {
  87. vkDeviceWaitIdle(mLogicalDevice);
  88. vkDestroyDevice(mLogicalDevice, gVulkanAllocator);
  89. }
  90. VkDeviceMemory VulkanDevice::allocateMemory(VkImage image, VkMemoryPropertyFlags flags)
  91. {
  92. VkMemoryRequirements memReq;
  93. vkGetImageMemoryRequirements(mLogicalDevice, image, &memReq);
  94. VkDeviceMemory memory = allocateMemory(memReq, flags);
  95. VkResult result = vkBindImageMemory(mLogicalDevice, image, memory, 0);
  96. assert(result == VK_SUCCESS);
  97. return memory;
  98. }
  99. VkDeviceMemory VulkanDevice::allocateMemory(VkBuffer buffer, VkMemoryPropertyFlags flags)
  100. {
  101. VkMemoryRequirements memReq;
  102. vkGetBufferMemoryRequirements(mLogicalDevice, buffer, &memReq);
  103. VkDeviceMemory memory = allocateMemory(memReq, flags);
  104. VkResult result = vkBindBufferMemory(mLogicalDevice, buffer, memory, 0);
  105. assert(result == VK_SUCCESS);
  106. return memory;
  107. }
  108. VkDeviceMemory VulkanDevice::allocateMemory(const VkMemoryRequirements& reqs, VkMemoryPropertyFlags flags)
  109. {
  110. VkMemoryAllocateInfo allocateInfo;
  111. allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  112. allocateInfo.pNext = nullptr;
  113. allocateInfo.memoryTypeIndex = findMemoryType(reqs.memoryTypeBits, flags);
  114. allocateInfo.allocationSize = reqs.size;
  115. VkDeviceMemory memory;
  116. VkResult result = vkAllocateMemory(mLogicalDevice, &allocateInfo, gVulkanAllocator, &memory);
  117. assert(result == VK_SUCCESS);
  118. return memory;
  119. }
  120. void VulkanDevice::freeMemory(VkDeviceMemory memory)
  121. {
  122. vkFreeMemory(mLogicalDevice, memory, gVulkanAllocator);
  123. }
  124. uint32_t VulkanDevice::findMemoryType(uint32_t requirementBits, VkMemoryPropertyFlags wantedFlags)
  125. {
  126. for (uint32_t i = 0; i < mMemoryProperties.memoryTypeCount; i++)
  127. {
  128. if (requirementBits & (1 << i))
  129. {
  130. if ((mMemoryProperties.memoryTypes[i].propertyFlags & wantedFlags) == wantedFlags)
  131. return i;
  132. }
  133. requirementBits >>= 1;
  134. }
  135. return -1;
  136. }
  137. }