26 glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
29 glfwSetWindowUserPointer(
window,
this);
38 double last_time_print = glfwGetTime();
40 while (!glfwWindowShouldClose(
window)) {
47 if (glfwGetTime() - last_time_print > 1.0 + std::numeric_limits<double>::epsilon()) {
48 std::ostringstream oss;
49 oss <<
TITLE <<
" - " << fps <<
" fps";
51 glfwSetWindowTitle(
window, oss.str().c_str());
53 last_time_print = glfwGetTime();
91 vkEnumerateInstanceLayerProperties(&layerCount,
nullptr);
93 std::vector<VkLayerProperties> availableLayers(layerCount);
94 vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
96 std::cout <<
"Available Validation Layers:" << std::endl;
97 for (
const auto& layerProperties : availableLayers) {
98 std::cout <<
" " << layerProperties.layerName << std::endl;
100 std::cout <<
"-----------------------------" << std::endl;
103 bool layerFound =
false;
105 for (
const auto& layerProperties : availableLayers) {
106 if (strcmp(layerName, layerProperties.layerName) == 0) {
120 uint32_t glfwExtensionCount = 0;
121 const char** glfwExtensions;
122 glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
124 std::vector<const char*> extensions(glfwExtensions, glfwExtensions + glfwExtensionCount);
127 extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
135 throw std::runtime_error(
"Validation layers requested, but not available !");
138 VkApplicationInfo appInfo{};
139 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
140 appInfo.pApplicationName =
TITLE;
141 appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
142 appInfo.pEngineName =
"No Engine";
143 appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
144 appInfo.apiVersion = VK_API_VERSION_1_0;
146 VkInstanceCreateInfo createInfo{};
147 createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
148 createInfo.pApplicationInfo = &appInfo;
152 extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
154 createInfo.enabledExtensionCount =
static_cast<uint32_t
>(extensions.size());
155 createInfo.ppEnabledExtensionNames = extensions.data();
157 VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
159 createInfo.enabledLayerCount =
static_cast<uint32_t
>(
validationLayers.size());
163 createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo;
165 createInfo.enabledLayerCount = 0;
167 createInfo.pNext =
nullptr;
171 createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
174 if (vkCreateInstance(&createInfo,
nullptr, &
instance) != VK_SUCCESS) {
175 throw std::runtime_error(
"Failed to create instance !");
181 throw std::runtime_error(
"Failed to create window surface !");
186 uint32_t extensionCount;
187 vkEnumerateDeviceExtensionProperties(
device,
nullptr, &extensionCount,
nullptr);
189 std::vector<VkExtensionProperties> availableExtensions(extensionCount);
190 vkEnumerateDeviceExtensionProperties(
device,
nullptr, &extensionCount, availableExtensions.data());
194 for (
const auto& extension : availableExtensions) {
195 requiredExtensions.erase(extension.extensionName);
198 return requiredExtensions.empty();
206 bool swapChainAdequate =
false;
207 if (extensionsSupported) {
209 swapChainAdequate = !swapChainSupport.
formats.empty() && !swapChainSupport.
presentModes.empty();
212 VkPhysicalDeviceFeatures supportedFeatures;
213 vkGetPhysicalDeviceFeatures(
device, &supportedFeatures);
215 return indices.isComplete() && extensionsSupported && swapChainAdequate && supportedFeatures.samplerAnisotropy;
219 uint32_t deviceCount = 0;
220 vkEnumeratePhysicalDevices(
instance, &deviceCount,
nullptr);
222 if (deviceCount == 0) {
223 throw std::runtime_error(
"Failed to find GPUs with Vulkan support !");
226 std::vector<VkPhysicalDevice> devices(deviceCount);
227 vkEnumeratePhysicalDevices(
instance, &deviceCount, devices.data());
229 for (
const auto&
device : devices) {
238 throw std::runtime_error(
"Failed to find a suitable GPU !");
245 std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
246 std::set<uint32_t> uniqueQueueFamilies = {
indices.graphicsFamily.value(),
indices.presentFamily.value()};
248 float queuePriority = 1.0f;
249 for (uint32_t queueFamily : uniqueQueueFamilies) {
250 VkDeviceQueueCreateInfo queueCreateInfo{};
251 queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
252 queueCreateInfo.queueFamilyIndex = queueFamily;
253 queueCreateInfo.queueCount = 1;
254 queueCreateInfo.pQueuePriorities = &queuePriority;
255 queueCreateInfos.push_back(queueCreateInfo);
258 VkPhysicalDeviceFeatures deviceFeatures{};
259 deviceFeatures.samplerAnisotropy = VK_TRUE;
260 deviceFeatures.sampleRateShading = VK_TRUE;
262 VkDeviceCreateInfo createInfo{};
263 createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
265 createInfo.queueCreateInfoCount =
static_cast<uint32_t
>(queueCreateInfos.size());
266 createInfo.pQueueCreateInfos = queueCreateInfos.data();
268 createInfo.pEnabledFeatures = &deviceFeatures;
270 createInfo.enabledExtensionCount =
static_cast<uint32_t
>(
deviceExtensions.size());
274 createInfo.enabledLayerCount =
static_cast<uint32_t
>(
validationLayers.size());
277 createInfo.enabledLayerCount = 0;
281 throw std::runtime_error(
"Failed to create logical device !");
289 for (
const auto& availableFormat : availableFormats) {
290 if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
291 return availableFormat;
295 return availableFormats[0];
299 for (
const auto& availablePresentMode : availablePresentModes) {
300 if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
301 return availablePresentMode;
305 return VK_PRESENT_MODE_FIFO_KHR;
309 if (capabilities.currentExtent.width != std::numeric_limits<uint32_t>::max()) {
310 return capabilities.currentExtent;
313 glfwGetFramebufferSize(
window, &width, &height);
315 VkExtent2D actualExtent = {
316 static_cast<uint32_t
>(width),
317 static_cast<uint32_t
>(height)
320 actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width);
321 actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height);
332 uint32_t formatCount;
333 vkGetPhysicalDeviceSurfaceFormatsKHR(
device,
surface, &formatCount,
nullptr);
335 if (formatCount != 0) {
336 details.
formats.resize(formatCount);
340 uint32_t presentModeCount;
341 vkGetPhysicalDeviceSurfacePresentModesKHR(
device,
surface, &presentModeCount,
nullptr);
343 if (presentModeCount != 0) {
358 uint32_t imageCount = swapChainSupport.
capabilities.minImageCount + 1;
360 imageCount = swapChainSupport.
capabilities.maxImageCount;
363 VkSwapchainCreateInfoKHR createInfo{};
364 createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
367 createInfo.minImageCount = imageCount;
368 createInfo.imageFormat = surfaceFormat.format;
369 createInfo.imageColorSpace = surfaceFormat.colorSpace;
370 createInfo.imageExtent = extent;
371 createInfo.imageArrayLayers = 1;
372 createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
375 uint32_t queueFamilyIndices[] = {
indices.graphicsFamily.value(),
indices.presentFamily.value()};
378 createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT;
379 createInfo.queueFamilyIndexCount = 2;
380 createInfo.pQueueFamilyIndices = queueFamilyIndices;
382 createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
385 createInfo.preTransform = swapChainSupport.
capabilities.currentTransform;
386 createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
387 createInfo.presentMode = presentMode;
388 createInfo.clipped = VK_TRUE;
390 createInfo.oldSwapchain = VK_NULL_HANDLE;
392 if (vkCreateSwapchainKHR(
device, &createInfo,
nullptr, &
swapChain) != VK_SUCCESS) {
393 throw std::runtime_error(
"Failed to create swap chain !");
405 int width = 0, height = 0;
406 glfwGetFramebufferSize(
window, &width, &height);
407 while (width == 0 || height == 0) {
408 glfwGetFramebufferSize(
window, &width, &height);
const std::vector< const char * > validationLayers
const std::vector< const char * > deviceExtensions
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector< VkSurfaceFormatKHR > &availableFormats)
void createDescriptorSets()
std::vector< uint32_t > indices
void createDepthResources()
VkSampleCountFlagBits msaaSamples
void createVertexBuffer()
void createGraphicsPipeline()
static void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device)
VkPhysicalDevice physicalDevice
void createColorResources()
void createTextureImageView()
static void cursorPosCallback(GLFWwindow *window, double xpos, double ypos)
bool checkValidationLayerSupport()
std::vector< VkImage > swapChainImages
VkPresentModeKHR chooseSwapPresentMode(const std::vector< VkPresentModeKHR > &availablePresentModes)
void run(const std::string &objFile1)
void pickPhysicalDevice()
void createDescriptorSetLayout()
void transitionTextures()
VkExtent2D swapChainExtent
static void framebufferResizeCallback(GLFWwindow *window, int width, int height)
void createTextureImage()
void setupDebugMessenger()
std::vector< const char * > getRequiredExtensions()
void parseObjFile(const std::string &filename)
bool checkDeviceExtensionSupport(VkPhysicalDevice device)
bool isDeviceSuitable(VkPhysicalDevice device)
void createCommandBuffers()
void createUniformBuffers()
void createLogicalDevice()
void createFramebuffers()
void createTextureSampler()
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device)
void createDescriptorPool()
VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities)
void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT &createInfo)
static void mouseButtonCallback(GLFWwindow *window, int button, int action, int mods)
VkFormat swapChainImageFormat
VkSampleCountFlagBits getMaxUsableSampleCount()
std::vector< VkSurfaceFormatKHR > formats
VkSurfaceCapabilitiesKHR capabilities
std::vector< VkPresentModeKHR > presentModes