Changeset c205c3a in opengl-game for Vulkan.cpp
- Timestamp:
- Nov 15, 2020, 3:18:33 PM (4 years ago)
- Branches:
- feature/imgui-sdl, master
- Children:
- 78c3045
- Parents:
- 57d43d0
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
Vulkan.cpp
r57d43d0 rc205c3a 1 2 //////////////////////////////////////////////////////////// 3 // Headers 4 //////////////////////////////////////////////////////////// 5 #define GLAD_VULKAN_IMPLEMENTATION 6 #include "vulkan.h" 7 8 // Include graphics because we use sf::Image for loading images 9 #include <SFML/Graphics.hpp> 10 11 #include <SFML/Window.hpp> 1 #include <vulkan/vulkan.h> 2 3 #include <iostream> 12 4 #include <vector> 13 5 #include <limits> … … 15 7 #include <cmath> 16 8 17 18 //////////////////////////////////////////////////////////// 19 // Helper functions 20 //////////////////////////////////////////////////////////// 21 namespace 22 { 9 #include <SFML/Window.hpp> 10 #include <SFML/Graphics.hpp> // Include graphics because we use sf::Image for loading images 11 12 #include "vulkan-utils-new.hpp" 13 14 using namespace std; 15 16 namespace { 17 18 #ifdef NDEBUG 19 const bool ENABLE_VALIDATION_LAYERS = false; 20 #else 21 const bool ENABLE_VALIDATION_LAYERS = true; 22 #endif 23 23 24 typedef float Vec3[3]; 24 25 typedef float Matrix[4][4]; 25 26 26 27 // Multiply 2 matrices 27 void matrixMultiply(Matrix& result, const Matrix& left, const Matrix& right) 28 { 28 void matrixMultiply(Matrix& result, const Matrix& left, const Matrix& right) { 29 29 Matrix temp; 30 30 … … 39 39 40 40 // Rotate a matrix around the x-axis 41 void matrixRotateX(Matrix& result, float angle) 42 { 41 void matrixRotateX(Matrix& result, float angle) { 43 42 Matrix matrix = { 44 43 {1.f, 0.f, 0.f, 0.f}, … … 52 51 53 52 // Rotate a matrix around the y-axis 54 void matrixRotateY(Matrix& result, float angle) 55 { 53 void matrixRotateY(Matrix& result, float angle) { 56 54 Matrix matrix = { 57 55 { std::cos(angle), 0.f, std::sin(angle), 0.f}, … … 65 63 66 64 // Rotate a matrix around the z-axis 67 void matrixRotateZ(Matrix& result, float angle) 68 { 65 void matrixRotateZ(Matrix& result, float angle) { 69 66 Matrix matrix = { 70 67 { std::cos(angle), std::sin(angle), 0.f, 0.f}, … … 78 75 79 76 // Construct a lookat view matrix 80 void matrixLookAt(Matrix& result, const Vec3& eye, const Vec3& center, const Vec3& up) 81 { 77 void matrixLookAt(Matrix& result, const Vec3& eye, const Vec3& center, const Vec3& up) { 82 78 // Forward-looking vector 83 79 Vec3 forward = { … … 90 86 float factor = 1.0f / std::sqrt(forward[0] * forward[0] + forward[1] * forward[1] + forward[2] * forward[2]); 91 87 92 for (int i = 0; i < 3; i++) 88 for (int i = 0; i < 3; i++) { 93 89 forward[i] = forward[i] * factor; 90 } 94 91 95 92 // Side vector (Forward cross product Up) … … 128 125 129 126 // Construct a perspective projection matrix 130 void matrixPerspective(Matrix& result, float fov, float aspect, float nearPlane, float farPlane) 131 { 127 void matrixPerspective(Matrix& result, float fov, float aspect, float nearPlane, float farPlane) { 132 128 const float a = 1.f / std::tan(fov / 2.f); 133 129 … … 155 151 // Clamp a value between low and high values 156 152 template<typename T> 157 T clamp(T value, T low, T high) 158 { 153 T clamp(T value, T low, T high) { 159 154 return (value <= low) ? low : ((value >= high) ? high : value); 160 155 } 161 156 162 // Helper function we pass to GLAD to load Vulkan functions via SFML 163 GLADapiproc getVulkanFunction(const char* name) 164 { 165 return reinterpret_cast<GLADapiproc>(sf::Vulkan::getFunction(name)); 166 } 167 168 // Debug we pass to Vulkan to call when it detects warnings or errors 169 VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugReportFlagsEXT, VkDebugReportObjectTypeEXT, uint64_t, size_t, int32_t, const char*, const char* pMessage, void*) 170 { 171 sf::err() << pMessage << std::endl; 157 VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( 158 VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, 159 VkDebugUtilsMessageTypeFlagsEXT messageType, 160 const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, 161 void* pUserData) { 162 cerr << "validation layer: " << pCallbackData->pMessage << endl; 172 163 173 164 return VK_FALSE; … … 176 167 177 168 178 //////////////////////////////////////////////////////////// 179 // VulkanExample class 180 //////////////////////////////////////////////////////////// 181 class VulkanExample 182 { 169 class VulkanExample { 183 170 public: 184 171 // Constructor … … 190 177 swapchainOutOfDate(false), 191 178 instance(0), 192 debugReportCallback(0),193 179 surface(0), 194 180 gpu(0), … … 220 206 descriptorPool(0) 221 207 { 208 const vector<const char*> validationLayers = { 209 "VK_LAYER_KHRONOS_validation", 210 "VK_LAYER_LUNARG_monitor" // This should show the FPS in the title bar 211 }; 212 222 213 // Vulkan setup procedure 223 if (vulkanAvailable) setupInstance( );224 if (vulkanAvailable) setupDebug ReportCallback();214 if (vulkanAvailable) setupInstance(validationLayers); 215 if (vulkanAvailable) setupDebugMessenger(); 225 216 if (vulkanAvailable) setupSurface(); 226 217 if (vulkanAvailable) setupPhysicalDevice(); … … 257 248 258 249 // Destructor 259 ~VulkanExample() 260 { 250 ~VulkanExample() { 261 251 // Wait until there are no pending frames 262 if (device) 252 if (device) { 263 253 vkDeviceWaitIdle(device); 254 } 264 255 265 256 // Teardown swapchain … … 327 318 vkDestroySurfaceKHR(instance, surface, 0); 328 319 329 if (debugReportCallback) 330 vkDestroyDebugReportCallbackEXT(instance, debugReportCallback, 0); 320 if (ENABLE_VALIDATION_LAYERS) { 321 VulkanUtilsNew::destroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); 322 } 331 323 332 324 if (instance) … … 335 327 336 328 // Cleanup swapchain 337 void cleanupSwapchain() 338 { 329 void cleanupSwapchain() { 339 330 // Swapchain teardown procedure 340 331 for (std::size_t i = 0; i < fences.size(); i++) … … 351 342 swapchainFramebuffers.clear(); 352 343 353 if (graphicsPipeline) 344 if (graphicsPipeline) { 354 345 vkDestroyPipeline(device, graphicsPipeline, 0); 346 } 355 347 356 348 if (renderPass) … … 374 366 swapchainImageViews.clear(); 375 367 376 if (swapchain) 368 if (swapchain) { 377 369 vkDestroySwapchainKHR(device, swapchain, 0); 370 } 378 371 } 379 372 380 373 // Cleanup and recreate swapchain 381 void recreateSwapchain() 382 { 374 void recreateSwapchain() { 375 cout << "Recreating pipeline..." << endl; 376 383 377 // Wait until there are no pending frames 384 378 vkDeviceWaitIdle(device); … … 401 395 402 396 // Setup Vulkan instance 403 void setupInstance() 404 { 405 // Load bootstrap entry points 406 gladLoadVulkan(0, getVulkanFunction); 407 408 if (!vkCreateInstance) 409 { 410 vulkanAvailable = false; 411 return; 412 } 413 414 // Retrieve the available instance layers 415 uint32_t objectCount = 0; 416 417 std::vector<VkLayerProperties> layers; 418 419 if (vkEnumerateInstanceLayerProperties(&objectCount, 0) != VK_SUCCESS) 420 { 421 vulkanAvailable = false; 422 return; 423 } 424 425 layers.resize(objectCount); 426 427 if (vkEnumerateInstanceLayerProperties(&objectCount, &layers[0]) != VK_SUCCESS) 428 { 429 vulkanAvailable = false; 430 return; 431 } 432 433 // Activate the layers we are interested in 434 std::vector<const char*> validationLayers; 435 436 for (std::size_t i = 0; i < layers.size(); i++) 437 { 438 // VK_LAYER_LUNARG_standard_validation, meta-layer for the following layers: 439 // -- VK_LAYER_GOOGLE_threading 440 // -- VK_LAYER_LUNARG_parameter_validation 441 // -- VK_LAYER_LUNARG_device_limits 442 // -- VK_LAYER_LUNARG_object_tracker 443 // -- VK_LAYER_LUNARG_image 444 // -- VK_LAYER_LUNARG_core_validation 445 // -- VK_LAYER_LUNARG_swapchain 446 // -- VK_LAYER_GOOGLE_unique_objects 447 // These layers perform error checking and warn about bad or sub-optimal Vulkan API usage 448 // VK_LAYER_LUNARG_monitor appends an FPS counter to the window title 449 if (!std::strcmp(layers[i].layerName, "VK_LAYER_LUNARG_standard_validation")) 450 { 451 validationLayers.push_back("VK_LAYER_LUNARG_standard_validation"); 452 } 453 else if (!std::strcmp(layers[i].layerName, "VK_LAYER_LUNARG_monitor")) 454 { 455 validationLayers.push_back("VK_LAYER_LUNARG_monitor"); 456 } 397 void setupInstance(const vector<const char*>& validationLayers) { 398 if (ENABLE_VALIDATION_LAYERS && !VulkanUtilsNew::checkValidationLayerSupport(validationLayers)) { 399 throw runtime_error("validation layers requested, but not available!"); 457 400 } 458 401 459 402 // Retrieve the extensions we need to enable in order to use Vulkan with SFML 460 403 std::vector<const char*> requiredExtentions = sf::Vulkan::getGraphicsRequiredInstanceExtensions(); 461 requiredExtentions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); 404 if (ENABLE_VALIDATION_LAYERS) { 405 requiredExtentions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); 406 } 462 407 463 408 // Register our application information … … 473 418 instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 474 419 instanceCreateInfo.pApplicationInfo = &applicationInfo; 475 instanceCreateInfo.enabledLayerCount = validationLayers.size(); 476 instanceCreateInfo.ppEnabledLayerNames = &validationLayers[0]; 420 477 421 instanceCreateInfo.enabledExtensionCount = requiredExtentions.size(); 478 instanceCreateInfo.ppEnabledExtensionNames = &requiredExtentions[0]; 479 480 // Try to create a Vulkan instance with debug report enabled 481 VkResult result = vkCreateInstance(&instanceCreateInfo, 0, &instance); 482 483 // If an extension is missing, try disabling debug report 484 if (result == VK_ERROR_EXTENSION_NOT_PRESENT) 485 { 486 requiredExtentions.pop_back(); 487 488 instanceCreateInfo.enabledExtensionCount = requiredExtentions.size(); 489 instanceCreateInfo.ppEnabledExtensionNames = &requiredExtentions[0]; 490 491 result = vkCreateInstance(&instanceCreateInfo, 0, &instance); 492 } 493 494 // If instance creation still fails, give up 495 if (result != VK_SUCCESS) 496 { 497 vulkanAvailable = false; 498 return; 499 } 500 501 // Load instance entry points 502 gladLoadVulkan(0, getVulkanFunction); 422 instanceCreateInfo.ppEnabledExtensionNames = requiredExtentions.data(); 423 424 VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo; 425 if (ENABLE_VALIDATION_LAYERS) { 426 instanceCreateInfo.enabledLayerCount = validationLayers.size(); 427 instanceCreateInfo.ppEnabledLayerNames = validationLayers.data(); 428 429 populateDebugMessengerCreateInfo(debugCreateInfo); 430 instanceCreateInfo.pNext = &debugCreateInfo; 431 } else { 432 instanceCreateInfo.enabledLayerCount = 0; 433 434 instanceCreateInfo.pNext = nullptr; 435 } 436 437 if (vkCreateInstance(&instanceCreateInfo, nullptr, &instance) != VK_SUCCESS) { 438 throw runtime_error("failed to create instance!"); 439 } 440 } 441 442 void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) { 443 createInfo = {}; 444 createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; 445 // createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; 446 createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; 447 createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; 448 createInfo.pfnUserCallback = debugCallback; 503 449 } 504 450 505 451 // Setup our debug callback function to be called by Vulkan 506 void setupDebugReportCallback() 507 { 508 // Don't try to register the callback if the extension is not available 509 if (!vkCreateDebugReportCallbackEXT) 510 return; 511 512 // Register for warnings and errors 513 VkDebugReportCallbackCreateInfoEXT debugReportCallbackCreateInfo = VkDebugReportCallbackCreateInfoEXT(); 514 debugReportCallbackCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; 515 debugReportCallbackCreateInfo.flags = VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT | VK_DEBUG_REPORT_ERROR_BIT_EXT; 516 debugReportCallbackCreateInfo.pfnCallback = debugCallback; 517 518 // Create the debug callback 519 if (vkCreateDebugReportCallbackEXT(instance, &debugReportCallbackCreateInfo, 0, &debugReportCallback) != VK_SUCCESS) 520 { 521 vulkanAvailable = false; 522 return; 452 void setupDebugMessenger() { 453 if (!ENABLE_VALIDATION_LAYERS) return; 454 455 VkDebugUtilsMessengerCreateInfoEXT createInfo; 456 populateDebugMessengerCreateInfo(createInfo); 457 458 if (VulkanUtilsNew::createDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) { 459 throw runtime_error("failed to set up debug messenger!"); 523 460 } 524 461 } … … 613 550 return; 614 551 } 615 616 // Load physical device entry points617 gladLoadVulkan(gpu, getVulkanFunction);618 552 619 553 // Check what depth formats are available and select one … … 716 650 717 651 // Query surface formats and set up swapchain 718 void setupSwapchain() 719 {652 void setupSwapchain() { 653 cout << "STARTED CALL" << endl; 720 654 // Select a surface format that supports RGBA color format 721 655 uint32_t objectCount = 0; … … 723 657 std::vector<VkSurfaceFormatKHR> surfaceFormats; 724 658 725 if (vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &objectCount, 0) != VK_SUCCESS) 726 { 659 if (vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &objectCount, 0) != VK_SUCCESS) { 727 660 vulkanAvailable = false; 728 661 return; … … 731 664 surfaceFormats.resize(objectCount); 732 665 733 if (vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &objectCount, &surfaceFormats[0]) != VK_SUCCESS) 734 { 735 vulkanAvailable = false; 736 return; 737 } 738 739 if ((surfaceFormats.size() == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED)) 740 { 666 if (vkGetPhysicalDeviceSurfaceFormatsKHR(gpu, surface, &objectCount, &surfaceFormats[0]) != VK_SUCCESS) { 667 vulkanAvailable = false; 668 return; 669 } 670 671 if ((surfaceFormats.size() == 1) && (surfaceFormats[0].format == VK_FORMAT_UNDEFINED)) { 741 672 swapchainFormat.format = VK_FORMAT_B8G8R8A8_UNORM; 742 673 swapchainFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; 743 } 744 else if (!surfaceFormats.empty()) 745 { 746 for (std::size_t i = 0; i < surfaceFormats.size(); i++) 747 { 748 if ((surfaceFormats[i].format == VK_FORMAT_B8G8R8A8_UNORM) && (surfaceFormats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)) 749 { 674 } else if (!surfaceFormats.empty()) { 675 for (std::size_t i = 0; i < surfaceFormats.size(); i++) { 676 if ((surfaceFormats[i].format == VK_FORMAT_B8G8R8A8_UNORM) && (surfaceFormats[i].colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR)) { 750 677 swapchainFormat.format = VK_FORMAT_B8G8R8A8_UNORM; 751 678 swapchainFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; … … 755 682 } 756 683 757 if (swapchainFormat.format == VK_FORMAT_UNDEFINED) 684 if (swapchainFormat.format == VK_FORMAT_UNDEFINED) { 758 685 swapchainFormat = surfaceFormats[0]; 759 } 760 else 761 { 686 } 687 } else { 762 688 vulkanAvailable = false; 763 689 return; … … 767 693 std::vector<VkPresentModeKHR> presentModes; 768 694 769 if (vkGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &objectCount, 0) != VK_SUCCESS) 770 { 695 if (vkGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &objectCount, 0) != VK_SUCCESS) { 771 696 vulkanAvailable = false; 772 697 return; … … 775 700 presentModes.resize(objectCount); 776 701 777 if (vkGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &objectCount, &presentModes[0]) != VK_SUCCESS) 778 { 702 if (vkGetPhysicalDeviceSurfacePresentModesKHR(gpu, surface, &objectCount, &presentModes[0]) != VK_SUCCESS) { 779 703 vulkanAvailable = false; 780 704 return; … … 784 708 VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR; 785 709 786 for (std::size_t i = 0; i < presentModes.size(); i++) 787 { 788 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) 789 { 710 for (std::size_t i = 0; i < presentModes.size(); i++) { 711 if (presentModes[i] == VK_PRESENT_MODE_MAILBOX_KHR) { 790 712 presentMode = presentModes[i]; 791 713 break; … … 796 718 VkSurfaceCapabilitiesKHR surfaceCapabilities; 797 719 798 if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, surface, &surfaceCapabilities) != VK_SUCCESS) 799 { 720 if (vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu, surface, &surfaceCapabilities) != VK_SUCCESS) { 800 721 vulkanAvailable = false; 801 722 return; … … 824 745 825 746 // Create the swapchain 826 if (vkCreateSwapchainKHR(device, &swapchainCreateInfo, 0, &swapchain) != VK_SUCCESS) 827 { 747 if (vkCreateSwapchainKHR(device, &swapchainCreateInfo, 0, &swapchain) != VK_SUCCESS) { 828 748 vulkanAvailable = false; 829 749 return; … … 1057 977 1058 978 // Set up pipeline layout 1059 void setupPipelineLayout() 1060 { 979 void setupPipelineLayout() { 1061 980 VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo = VkPipelineLayoutCreateInfo(); 1062 981 pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; … … 1065 984 1066 985 // Create pipeline layout 1067 if (vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, 0, &pipelineLayout) != VK_SUCCESS) 1068 { 986 if (vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, 0, &pipelineLayout) != VK_SUCCESS) { 1069 987 vulkanAvailable = false; 1070 988 return; … … 1073 991 1074 992 // Set up rendering pipeline 1075 void setupPipeline() 1076 { 993 void setupPipeline() { 1077 994 // Set up how the vertex shader pulls data out of our vertex buffer 1078 995 VkVertexInputBindingDescription vertexInputBindingDescription = VkVertexInputBindingDescription(); … … 1199 1116 1200 1117 // Create our graphics pipeline 1201 if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, 0, &graphicsPipeline) != VK_SUCCESS) 1202 { 1203 vulkanAvailable = false; 1204 return; 1118 if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, 0, &graphicsPipeline) != VK_SUCCESS) { 1119 vulkanAvailable = false; 1205 1120 } 1206 1121 } 1207 1122 1208 1123 // Use our renderpass and swapchain images to create the corresponding framebuffers 1209 void setupFramebuffers() 1210 { 1124 void setupFramebuffers() { 1211 1125 swapchainFramebuffers.resize(swapchainImageViews.size()); 1212 1126 … … 1219 1133 framebufferCreateInfo.layers = 1; 1220 1134 1221 for (std::size_t i = 0; i < swapchainFramebuffers.size(); i++) 1222 { 1135 for (std::size_t i = 0; i < swapchainFramebuffers.size(); i++) { 1223 1136 // Each framebuffer consists of a corresponding swapchain image and the shared depth image 1224 1137 VkImageView attachments[] = { swapchainImageViews[i], depthImageView }; … … 1227 1140 1228 1141 // Create the framebuffer 1229 if (vkCreateFramebuffer(device, &framebufferCreateInfo, 0, &swapchainFramebuffers[i]) != VK_SUCCESS) 1230 { 1142 if (vkCreateFramebuffer(device, &framebufferCreateInfo, 0, &swapchainFramebuffers[i]) != VK_SUCCESS) { 1231 1143 vulkanAvailable = false; 1232 1144 return; … … 1236 1148 1237 1149 // Set up our command pool 1238 void setupCommandPool() 1239 { 1150 void setupCommandPool() { 1240 1151 // We want to be able to reset command buffers after submitting them 1241 1152 VkCommandPoolCreateInfo commandPoolCreateInfo = VkCommandPoolCreateInfo(); … … 1245 1156 1246 1157 // Create our command pool 1247 if (vkCreateCommandPool(device, &commandPoolCreateInfo, 0, &commandPool) != VK_SUCCESS) 1248 { 1158 if (vkCreateCommandPool(device, &commandPoolCreateInfo, 0, &commandPool) != VK_SUCCESS) { 1249 1159 vulkanAvailable = false; 1250 1160 return; … … 1253 1163 1254 1164 // Helper to create a generic buffer with the specified size, usage and memory flags 1255 bool createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& memory) 1256 { 1165 bool createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& memory) { 1257 1166 // We only have a single queue so we can request exclusive access 1258 1167 VkBufferCreateInfo bufferCreateInfo = VkBufferCreateInfo(); … … 1263 1172 1264 1173 // Create the buffer, this does not allocate any memory for it yet 1265 if (vkCreateBuffer(device, &bufferCreateInfo, 0, &buffer) != VK_SUCCESS) 1174 if (vkCreateBuffer(device, &bufferCreateInfo, 0, &buffer) != VK_SUCCESS) { 1266 1175 return false; 1176 } 1267 1177 1268 1178 // Check what kind of memory we need to request from the GPU … … 1276 1186 uint32_t memoryType = 0; 1277 1187 1278 for (; memoryType < memoryProperties.memoryTypeCount; memoryType++) 1279 { 1188 for (; memoryType < memoryProperties.memoryTypeCount; memoryType++) { 1280 1189 if ((memoryRequirements.memoryTypeBits & (1 << memoryType)) && 1281 ((memoryProperties.memoryTypes[memoryType].propertyFlags & properties) == properties))1190 ((memoryProperties.memoryTypes[memoryType].propertyFlags & properties) == properties)) { 1282 1191 break; 1283 } 1284 1285 if (memoryType == memoryProperties.memoryTypeCount) 1192 } 1193 } 1194 1195 if (memoryType == memoryProperties.memoryTypeCount) { 1286 1196 return false; 1197 } 1287 1198 1288 1199 VkMemoryAllocateInfo memoryAllocateInfo = VkMemoryAllocateInfo(); … … 1292 1203 1293 1204 // Allocate the memory out of the GPU pool for the required memory type 1294 if (vkAllocateMemory(device, &memoryAllocateInfo, 0, &memory) != VK_SUCCESS) 1205 if (vkAllocateMemory(device, &memoryAllocateInfo, 0, &memory) != VK_SUCCESS) { 1295 1206 return false; 1207 } 1296 1208 1297 1209 // Bind the allocated memory to our buffer object 1298 if (vkBindBufferMemory(device, buffer, memory, 0) != VK_SUCCESS) 1210 if (vkBindBufferMemory(device, buffer, memory, 0) != VK_SUCCESS) { 1299 1211 return false; 1212 } 1300 1213 1301 1214 return true; … … 1303 1216 1304 1217 // Helper to copy the contents of one buffer to another buffer 1305 bool copyBuffer(VkBuffer dst, VkBuffer src, VkDeviceSize size) 1306 { 1218 bool copyBuffer(VkBuffer dst, VkBuffer src, VkDeviceSize size) { 1307 1219 // Allocate a primary command buffer out of our command pool 1308 1220 VkCommandBufferAllocateInfo commandBufferAllocateInfo = VkCommandBufferAllocateInfo(); … … 1314 1226 VkCommandBuffer commandBuffer; 1315 1227 1316 if (vkAllocateCommandBuffers(device, &commandBufferAllocateInfo, &commandBuffer) != VK_SUCCESS) 1228 if (vkAllocateCommandBuffers(device, &commandBufferAllocateInfo, &commandBuffer) != VK_SUCCESS) { 1317 1229 return false; 1230 } 1318 1231 1319 1232 // Begin the command buffer … … 1322 1235 commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; 1323 1236 1324 if (vkBeginCommandBuffer(commandBuffer, &commandBufferBeginInfo) != VK_SUCCESS) 1325 { 1237 if (vkBeginCommandBuffer(commandBuffer, &commandBufferBeginInfo) != VK_SUCCESS) { 1326 1238 vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer); 1327 1239 … … 1345 1257 submitInfo.pCommandBuffers = &commandBuffer; 1346 1258 1347 if (vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE) != VK_SUCCESS) 1348 { 1259 if (vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE) != VK_SUCCESS) { 1349 1260 vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer); 1350 1261 … … 1353 1264 1354 1265 // Ensure the command buffer has been processed 1355 if (vkQueueWaitIdle(queue) != VK_SUCCESS) 1356 { 1266 if (vkQueueWaitIdle(queue) != VK_SUCCESS) { 1357 1267 vkFreeCommandBuffers(device, commandPool, 1, &commandBuffer); 1358 1268 … … 1367 1277 1368 1278 // Create our vertex buffer and upload its data 1369 void setupVertexBuffer() 1370 { 1279 void setupVertexBuffer() { 1371 1280 float vertexData[] = { 1372 1281 // X Y Z R G B A U V … … 2376 2285 } 2377 2286 2378 void draw() 2379 { 2287 void draw() { 2380 2288 uint32_t imageIndex = 0; 2381 2289 … … 2383 2291 vkWaitForFences(device, 1, &fences[currentFrame], VK_TRUE, std::numeric_limits<uint64_t>::max()); 2384 2292 2385 { 2386 // Get the next image in the swapchain 2387 VkResult result = vkAcquireNextImageKHR(device, swapchain, std::numeric_limits<uint64_t>::max(), imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); 2388 2389 // Check if we need to re-create the swapchain (e.g. if the window was resized) 2390 if (result == VK_ERROR_OUT_OF_DATE_KHR) 2391 { 2392 recreateSwapchain(); 2393 swapchainOutOfDate = false; 2394 return; 2395 } 2396 2397 if ((result != VK_SUCCESS) && (result != VK_TIMEOUT) && (result != VK_NOT_READY) && (result != VK_SUBOPTIMAL_KHR)) 2398 { 2399 vulkanAvailable = false; 2400 return; 2401 } 2293 // Get the next image in the swapchain 2294 VkResult result = vkAcquireNextImageKHR(device, swapchain, std::numeric_limits<uint64_t>::max(), imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); 2295 2296 // Check if we need to re-create the swapchain (e.g. if the window was resized) 2297 if (result == VK_ERROR_OUT_OF_DATE_KHR) { 2298 recreateSwapchain(); 2299 swapchainOutOfDate = false; 2300 return; 2301 } 2302 2303 // && result != VK_TIMEOUT && result != VK_NOT_READY 2304 if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { 2305 throw runtime_error("failed to acquire swap chain image!"); 2306 vulkanAvailable = false; 2307 return; 2402 2308 } 2403 2309 … … 2418 2324 vkResetFences(device, 1, &fences[currentFrame]); 2419 2325 2420 if (vkQueueSubmit(queue, 1, &submitInfo, fences[currentFrame]) != VK_SUCCESS) 2421 { 2326 if (vkQueueSubmit(queue, 1, &submitInfo, fences[currentFrame]) != VK_SUCCESS) { 2422 2327 vulkanAvailable = false; 2423 2328 return; … … 2433 2338 presentInfo.pImageIndices = &imageIndex; 2434 2339 2435 { 2436 // Queue presentation 2437 VkResult result = vkQueuePresentKHR(queue, &presentInfo); 2438 2439 // Check if we need to re-create the swapchain (e.g. if the window was resized) 2440 if ((result == VK_ERROR_OUT_OF_DATE_KHR) || (result == VK_SUBOPTIMAL_KHR) || swapchainOutOfDate) 2441 { 2442 recreateSwapchain(); 2443 swapchainOutOfDate = false; 2444 } 2445 else if (result != VK_SUCCESS) 2446 { 2447 vulkanAvailable = false; 2448 return; 2449 } 2340 // Queue presentation 2341 result = vkQueuePresentKHR(queue, &presentInfo); 2342 2343 // Check if we need to re-create the swapchain (e.g. if the window was resized) 2344 if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || swapchainOutOfDate) { 2345 recreateSwapchain(); 2346 swapchainOutOfDate = false; 2347 } else if (result != VK_SUCCESS) { 2348 throw runtime_error("failed to present swap chain image!"); 2349 vulkanAvailable = false; 2350 return; 2450 2351 } 2451 2352 … … 2463 2364 // Process events 2464 2365 sf::Event event; 2465 while (window.pollEvent(event)) 2466 { 2366 while (window.pollEvent(event)) { 2467 2367 // Close window: exit 2468 2368 if (event.type == sf::Event::Closed) … … 2478 2378 } 2479 2379 2480 if (vulkanAvailable) 2481 { 2380 if (vulkanAvailable) { 2482 2381 // Update the uniform buffer (matrices) 2483 2382 updateUniformBuffer(clock.getElapsedTime().asSeconds()); … … 2499 2398 2500 2399 VkInstance instance; 2501 VkDebug ReportCallbackEXT debugReportCallback;2400 VkDebugUtilsMessengerEXT debugMessenger; 2502 2401 VkSurfaceKHR surface; 2503 2402 VkPhysicalDevice gpu;
Note:
See TracChangeset
for help on using the changeset viewer.