Advertisement
Guest User

Untitled

a guest
May 5th, 2016
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 30.00 KB | None | 0 0
  1. #include <cassert>
  2. #include <iostream>
  3. #include <vector>
  4. #include <array>
  5. #include <cstring>
  6. #define GLFW_INCLUDE_VULKAN
  7. #include <GLFW/glfw3.h>
  8.  
  9. #define VKCHECK(x) if ((x) != VK_SUCCESS) fprintf(stderr, "Failure while executing Vulkan command at line %d\n", __LINE__)
  10.  
  11. static bool getMemoryTypeFromProperties(VkPhysicalDeviceMemoryProperties memProps, uint32_t typeBits, VkFlags requirementsMask, uint32_t* typeIndex)
  12. {
  13. for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; ++i) {
  14. if ((typeBits & 1) == 1) {
  15. if ((memProps.memoryTypes[i].propertyFlags & requirementsMask) == requirementsMask) {
  16. *typeIndex = i;
  17. return true;
  18. }
  19. }
  20. typeBits >>= 1;
  21. }
  22. return false;
  23. }
  24.  
  25. /*static std::array<const char*, 8> instanceValidationLayerNames = {{
  26. "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
  27. "VK_LAYER_LUNARG_device_limits", "VK_LAYER_LUNARG_object_tracker",
  28. "VK_LAYER_LUNARG_image", "VK_LAYER_LUNARG_core_validation",
  29. "VK_LAYER_LUNARG_swapchain", "VK_LAYER_GOOGLE_unique_objects"
  30. }
  31. };*/
  32. static std::array<const char*, 1> instanceValidationLayerNames = {{ "VK_LAYER_LUNARG_standard_validation" }};
  33.  
  34. static void setImageLayout(VkCommandBuffer& cmdBuf, VkDevice device, VkCommandPool cmdPool, VkImage image, VkImageAspectFlags aspectMask, VkImageLayout oldImageLayout, VkImageLayout newImageLayout, VkAccessFlagBits srcAccessMask)
  35. {
  36. // allocate a command buffer if we don't already have one
  37. if (cmdBuf == VK_NULL_HANDLE) {
  38. VkCommandBufferAllocateInfo cmdBufAllocInfo = {};
  39. cmdBufAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  40. cmdBufAllocInfo.pNext = nullptr;
  41. cmdBufAllocInfo.commandPool = cmdPool;
  42. cmdBufAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  43. cmdBufAllocInfo.commandBufferCount = 1;
  44.  
  45. VKCHECK(vkAllocateCommandBuffers(device, &cmdBufAllocInfo, &cmdBuf));
  46.  
  47. VkCommandBufferInheritanceInfo cmdBufInhInfo = {};
  48. cmdBufInhInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
  49. cmdBufInhInfo.pNext = nullptr;
  50. cmdBufInhInfo.renderPass = VK_NULL_HANDLE;
  51. cmdBufInhInfo.subpass = 0;
  52. cmdBufInhInfo.framebuffer = VK_NULL_HANDLE;
  53. cmdBufInhInfo.occlusionQueryEnable = VK_FALSE;
  54. cmdBufInhInfo.queryFlags = 0;
  55. cmdBufInhInfo.pipelineStatistics = 0;
  56.  
  57. VkCommandBufferBeginInfo cmdBufBeginInfo = {};
  58. cmdBufBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  59. cmdBufBeginInfo.pNext = nullptr;
  60. cmdBufBeginInfo.flags = 0;
  61. cmdBufBeginInfo.pInheritanceInfo = &cmdBufInhInfo;
  62. VKCHECK(vkBeginCommandBuffer(cmdBuf, &cmdBufBeginInfo));
  63. }
  64.  
  65. VkImageMemoryBarrier imageMemBarrier = {};
  66. imageMemBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  67. imageMemBarrier.pNext = nullptr;
  68. imageMemBarrier.srcAccessMask = srcAccessMask;
  69. imageMemBarrier.dstAccessMask = 0;
  70. imageMemBarrier.oldLayout = oldImageLayout;
  71. imageMemBarrier.newLayout = newImageLayout;
  72. imageMemBarrier.image = image;
  73. imageMemBarrier.subresourceRange = { aspectMask, 0, 1, 0, 1 };
  74.  
  75. if (newImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
  76. imageMemBarrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
  77. } else if (newImageLayout == VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
  78. imageMemBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  79. } else if (newImageLayout == VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
  80. imageMemBarrier.dstAccessMask = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
  81. } else if (newImageLayout == VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) {
  82. imageMemBarrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
  83. }
  84.  
  85. VkPipelineStageFlags srcStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
  86. VkPipelineStageFlags destStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
  87.  
  88. vkCmdPipelineBarrier(cmdBuf, srcStages, destStages, 0, 0, nullptr, 0, nullptr, 1, &imageMemBarrier);
  89. }
  90.  
  91. static bool checkInstanceLayers(uint32_t checkCount, const char* const* checkNames, uint32_t layerCount, VkLayerProperties* layers)
  92. {
  93. for (uint32_t i = 0; i < checkCount; ++i) {
  94. bool found = false;
  95. for (uint32_t j = 0; j < layerCount; ++j) {
  96. if (std::strcmp(checkNames[i], layers[j].layerName) == 0) {
  97. found = true;
  98. break;
  99. }
  100. }
  101. if (!found) {
  102. fprintf(stderr, "Cannot find instance layer %s\n", checkNames[i]);
  103. return false;
  104. }
  105. }
  106. return true;
  107. }
  108.  
  109. static const bool validate = true;
  110.  
  111. int main()
  112. {
  113. glfwInit();
  114. assert(glfwVulkanSupported());
  115.  
  116. // enable validation if wanted
  117. bool validationFound = false;
  118. if (validate) {
  119. uint32_t propCount;
  120. VKCHECK(vkEnumerateInstanceLayerProperties(&propCount, nullptr));
  121.  
  122. std::vector<VkLayerProperties> instanceLayerProps(propCount);
  123. VKCHECK(vkEnumerateInstanceLayerProperties(&propCount, instanceLayerProps.data()));
  124. validationFound = checkInstanceLayers((uint32_t)instanceValidationLayerNames.size(), instanceValidationLayerNames.data(), propCount, instanceLayerProps.data());
  125. }
  126.  
  127. if (!validationFound) {
  128. fprintf(stderr, "Validation was requested, but not all required validation layers were found.\n");
  129. return 1;
  130. }
  131.  
  132. PFN_vkCreateInstance pfnCreateInstance = (PFN_vkCreateInstance)glfwGetInstanceProcAddress(VK_NULL_HANDLE, "vkCreateInstance");
  133. PFN_vkDestroyInstance pfnDestroyInstance = (PFN_vkDestroyInstance)glfwGetInstanceProcAddress(VK_NULL_HANDLE, "vkDestroyInstance");
  134.  
  135. unsigned int instanceExtCount;
  136. const char** reqInstanceExts = glfwGetRequiredInstanceExtensions(&instanceExtCount);
  137.  
  138. if (reqInstanceExts) {
  139. printf("Required instance extensions:\n");
  140. for (unsigned int i = 0; i < instanceExtCount; ++i) {
  141. puts(reqInstanceExts[i]);
  142. }
  143. }
  144.  
  145. std::array<const char*, 8> instanceExts;
  146. std::memcpy(instanceExts.data(), reqInstanceExts, sizeof(const char*) * instanceExtCount);
  147.  
  148. if (validate) {
  149. instanceExts[instanceExtCount++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME; // we just assume it's there
  150. }
  151.  
  152. VkApplicationInfo appInfo = {};
  153. appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  154. appInfo.pNext = nullptr;
  155. appInfo.pApplicationName = "glfwvktest";
  156. appInfo.applicationVersion = 1;
  157. appInfo.pEngineName = "glfwvktest";
  158. appInfo.engineVersion = 1;
  159. appInfo.apiVersion = VK_API_VERSION_1_0;
  160.  
  161. VkInstanceCreateInfo instanceCreateInfo = {};
  162. instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  163. instanceCreateInfo.pNext = nullptr;
  164. instanceCreateInfo.flags = 0;
  165. instanceCreateInfo.pApplicationInfo = &appInfo;
  166. instanceCreateInfo.enabledLayerCount = (uint32_t)instanceValidationLayerNames.size();
  167. instanceCreateInfo.ppEnabledLayerNames = instanceValidationLayerNames.data();
  168. instanceCreateInfo.enabledExtensionCount = instanceExtCount;
  169. instanceCreateInfo.ppEnabledExtensionNames = instanceExts.data();
  170.  
  171. VkDebugReportCallbackCreateInfoEXT dbgCreateInfo = {};
  172. dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
  173. dbgCreateInfo.pNext = nullptr;
  174. dbgCreateInfo.pfnCallback = static_cast<PFN_vkDebugReportCallbackEXT>([](VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void* pUserData) -> VkBool32 {
  175. if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
  176. {
  177. fprintf(stderr, "ERROR: [%s] Code %d : %s\n", pLayerPrefix, msgCode, pMsg);
  178. } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT)
  179. {
  180. fprintf(stderr, "WARNING: [%s] Code %d : %s\n", pLayerPrefix, msgCode, pMsg);
  181. } else {
  182. fprintf(stderr, "INFO: [%s] Code %d : %s\n", pLayerPrefix, msgCode, pMsg);
  183. }
  184. return VK_FALSE;
  185. });
  186. dbgCreateInfo.pUserData = nullptr;
  187. dbgCreateInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
  188. instanceCreateInfo.pNext = &dbgCreateInfo;
  189.  
  190. VkInstance instance;
  191. VKCHECK(pfnCreateInstance(&instanceCreateInfo, nullptr, &instance));
  192.  
  193. // set the debug report callback
  194. PFN_vkCreateDebugReportCallbackEXT pfnCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)glfwGetInstanceProcAddress(instance, "vkCreateDebugReportCallbackEXT");
  195. PFN_vkDestroyDebugReportCallbackEXT pfnDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)glfwGetInstanceProcAddress(instance, "vkDestroyDebugReportCallbackEXT");
  196. VkDebugReportCallbackEXT debugReportCallback;
  197. if (validate) {
  198. VKCHECK(pfnCreateDebugReportCallbackEXT(instance, &dbgCreateInfo, nullptr, &debugReportCallback));
  199. }
  200.  
  201. PFN_vkCreateDevice pfnCreateDevice = (PFN_vkCreateDevice)glfwGetInstanceProcAddress(instance, "vkCreateDevice");
  202. PFN_vkDestroyDevice pfnDestroyDevice = (PFN_vkDestroyDevice)glfwGetInstanceProcAddress(instance, "vkDestroyDevice");
  203. PFN_vkGetDeviceProcAddr pfnGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)glfwGetInstanceProcAddress(instance, "vkGetDeviceProcAddr");
  204. PFN_vkEnumeratePhysicalDevices pfnEnumeratePhysicalDevices = (PFN_vkEnumeratePhysicalDevices)glfwGetInstanceProcAddress(instance, "vkEnumeratePhysicalDevices");
  205. PFN_vkGetPhysicalDeviceQueueFamilyProperties pfnGetPhysicalDeviceQueueFamilyProperties = (PFN_vkGetPhysicalDeviceQueueFamilyProperties)glfwGetInstanceProcAddress(instance, "vkGetPhysicalDeviceQueueFamilyProperties");
  206. PFN_vkDestroySurfaceKHR pfnDestroySurfaceKHR = (PFN_vkDestroySurfaceKHR)glfwGetInstanceProcAddress(instance, "vkDestroySurfaceKHR");
  207.  
  208. uint32_t gpuCount;
  209. VKCHECK(pfnEnumeratePhysicalDevices(instance, &gpuCount, nullptr));
  210. VkPhysicalDevice gpu;
  211. {
  212. std::vector<VkPhysicalDevice> gpus(gpuCount);
  213. VKCHECK(pfnEnumeratePhysicalDevices(instance, &gpuCount, gpus.data()));
  214. gpu = gpus[0];
  215. }
  216.  
  217. uint32_t deviceExtensionCount = 0;
  218. VKCHECK(vkEnumerateDeviceExtensionProperties(gpu, nullptr, &deviceExtensionCount, nullptr));
  219. std::array<const char*, 4> enabledDeviceExtensions;
  220. uint32_t enabledDeviceExtensionCount = 0;
  221. bool swapchainExtFound = false;
  222. {
  223. std::vector<VkExtensionProperties> deviceExtensions(deviceExtensionCount);
  224. VKCHECK(vkEnumerateDeviceExtensionProperties(gpu, nullptr, &deviceExtensionCount, deviceExtensions.data()));
  225.  
  226. for (uint32_t i = 0; i < deviceExtensionCount; ++i) {
  227. if (std::strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME, deviceExtensions[i].extensionName) == 0) {
  228. swapchainExtFound = true;
  229. enabledDeviceExtensions[enabledDeviceExtensionCount++] = VK_KHR_SWAPCHAIN_EXTENSION_NAME;
  230. }
  231. }
  232. }
  233.  
  234. if (!swapchainExtFound) {
  235. assert(false && "Need the swapchain extension, but it wasn't found");
  236. }
  237.  
  238. uint32_t queueFamilyCount;
  239. pfnGetPhysicalDeviceQueueFamilyProperties(gpu, &queueFamilyCount, nullptr);
  240. uint32_t suitableQueueFamilyIndex;
  241. {
  242. std::vector<VkQueueFamilyProperties> queueFamilyProperties(queueFamilyCount);
  243. pfnGetPhysicalDeviceQueueFamilyProperties(gpu, &queueFamilyCount, queueFamilyProperties.data());
  244. for (uint32_t i = 0; i < queueFamilyCount; ++i) {
  245. if (queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
  246. if (glfwGetPhysicalDevicePresentationSupport(instance, gpu, i)) {
  247. suitableQueueFamilyIndex = i;
  248. break;
  249. }
  250. }
  251. }
  252. }
  253.  
  254. VkDeviceQueueCreateInfo queueCreateInfo = {};
  255. queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  256. queueCreateInfo.pNext = nullptr;
  257. queueCreateInfo.flags = 0;
  258. queueCreateInfo.queueFamilyIndex = suitableQueueFamilyIndex;
  259. queueCreateInfo.queueCount = 1;
  260. float queuePriority = 0.0f;
  261. queueCreateInfo.pQueuePriorities = &queuePriority;
  262.  
  263. VkDeviceCreateInfo deviceCreateInfo = {};
  264. deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  265. deviceCreateInfo.pNext = nullptr;
  266. deviceCreateInfo.flags = 0;
  267. deviceCreateInfo.queueCreateInfoCount = 1;
  268. deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
  269. deviceCreateInfo.enabledLayerCount = (uint32_t)instanceValidationLayerNames.size(); // TODO: layer checking omitted
  270. deviceCreateInfo.ppEnabledLayerNames = instanceValidationLayerNames.data();
  271. deviceCreateInfo.enabledExtensionCount = enabledDeviceExtensionCount;
  272. deviceCreateInfo.ppEnabledExtensionNames = enabledDeviceExtensions.data();
  273. deviceCreateInfo.pEnabledFeatures = nullptr;
  274.  
  275. VkDevice device;
  276. VKCHECK(pfnCreateDevice(gpu, &deviceCreateInfo, nullptr, &device));
  277.  
  278. glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
  279. uint32_t width = 1280;
  280. uint32_t height = 720;
  281. GLFWwindow* window = glfwCreateWindow(width, height, "Vulkan on GLFW", nullptr, nullptr);
  282.  
  283. VkSurfaceKHR surface;
  284. glfwCreateWindowSurface(instance, window, nullptr, &surface);
  285. VkBool32 surfSupported = VK_FALSE;
  286. VKCHECK(vkGetPhysicalDeviceSurfaceSupportKHR(gpu, suitableQueueFamilyIndex, surface, &surfSupported));
  287. assert(surfSupported == VK_TRUE);
  288.  
  289. VkQueue queue;
  290. vkGetDeviceQueue(device, suitableQueueFamilyIndex, 0, &queue);
  291.  
  292. VkSurfaceCapabilitiesKHR surfCaps;
  293. VKCHECK(vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, surface, &surfCaps));
  294.  
  295. VkPhysicalDeviceMemoryProperties memProps;
  296. vkGetPhysicalDeviceMemoryProperties(gpu, &memProps);
  297.  
  298. uint32_t presentModeCount;
  299. VKCHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &presentModeCount, nullptr));
  300. VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
  301. {
  302. std::vector<VkPresentModeKHR> presentModes(presentModeCount);
  303. VKCHECK(vkGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &presentModeCount, presentModes.data()));
  304. for (uint32_t i = 0; i < presentModeCount; ++i) {
  305. if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) {
  306. swapchainPresentMode = VK_PRESENT_MODE_MAILBOX_KHR;
  307. break;
  308. }
  309. if ((swapchainPresentMode != VK_PRESENT_MODE_MAILBOX_KHR) &&
  310. (presentModes[i] == VK_PRESENT_MODE_IMMEDIATE_KHR)) {
  311. swapchainPresentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
  312. }
  313. }
  314. }
  315.  
  316. VkExtent2D swapchainExtent = {};
  317. if (surfCaps.currentExtent.width == 0xffffffff) {
  318. swapchainExtent.width = width;
  319. swapchainExtent.height = height;
  320. } else {
  321. swapchainExtent = surfCaps.currentExtent;
  322. width = surfCaps.currentExtent.width;
  323. height = surfCaps.currentExtent.height;
  324. }
  325.  
  326. VkSurfaceTransformFlagBitsKHR preTransform;
  327. if (surfCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
  328. preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
  329. } else {
  330. preTransform = surfCaps.currentTransform;
  331. }
  332.  
  333. uint32_t formatCount;
  334. VKCHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &formatCount, nullptr));
  335. VkFormat suitableFormat;
  336. VkColorSpaceKHR suitableColorSpace;
  337. {
  338. std::vector<VkSurfaceFormatKHR> surfFormats(formatCount);
  339. VKCHECK(vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &formatCount, surfFormats.data()));
  340. if ((formatCount == 1) && (surfFormats[0].format == VK_FORMAT_UNDEFINED)) {
  341. suitableFormat = VK_FORMAT_B8G8R8A8_UNORM;
  342. } else {
  343. assert(formatCount >= 1);
  344. suitableFormat = surfFormats[0].format;
  345. }
  346. suitableColorSpace = surfFormats[0].colorSpace;
  347. }
  348.  
  349. VkSwapchainCreateInfoKHR swapchainCreateInfo = {};
  350. swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
  351. swapchainCreateInfo.pNext = nullptr;
  352. swapchainCreateInfo.flags = 0;
  353. swapchainCreateInfo.surface = surface;
  354. swapchainCreateInfo.minImageCount = 2;
  355. swapchainCreateInfo.imageFormat = suitableFormat;
  356. swapchainCreateInfo.imageColorSpace = suitableColorSpace;
  357. swapchainCreateInfo.imageExtent = swapchainExtent;
  358. swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
  359. swapchainCreateInfo.preTransform = preTransform;
  360. swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
  361. swapchainCreateInfo.imageArrayLayers = 1;
  362. swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
  363. swapchainCreateInfo.queueFamilyIndexCount = 0;
  364. swapchainCreateInfo.pQueueFamilyIndices = nullptr;
  365. swapchainCreateInfo.presentMode = swapchainPresentMode;
  366. swapchainCreateInfo.oldSwapchain = VK_NULL_HANDLE;
  367. swapchainCreateInfo.clipped = VK_TRUE;
  368.  
  369. PFN_vkCreateSwapchainKHR pfnCreateSwapchainKHR = (PFN_vkCreateSwapchainKHR)pfnGetDeviceProcAddr(device, "vkCreateSwapchainKHR");
  370. PFN_vkDestroySwapchainKHR pfnDestroySwapchainKHR = (PFN_vkDestroySwapchainKHR)pfnGetDeviceProcAddr(device, "vkDestroySwapchainKHR");
  371. PFN_vkGetSwapchainImagesKHR pfnGetSwapchainImagesKHR = (PFN_vkGetSwapchainImagesKHR)pfnGetDeviceProcAddr(device, "vkGetSwapchainImagesKHR");
  372. PFN_vkAcquireNextImageKHR pfnAcquireNextImageKHR = (PFN_vkAcquireNextImageKHR)pfnGetDeviceProcAddr(device, "vkAcquireNextImageKHR");
  373. PFN_vkQueuePresentKHR pfnQueuePresentKHR = (PFN_vkQueuePresentKHR)pfnGetDeviceProcAddr(device, "vkQueuePresentKHR");
  374.  
  375. VkSwapchainKHR swapchain;
  376. VKCHECK(pfnCreateSwapchainKHR(device, &swapchainCreateInfo, nullptr, &swapchain));
  377.  
  378. std::array<VkImage, 2> swapchainImages;
  379. uint32_t swapchainImageCount;
  380. VKCHECK(pfnGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, nullptr));
  381. assert(swapchainImageCount == 2);
  382. VKCHECK(pfnGetSwapchainImagesKHR(device, swapchain, &swapchainImageCount, swapchainImages.data()));
  383.  
  384. uint32_t currentSwapchainImage = 0;
  385.  
  386. // create a command pool
  387. VkCommandPoolCreateInfo cmdPoolCreateInfo = {};
  388. cmdPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
  389. cmdPoolCreateInfo.pNext = nullptr;
  390. cmdPoolCreateInfo.flags = 0;
  391. cmdPoolCreateInfo.queueFamilyIndex = suitableQueueFamilyIndex;
  392. VkCommandPool cmdPool;
  393. VKCHECK(vkCreateCommandPool(device, &cmdPoolCreateInfo, nullptr, &cmdPool));
  394.  
  395. // create a depth buffer
  396. VkFormat depthFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
  397. VkImageCreateInfo dsImageCreateInfo = {};
  398. dsImageCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
  399. dsImageCreateInfo.pNext = nullptr;
  400. dsImageCreateInfo.flags = 0;
  401. dsImageCreateInfo.imageType = VK_IMAGE_TYPE_2D;
  402. dsImageCreateInfo.format = depthFormat;
  403. dsImageCreateInfo.extent = { width, height, 1 };
  404. dsImageCreateInfo.mipLevels = 1;
  405. dsImageCreateInfo.arrayLayers = 1;
  406. dsImageCreateInfo.samples = VK_SAMPLE_COUNT_1_BIT;
  407. dsImageCreateInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
  408. dsImageCreateInfo.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
  409.  
  410. VkImageViewCreateInfo dsivCreateInfo = {};
  411. dsivCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  412. dsivCreateInfo.pNext = nullptr;
  413. dsivCreateInfo.flags = 0;
  414. dsivCreateInfo.image = VK_NULL_HANDLE;
  415. dsivCreateInfo.format = depthFormat;
  416. dsivCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
  417. dsivCreateInfo.subresourceRange.baseMipLevel = 0;
  418. dsivCreateInfo.subresourceRange.levelCount = 1;
  419. dsivCreateInfo.subresourceRange.baseArrayLayer = 0;
  420. dsivCreateInfo.subresourceRange.layerCount = 1;
  421. dsivCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  422.  
  423. VkMemoryRequirements dsMemReqs;
  424. VkImage dsImage;
  425. VKCHECK(vkCreateImage(device, &dsImageCreateInfo, nullptr, &dsImage));
  426. vkGetImageMemoryRequirements(device, dsImage, &dsMemReqs);
  427. VkMemoryAllocateInfo dsMemAllocInfo = {};
  428. dsMemAllocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
  429. dsMemAllocInfo.pNext = nullptr;
  430. dsMemAllocInfo.allocationSize = dsMemReqs.size;
  431. dsMemAllocInfo.memoryTypeIndex = 0;
  432.  
  433. bool ok = getMemoryTypeFromProperties(memProps, dsMemReqs.memoryTypeBits, 0, &dsMemAllocInfo.memoryTypeIndex);
  434. assert(ok);
  435.  
  436. VkDeviceMemory dsMemory;
  437. VKCHECK(vkAllocateMemory(device, &dsMemAllocInfo, nullptr, &dsMemory));
  438. VKCHECK(vkBindImageMemory(device, dsImage, dsMemory, 0));
  439.  
  440. VkCommandBuffer cmdBuf = VK_NULL_HANDLE;
  441. setImageLayout(cmdBuf, device, cmdPool, dsImage, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, (VkAccessFlagBits)0);
  442.  
  443. VkImageView dsImageView;
  444. dsivCreateInfo.image = dsImage;
  445. VKCHECK(vkCreateImageView(device, &dsivCreateInfo, nullptr, &dsImageView));
  446.  
  447. VkImageViewCreateInfo ivCreateInfo = {};
  448. ivCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
  449. ivCreateInfo.pNext = nullptr;
  450. ivCreateInfo.flags = 0;
  451. ivCreateInfo.format = suitableFormat;
  452. ivCreateInfo.components = {
  453. VK_COMPONENT_SWIZZLE_R,
  454. VK_COMPONENT_SWIZZLE_G,
  455. VK_COMPONENT_SWIZZLE_B,
  456. VK_COMPONENT_SWIZZLE_A
  457. };
  458. ivCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
  459. ivCreateInfo.subresourceRange.baseMipLevel = 0;
  460. ivCreateInfo.subresourceRange.levelCount = 1;
  461. ivCreateInfo.subresourceRange.baseArrayLayer = 0;
  462. ivCreateInfo.subresourceRange.layerCount = 1;
  463. ivCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
  464. std::array<VkImageView, 2> presentViews;
  465.  
  466. for (uint32_t i = 0; i < 2; ++i) {
  467. ivCreateInfo.image = swapchainImages[i];
  468. VKCHECK(vkCreateImageView(device, &ivCreateInfo, nullptr, &presentViews[i]));
  469. }
  470.  
  471. VkAttachmentDescription attachments[2] = {};
  472. attachments[0].format = suitableFormat;
  473. attachments[0].samples = VK_SAMPLE_COUNT_1_BIT;
  474. attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  475. attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
  476. attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  477. attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  478. attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  479. attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  480.  
  481. attachments[1].format = depthFormat;
  482. attachments[1].samples = VK_SAMPLE_COUNT_1_BIT;
  483. attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
  484. attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  485. attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
  486. attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
  487. attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  488. attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  489.  
  490. VkAttachmentReference colorReference = {};
  491. colorReference.attachment = 0;
  492. colorReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  493.  
  494. VkAttachmentReference depthStencilReference = {};
  495. depthStencilReference.attachment = 1;
  496. depthStencilReference.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
  497.  
  498. VkSubpassDescription subpassDesc = {};
  499. subpassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
  500. subpassDesc.flags = 0;
  501. subpassDesc.inputAttachmentCount = 0;
  502. subpassDesc.pInputAttachments = nullptr;
  503. subpassDesc.colorAttachmentCount = 1;
  504. subpassDesc.pColorAttachments = &colorReference;
  505. subpassDesc.pResolveAttachments = nullptr;
  506. subpassDesc.pDepthStencilAttachment = &depthStencilReference;
  507. subpassDesc.preserveAttachmentCount = 0;
  508. subpassDesc.pPreserveAttachments = nullptr;
  509.  
  510. VkRenderPassCreateInfo rpCreateInfo = {};
  511. rpCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
  512. rpCreateInfo.pNext = nullptr;
  513. rpCreateInfo.flags = 0;
  514. rpCreateInfo.attachmentCount = 2;
  515. rpCreateInfo.pAttachments = attachments;
  516. rpCreateInfo.subpassCount = 1;
  517. rpCreateInfo.pSubpasses = &subpassDesc;
  518. rpCreateInfo.dependencyCount = 0;
  519. rpCreateInfo.pDependencies = nullptr;
  520.  
  521. VkRenderPass renderPass;
  522. VKCHECK(vkCreateRenderPass(device, &rpCreateInfo, nullptr, &renderPass));
  523.  
  524. std::array<VkImageView, 2> fbAttachments;
  525. fbAttachments[1] = dsImageView;
  526.  
  527. VkFramebufferCreateInfo fbCreateInfo = {};
  528. fbCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
  529. fbCreateInfo.pNext = nullptr;
  530. fbCreateInfo.flags = 0;
  531. fbCreateInfo.renderPass = renderPass;
  532. fbCreateInfo.attachmentCount = 2;
  533. fbCreateInfo.pAttachments = fbAttachments.data();
  534. fbCreateInfo.width = width;
  535. fbCreateInfo.height = height;
  536. fbCreateInfo.layers = 1;
  537.  
  538. std::array<VkFramebuffer, 2> framebuffers;
  539. for (uint32_t i = 0; i < 2; ++i) {
  540. fbAttachments[0] = presentViews[i];
  541. VKCHECK(vkCreateFramebuffer(device, &fbCreateInfo, nullptr, framebuffers.data() + i));
  542. }
  543.  
  544. // flush preparation commands
  545. VKCHECK(vkEndCommandBuffer(cmdBuf));
  546. VkSubmitInfo submitInfo = {};
  547. submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  548. submitInfo.pNext = nullptr;
  549. submitInfo.waitSemaphoreCount = 0;
  550. submitInfo.pWaitSemaphores = nullptr;
  551. submitInfo.pWaitDstStageMask = nullptr;
  552. submitInfo.commandBufferCount = 1;
  553. submitInfo.pCommandBuffers = &cmdBuf;
  554. submitInfo.signalSemaphoreCount = 0;
  555. submitInfo.pSignalSemaphores = nullptr;
  556.  
  557. VKCHECK(vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE));
  558. VKCHECK(vkQueueWaitIdle(queue));
  559.  
  560. vkFreeCommandBuffers(device, cmdPool, 1, &cmdBuf);
  561. cmdBuf = VK_NULL_HANDLE;
  562.  
  563. // and create new ones for rendering
  564. VkCommandBufferAllocateInfo cmdBufAllocInfo = {};
  565. cmdBufAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
  566. cmdBufAllocInfo.pNext = nullptr;
  567. cmdBufAllocInfo.commandPool = cmdPool;
  568. cmdBufAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
  569. cmdBufAllocInfo.commandBufferCount = 2;
  570.  
  571. std::array<VkCommandBuffer, 2> cmdBufs;
  572. VKCHECK(vkAllocateCommandBuffers(device, &cmdBufAllocInfo, cmdBufs.data()));
  573.  
  574. VkCommandBufferInheritanceInfo cmdBufInhInfo = {};
  575. cmdBufInhInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO;
  576. cmdBufInhInfo.pNext = nullptr;
  577. cmdBufInhInfo.renderPass = VK_NULL_HANDLE;
  578. cmdBufInhInfo.subpass = 0;
  579. cmdBufInhInfo.framebuffer = VK_NULL_HANDLE;
  580. cmdBufInhInfo.occlusionQueryEnable = VK_FALSE;
  581. cmdBufInhInfo.queryFlags = 0;
  582. cmdBufInhInfo.pipelineStatistics = 0;
  583.  
  584. VkCommandBufferBeginInfo cmdBufBeginInfo = {};
  585. cmdBufBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
  586. cmdBufBeginInfo.pNext = nullptr;
  587. cmdBufBeginInfo.flags = 0;
  588. cmdBufBeginInfo.pInheritanceInfo = &cmdBufInhInfo;
  589.  
  590. std::array<VkClearValue, 2> clearValues = {};
  591. clearValues[0].color.float32[0] = 0.5f;
  592. clearValues[0].color.float32[1] = 0.5f;
  593. clearValues[0].color.float32[2] = 0.5f;
  594. clearValues[0].color.float32[3] = 1.0f;
  595. clearValues[1].depthStencil = { 1.0f, 0 };
  596.  
  597. // build our drawing command buffers
  598. for (uint32_t i = 0; i < 2; ++i) {
  599. VKCHECK(vkBeginCommandBuffer(cmdBufs[i], &cmdBufBeginInfo));
  600.  
  601. VkImageMemoryBarrier imageMemBarrier = {};
  602. imageMemBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  603. imageMemBarrier.pNext = nullptr;
  604. imageMemBarrier.srcAccessMask = 0;
  605. imageMemBarrier.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  606. imageMemBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
  607. imageMemBarrier.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  608. imageMemBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  609. imageMemBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  610. imageMemBarrier.image = swapchainImages[i];
  611. imageMemBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
  612.  
  613. vkCmdPipelineBarrier(cmdBufs[i], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &imageMemBarrier);
  614.  
  615. VkRenderPassBeginInfo rpBeginInfo = {};
  616. rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
  617. rpBeginInfo.pNext = nullptr;
  618. rpBeginInfo.renderPass = renderPass;
  619. rpBeginInfo.framebuffer = framebuffers[i];
  620. rpBeginInfo.renderArea.offset.x = 0;
  621. rpBeginInfo.renderArea.offset.y = 0;
  622. rpBeginInfo.renderArea.extent.width = width;
  623. rpBeginInfo.renderArea.extent.height = height;
  624. rpBeginInfo.clearValueCount = 2;
  625. rpBeginInfo.pClearValues = clearValues.data();
  626.  
  627. vkCmdBeginRenderPass(cmdBufs[i], &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
  628. VkViewport viewport = {};
  629. viewport.width = static_cast<float>(width);
  630. viewport.height = static_cast<float>(height);
  631. viewport.minDepth = 0.0f;
  632. viewport.maxDepth = 1.0f;
  633. vkCmdSetViewport(cmdBufs[i], 0, 1, &viewport);
  634.  
  635. VkRect2D scissor = {};
  636. scissor.extent.width = width;
  637. scissor.extent.height = height;
  638. scissor.offset.x = 0;
  639. scissor.offset.y = 0;
  640. vkCmdSetScissor(cmdBufs[i], 0, 1, &scissor);
  641. vkCmdEndRenderPass(cmdBufs[i]);
  642.  
  643. VkImageMemoryBarrier prePresentBarrier = {};
  644. prePresentBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
  645. prePresentBarrier.pNext = nullptr;
  646. prePresentBarrier.srcAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
  647. prePresentBarrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT;
  648. prePresentBarrier.oldLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
  649. prePresentBarrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
  650. prePresentBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  651. prePresentBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
  652. prePresentBarrier.subresourceRange = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1 };
  653. prePresentBarrier.image = swapchainImages[i];
  654.  
  655. vkCmdPipelineBarrier(cmdBufs[i], VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0, 0, nullptr, 0, nullptr, 1, &prePresentBarrier);
  656. VKCHECK(vkEndCommandBuffer(cmdBufs[i]));
  657. }
  658.  
  659. // main loop
  660. while (!glfwWindowShouldClose(window)) {
  661. glfwPollEvents();
  662.  
  663. // do the rendering
  664. VkSemaphore presentCompleteSemaphore;
  665. VkSemaphoreCreateInfo pcsCreateInfo = {};
  666. pcsCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
  667. pcsCreateInfo.pNext = nullptr;
  668. pcsCreateInfo.flags = 0;
  669.  
  670. VKCHECK(vkCreateSemaphore(device, &pcsCreateInfo, nullptr, &presentCompleteSemaphore));
  671.  
  672. VkResult res = pfnAcquireNextImageKHR(device, swapchain, UINT64_MAX, presentCompleteSemaphore, VK_NULL_HANDLE, &currentSwapchainImage);
  673. if (res == VK_ERROR_OUT_OF_DATE_KHR) {
  674. assert(false && "Swapchain is out-of-date!");
  675. } else if (res == VK_SUBOPTIMAL_KHR) {
  676. } else {
  677. assert(res == VK_SUCCESS);
  678. }
  679.  
  680. VkSubmitInfo submitInfo = {};
  681. VkPipelineStageFlags pipelineStageFlags = VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
  682. submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
  683. submitInfo.pNext = nullptr;
  684. submitInfo.waitSemaphoreCount = 1;
  685. submitInfo.pWaitSemaphores = &presentCompleteSemaphore;
  686. submitInfo.pWaitDstStageMask = &pipelineStageFlags;
  687. submitInfo.commandBufferCount = 1;
  688. submitInfo.pCommandBuffers = &cmdBufs[currentSwapchainImage];
  689. submitInfo.signalSemaphoreCount = 0;
  690. submitInfo.pSignalSemaphores = nullptr;
  691.  
  692. res = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
  693. assert(res == VK_SUCCESS);
  694.  
  695. VkPresentInfoKHR present = {};
  696. present.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
  697. present.pNext = nullptr;
  698. present.swapchainCount = 1;
  699. present.pSwapchains = &swapchain;
  700. present.pImageIndices = &currentSwapchainImage;
  701.  
  702. res = pfnQueuePresentKHR(queue, &present);
  703. if (res == VK_ERROR_OUT_OF_DATE_KHR) {
  704. assert(false && "Swapchain out of date!");
  705. } else if (res == VK_SUBOPTIMAL_KHR) {
  706. } else {
  707. assert(res == VK_SUCCESS);
  708. }
  709.  
  710. res = vkQueueWaitIdle(queue);
  711. assert(res == VK_SUCCESS);
  712.  
  713. vkDestroySemaphore(device, presentCompleteSemaphore, nullptr);
  714. }
  715.  
  716. // free allocated resources
  717. vkDestroyRenderPass(device, renderPass, nullptr);
  718.  
  719. vkDestroyImageView(device, dsImageView, nullptr);
  720. vkDestroyImage(device, dsImage, nullptr);
  721. vkFreeMemory(device, dsMemory, nullptr);
  722.  
  723. vkFreeCommandBuffers(device, cmdPool, 2, cmdBufs.data());
  724. vkDestroyCommandPool(device, cmdPool, nullptr);
  725.  
  726. for (VkImageView pv : presentViews) {
  727. vkDestroyImageView(device, pv, nullptr);
  728. }
  729. for (VkFramebuffer fb : framebuffers) {
  730. vkDestroyFramebuffer(device, fb, nullptr);
  731. }
  732.  
  733. pfnDestroySwapchainKHR(device, swapchain, nullptr);
  734.  
  735. pfnDestroySurfaceKHR(instance, surface, nullptr);
  736.  
  737. glfwDestroyWindow(window);
  738. pfnDestroyDevice(device, nullptr);
  739. pfnDestroyDebugReportCallbackEXT(instance, debugReportCallback, nullptr);
  740. pfnDestroyInstance(instance, nullptr);
  741. glfwTerminate();
  742.  
  743. return 0;
  744. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement