4#include <unordered_set>
8static VKAPI_ATTR VkBool32 VKAPI_CALL
debugCallback(
const VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
const VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
void *pUserData)
10 (void) pUserData; (void) messageSeverity; (void) messageType;
12 std::cerr <<
"validation layer: " << pCallbackData->pMessage <<
'\n';
16VkResult
CreateDebugUtilsMessengerEXT(
const VkInstance instance,
const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pDebugMessenger)
18 auto func =
reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT
>(vkGetInstanceProcAddr(instance,
"vkCreateDebugUtilsMessengerEXT"));
19 if (func !=
nullptr) {
20 return func(instance, pCreateInfo, pAllocator, pDebugMessenger);
23 return VK_ERROR_EXTENSION_NOT_PRESENT;
28 auto func =
reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT
>(vkGetInstanceProcAddr(instance,
"vkDestroyDebugUtilsMessengerEXT"));
29 if (func !=
nullptr) {
30 func(instance, debugMessenger, pAllocator);
46 vkDestroyCommandPool(device_, commandPool,
nullptr);
47 vkDestroyDevice(device_,
nullptr);
49 if (enableValidationLayers) {
53 vkDestroySurfaceKHR(instance, surface_,
nullptr);
54 vkDestroyInstance(instance,
nullptr);
59 if (enableValidationLayers && !checkValidationLayerSupport()) {
60 throw std::runtime_error(
"validation layers requested, but not available!");
63 VkApplicationInfo appInfo = {};
64 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
65 appInfo.pApplicationName =
"LittleVulkanEngine App";
66 appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
67 appInfo.pEngineName =
"No Engine";
68 appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
69 appInfo.apiVersion = VK_API_VERSION_1_0;
71 VkInstanceCreateInfo createInfo = {};
72 createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
73 createInfo.pApplicationInfo = &appInfo;
75 std::vector<const char *> extensions = getRequiredExtensions();
76 createInfo.enabledExtensionCount =
static_cast<uint32_t
>(extensions.size());
77 createInfo.ppEnabledExtensionNames = extensions.data();
79 VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo;
80 if (enableValidationLayers) {
81 createInfo.enabledLayerCount =
static_cast<uint32_t
>(validationLayers.size());
82 createInfo.ppEnabledLayerNames = validationLayers.data();
84 populateDebugMessengerCreateInfo(debugCreateInfo);
85 createInfo.pNext = &debugCreateInfo;
87 createInfo.enabledLayerCount = 0;
88 createInfo.pNext =
nullptr;
91 if (vkCreateInstance(&createInfo,
nullptr, &instance) != VK_SUCCESS) {
92 throw std::runtime_error(
"failed to create instance!");
95 hasGlfwRequiredInstanceExtensions();
100 uint32_t deviceCount = 0;
101 vkEnumeratePhysicalDevices(instance, &deviceCount,
nullptr);
102 if (deviceCount == 0) {
103 throw std::runtime_error(
"failed to find GPUs with Vulkan support!");
105 std::cout <<
"Device count: " << deviceCount <<
'\n';
106 std::vector<VkPhysicalDevice> devices(deviceCount);
107 vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
109 for (
const auto &device : devices) {
110 if (isDeviceSuitable(device)) {
111 physicalDevice = device;
116 if (physicalDevice == VK_NULL_HANDLE) {
117 throw std::runtime_error(
"failed to find a suitable GPU!");
120 vkGetPhysicalDeviceProperties(physicalDevice, &m_properties);
121 std::cout <<
"physical device: " << m_properties.deviceName <<
'\n';
128 std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
130 float queuePriority = 1.0F;
132 for (
const uint32_t queueFamily : uniqueQueueFamilies) {
133 VkDeviceQueueCreateInfo queueCreateInfo = {};
134 queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
135 queueCreateInfo.queueFamilyIndex = queueFamily;
136 queueCreateInfo.queueCount = 1;
137 queueCreateInfo.pQueuePriorities = &queuePriority;
138 queueCreateInfos.push_back(queueCreateInfo);
141 VkPhysicalDeviceFeatures deviceFeatures = {};
142 deviceFeatures.samplerAnisotropy = VK_TRUE;
144 VkDeviceCreateInfo createInfo = {};
145 createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
147 createInfo.queueCreateInfoCount =
static_cast<uint32_t
>(queueCreateInfos.size());
148 createInfo.pQueueCreateInfos = queueCreateInfos.data();
150 createInfo.pEnabledFeatures = &deviceFeatures;
151 createInfo.enabledExtensionCount =
static_cast<uint32_t
>(deviceExtensions.size());
152 createInfo.ppEnabledExtensionNames = deviceExtensions.data();
156 if (enableValidationLayers) {
157 createInfo.enabledLayerCount =
static_cast<uint32_t
>(validationLayers.size());
158 createInfo.ppEnabledLayerNames = validationLayers.data();
160 createInfo.enabledLayerCount = 0;
163 if (vkCreateDevice(physicalDevice, &createInfo,
nullptr, &device_) != VK_SUCCESS) {
164 throw std::runtime_error(
"failed to create logical device!");
167 vkGetDeviceQueue(device_, indices.
graphicsFamily, 0, &graphicsQueue_);
168 vkGetDeviceQueue(device_, indices.
presentFamily, 0, &presentQueue_);
175 VkCommandPoolCreateInfo poolInfo = {};
176 poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
178 poolInfo.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
180 if (vkCreateCommandPool(device_, &poolInfo,
nullptr, &commandPool) != VK_SUCCESS) {
181 throw std::runtime_error(
"failed to create command pool!");
188 const bool extensionsSupported = checkDeviceExtensionSupport(device);
189 bool swapChainAdequate =
false;
191 if (extensionsSupported) {
193 swapChainAdequate = !swapChainSupport.
formats.empty() && !swapChainSupport.
presentModes.empty();
196 VkPhysicalDeviceFeatures supportedFeatures;
197 vkGetPhysicalDeviceFeatures(device, &supportedFeatures);
199 return indices.
isComplete() && extensionsSupported && swapChainAdequate && (supportedFeatures.samplerAnisotropy != 0U);
205 createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
206 createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
207 VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
208 createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
209 VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
210 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
212 createInfo.pUserData =
nullptr;
217 if (!enableValidationLayers) {
return; }
218 VkDebugUtilsMessengerCreateInfoEXT createInfo;
219 populateDebugMessengerCreateInfo(createInfo);
221 throw std::runtime_error(
"failed to set up debug messenger!");
227 uint32_t layerCount = 0;
228 vkEnumerateInstanceLayerProperties(&layerCount,
nullptr);
230 std::vector<VkLayerProperties> availableLayers(layerCount);
231 vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
233 for (
const char *layerName : validationLayers) {
234 bool layerFound =
false;
236 for (
const auto &layerProperties : availableLayers) {
237 if (strcmp(layerName, layerProperties.layerName) == 0) {
252 uint32_t glfwExtensionCount = 0;
253 const char **glfwExtensions =
nullptr;
254 glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
256 std::vector<const char *> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
258 if (enableValidationLayers) {
259 extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
267 uint32_t extensionCount = 0;
268 vkEnumerateInstanceExtensionProperties(
nullptr, &extensionCount,
nullptr);
269 std::vector<VkExtensionProperties> extensions(extensionCount);
270 vkEnumerateInstanceExtensionProperties(
nullptr, &extensionCount, extensions.data());
272 std::cout <<
"available extensions:\n";
273 std::unordered_set<std::string> available;
274 for (
const auto &extension : extensions) {
275 std::cout <<
'\t' << extension.extensionName <<
'\n';
276 available.insert(extension.extensionName);
279 std::cout <<
"required extensions:\n";
280 const std::vector<const char *> requiredExtensions = getRequiredExtensions();
281 for (
const auto &required : requiredExtensions) {
282 std::cout <<
"\t" << required <<
'\n';
283 if (available.find(required) == available.end()) {
284 throw std::runtime_error(
"Missing required glfw extension");
291 uint32_t extensionCount = 0;
292 vkEnumerateDeviceExtensionProperties(device,
nullptr, &extensionCount,
nullptr);
294 std::vector<VkExtensionProperties> availableExtensions(extensionCount);
295 vkEnumerateDeviceExtensionProperties(device,
nullptr, &extensionCount, availableExtensions.data());
297 std::set<std::string> requiredExtensions(deviceExtensions.begin(), deviceExtensions.end());
298 for (
const auto &extension : availableExtensions) {
299 requiredExtensions.erase(extension.extensionName);
302 return requiredExtensions.empty();
309 uint32_t queueFamilyCount = 0;
310 vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount,
nullptr);
311 std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
312 vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
315 for (
const auto &queueFamily : queueFamilies) {
316 if (queueFamily.queueCount > 0 && ((queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0U)) {
320 VkBool32 presentSupport = 0U;
321 vkGetPhysicalDeviceSurfaceSupportKHR(device, index, surface_, &presentSupport);
322 if (queueFamily.queueCount > 0 && (presentSupport != 0U)) {
337 vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface_, &details.
capabilities);
338 uint32_t formatCount = 0;
340 vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface_, &formatCount,
nullptr);
341 if (formatCount != 0) {
342 details.
formats.resize(formatCount);
343 vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface_, &formatCount, details.
formats.data());
345 uint32_t presentModeCount = 0;
346 vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface_, &presentModeCount,
nullptr);
347 if (presentModeCount != 0) {
349 vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface_, &presentModeCount, details.
presentModes.data());
357 for (
const VkFormat format : candidates) {
358 VkFormatProperties props;
359 vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &props);
360 if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) {
362 }
if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) {
366 throw std::runtime_error(
"failed to find supported format!");
371 VkPhysicalDeviceMemoryProperties memProperties;
372 vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);
374 for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
375 if (((typeFilter & (1 << i)) != 0U) &&
376 (memProperties.memoryTypes[i].propertyFlags & propertiesp) == propertiesp) {
381 throw std::runtime_error(
"failed to find suitable m_memory type!");
384void ven::Device::createBuffer(
const VkDeviceSize size,
const VkBufferUsageFlags usage,
const VkMemoryPropertyFlags propertiesp, VkBuffer &buffer, VkDeviceMemory &bufferMemory)
const
386 VkBufferCreateInfo bufferInfo{};
387 bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
388 bufferInfo.size = size;
389 bufferInfo.usage = usage;
390 bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
392 if (vkCreateBuffer(device_, &bufferInfo,
nullptr, &buffer) != VK_SUCCESS) {
393 throw std::runtime_error(
"failed to create vertex m_buffer!");
396 VkMemoryRequirements memRequirements;
397 vkGetBufferMemoryRequirements(device_, buffer, &memRequirements);
399 VkMemoryAllocateInfo allocInfo{};
400 allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
401 allocInfo.allocationSize = memRequirements.size;
402 allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, propertiesp);
404 if (vkAllocateMemory(device_, &allocInfo,
nullptr, &bufferMemory) != VK_SUCCESS) {
405 throw std::runtime_error(
"failed to allocate vertex m_buffer m_memory!");
408 vkBindBufferMemory(device_, buffer, bufferMemory, 0);
413 VkCommandBufferAllocateInfo allocInfo{};
414 allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
415 allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
416 allocInfo.commandPool = commandPool;
417 allocInfo.commandBufferCount = 1;
419 VkCommandBuffer commandBuffer =
nullptr;
420 vkAllocateCommandBuffers(device_, &allocInfo, &commandBuffer);
422 VkCommandBufferBeginInfo beginInfo{};
423 beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
424 beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
426 vkBeginCommandBuffer(commandBuffer, &beginInfo);
427 return commandBuffer;
432 vkEndCommandBuffer(commandBuffer);
434 VkSubmitInfo submitInfo{};
435 submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
436 submitInfo.commandBufferCount = 1;
437 submitInfo.pCommandBuffers = &commandBuffer;
439 vkQueueSubmit(graphicsQueue_, 1, &submitInfo, VK_NULL_HANDLE);
440 vkQueueWaitIdle(graphicsQueue_);
442 vkFreeCommandBuffers(device_, commandPool, 1, &commandBuffer);
447 const VkCommandBuffer commandBuffer = beginSingleTimeCommands();
449 VkBufferCopy copyRegion{};
450 copyRegion.srcOffset = 0;
451 copyRegion.dstOffset = 0;
452 copyRegion.size = size;
453 vkCmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, 1, ©Region);
455 endSingleTimeCommands(commandBuffer);
460 const VkCommandBuffer commandBuffer = beginSingleTimeCommands();
462 VkBufferImageCopy region{};
463 region.bufferOffset = 0;
464 region.bufferRowLength = 0;
465 region.bufferImageHeight = 0;
467 region.imageSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
468 region.imageSubresource.mipLevel = 0;
469 region.imageSubresource.baseArrayLayer = 0;
470 region.imageSubresource.layerCount = layerCount;
472 region.imageOffset = {0, 0, 0};
473 region.imageExtent = {width, height, 1};
475 vkCmdCopyBufferToImage(commandBuffer, buffer, image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
476 endSingleTimeCommands(commandBuffer);
481 if (vkCreateImage(device_, &imageInfo,
nullptr, &image) != VK_SUCCESS) {
482 throw std::runtime_error(
"failed to create image!");
485 VkMemoryRequirements memRequirements;
486 vkGetImageMemoryRequirements(device_, image, &memRequirements);
488 VkMemoryAllocateInfo allocInfo{};
489 allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
490 allocInfo.allocationSize = memRequirements.size;
491 allocInfo.memoryTypeIndex = findMemoryType(memRequirements.memoryTypeBits, properties);
493 if (vkAllocateMemory(device_, &allocInfo,
nullptr, &imageMemory) != VK_SUCCESS) {
494 throw std::runtime_error(
"failed to allocate image m_memory!");
497 if (vkBindImageMemory(device_, image, imageMemory, 0) != VK_SUCCESS) {
498 throw std::runtime_error(
"failed to bind image m_memory!");
This file contains the Device class.
void endSingleTimeCommands(VkCommandBuffer commandBuffer) const
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) const
bool checkValidationLayerSupport() const
void setupDebugMessenger()
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags propertiesp) const
void pickPhysicalDevice()
bool checkDeviceExtensionSupport(VkPhysicalDevice device) const
void createLogicalDevice()
void createImageWithInfo(const VkImageCreateInfo &imageInfo, VkMemoryPropertyFlags properties, VkImage &image, VkDeviceMemory &imageMemory) const
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) const
VkCommandBuffer beginSingleTimeCommands() const
void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size) const
bool isDeviceSuitable(VkPhysicalDevice device) const
std::vector< const char * > getRequiredExtensions() const
void copyBufferToImage(VkBuffer buffer, VkImage image, uint32_t width, uint32_t height, uint32_t layerCount) const
static void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT &createInfo)
void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags propertiesp, VkBuffer &buffer, VkDeviceMemory &bufferMemory) const
void hasGlfwRequiredInstanceExtensions() const
VkFormat findSupportedFormat(const std::vector< VkFormat > &candidates, VkImageTiling tiling, VkFormatFeatureFlags features) const
void DestroyDebugUtilsMessengerEXT(const VkInstance instance, const VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks *pAllocator)
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(const VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, const VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData)
VkResult CreateDebugUtilsMessengerEXT(const VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pDebugMessenger)
bool presentFamilyHasValue
bool graphicsFamilyHasValue
std::vector< VkPresentModeKHR > presentModes
VkSurfaceCapabilitiesKHR capabilities
std::vector< VkSurfaceFormatKHR > formats