diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cf76f1..c624c5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,7 +29,21 @@ set(GLFW_LIBRARY "D:/code/vulkan_demo/glfw/lib/glfw3.lib") set(GLM_INCLUDE_DIR "D:/code/vulkan_demo/glm") # 添加可执行文件 -add_executable(${PROJECT_NAME} main.cpp) +add_executable(${PROJECT_NAME} + main.cpp + HelloTriangleApplication.cpp + VulkanDebug.cpp + Cleanup.cpp + SwapChain.cpp + PhysicalDevice.cpp + LogicDevice.cpp + Framebuffers.cpp + RenderPass.cpp + Pipeline.cpp + Image.cpp + Render.cpp + Command.cpp + ) # 包含目录 target_include_directories(${PROJECT_NAME} PRIVATE diff --git a/Cleanup.cpp b/Cleanup.cpp new file mode 100644 index 0000000..ecebf02 --- /dev/null +++ b/Cleanup.cpp @@ -0,0 +1,55 @@ +#include "HelloTriangleApplication.h" + + +void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) { + auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); + if (func != nullptr) { + func(instance, debugMessenger, pAllocator); + } +} + +void HelloTriangleApplication::cleanupSwapChain() { + for (auto framebuffer : swapChainFramebuffers) { + vkDestroyFramebuffer(device, framebuffer, nullptr); + } + + vkFreeCommandBuffers(device, commandPool, static_cast(commandBuffers.size()), commandBuffers.data()); + + vkDestroyPipeline(device, graphicsPipeline, nullptr); + vkDestroyPipelineLayout(device, pipelineLayout, nullptr); + vkDestroyRenderPass(device, renderPass, nullptr); + + for (auto imageView : swapChainImageViews) { + vkDestroyImageView(device, imageView, nullptr); + } + + vkDestroySwapchainKHR(device, swapChain, nullptr); + } + +void HelloTriangleApplication::cleanup() +{ + cleanupSwapChain(); + + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + { + vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr); + vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr); + vkDestroyFence(device, inFlightFences[i], nullptr); + } + + vkDestroyCommandPool(device, commandPool, nullptr); + + vkDestroyDevice(device, nullptr); + + if (enableValidationLayers) + { + DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); + } + + vkDestroySurfaceKHR(instance, surface, nullptr); + vkDestroyInstance(instance, nullptr); + + glfwDestroyWindow(window); + + glfwTerminate(); +} \ No newline at end of file diff --git a/Command.cpp b/Command.cpp new file mode 100644 index 0000000..8053b59 --- /dev/null +++ b/Command.cpp @@ -0,0 +1,66 @@ +#include "HelloTriangleApplication.h" + +void HelloTriangleApplication::createCommandPool() +{ + QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice); + + VkCommandPoolCreateInfo poolInfo{}; + poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value(); + + if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) + { + throw std::runtime_error("failed to create graphics command pool!"); + } +} + +void HelloTriangleApplication::createCommandBuffers() +{ + commandBuffers.resize(swapChainFramebuffers.size()); + + VkCommandBufferAllocateInfo allocInfo{}; + allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + allocInfo.commandPool = commandPool; + allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + allocInfo.commandBufferCount = (uint32_t)commandBuffers.size(); + + if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) + { + throw std::runtime_error("failed to allocate command buffers!"); + } + + for (size_t i = 0; i < commandBuffers.size(); i++) + { + VkCommandBufferBeginInfo beginInfo{}; + beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + + if (vkBeginCommandBuffer(commandBuffers[i], &beginInfo) != VK_SUCCESS) + { + throw std::runtime_error("failed to begin recording command buffer!"); + } + + VkRenderPassBeginInfo renderPassInfo{}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + renderPassInfo.renderPass = renderPass; + renderPassInfo.framebuffer = swapChainFramebuffers[i]; + renderPassInfo.renderArea.offset = {0, 0}; + renderPassInfo.renderArea.extent = swapChainExtent; + + VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; + renderPassInfo.clearValueCount = 1; + renderPassInfo.pClearValues = &clearColor; + + vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); + + vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); + + vkCmdDraw(commandBuffers[i], 3, 1, 0, 0); + + vkCmdEndRenderPass(commandBuffers[i]); + + if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) + { + throw std::runtime_error("failed to record command buffer!"); + } + } +} \ No newline at end of file diff --git a/Framebuffers.cpp b/Framebuffers.cpp new file mode 100644 index 0000000..af207d8 --- /dev/null +++ b/Framebuffers.cpp @@ -0,0 +1,26 @@ +#include "HelloTriangleApplication.h" + +void HelloTriangleApplication::createFramebuffers() +{ + swapChainFramebuffers.resize(swapChainImageViews.size()); + + for (size_t i = 0; i < swapChainImageViews.size(); i++) + { + VkImageView attachments[] = { + swapChainImageViews[i]}; + + VkFramebufferCreateInfo framebufferInfo{}; + framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + framebufferInfo.renderPass = renderPass; + framebufferInfo.attachmentCount = 1; + framebufferInfo.pAttachments = attachments; + framebufferInfo.width = swapChainExtent.width; + framebufferInfo.height = swapChainExtent.height; + framebufferInfo.layers = 1; + + if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) + { + throw std::runtime_error("failed to create framebuffer!"); + } + } +} \ No newline at end of file diff --git a/HelloTriangleApplication.cpp b/HelloTriangleApplication.cpp new file mode 100644 index 0000000..5123d3d --- /dev/null +++ b/HelloTriangleApplication.cpp @@ -0,0 +1,101 @@ +#include "HelloTriangleApplication.h" + +void HelloTriangleApplication::initWindow() +{ + glfwInit(); + + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + + window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan Triangle", nullptr, nullptr); + glfwSetWindowUserPointer(window, this); + glfwSetFramebufferSizeCallback(window, framebufferResizeCallback); +} + +void HelloTriangleApplication::initVulkan() +{ + createInstance(); + setupDebugMessenger(); + createSurface(); + pickPhysicalDevice(); + createLogicalDevice(); + createSwapChain(); + createImageViews(); + createRenderPass(); + createGraphicsPipeline(); + createFramebuffers(); + createCommandPool(); + createCommandBuffers(); + createSyncObjects(); +} + +void HelloTriangleApplication::createInstance() +{ + if (enableValidationLayers && !checkValidationLayerSupport()) + { + throw std::runtime_error("validation layers requested, but not available!"); + } + + VkApplicationInfo appInfo{}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = "Hello Triangle"; + appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.pEngineName = "No Engine"; + appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); + appInfo.apiVersion = VK_API_VERSION_1_0; + + VkInstanceCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &appInfo; + + auto extensions = getRequiredExtensions(); + createInfo.enabledExtensionCount = static_cast(extensions.size()); + createInfo.ppEnabledExtensionNames = extensions.data(); + + VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; + if (enableValidationLayers) + { + createInfo.enabledLayerCount = static_cast(validationLayers.size()); + createInfo.ppEnabledLayerNames = validationLayers.data(); + + populateDebugMessengerCreateInfo(debugCreateInfo); + createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT *)&debugCreateInfo; + } + else + { + createInfo.enabledLayerCount = 0; + + createInfo.pNext = nullptr; + } + + if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) + { + throw std::runtime_error("failed to create instance!"); + } +} + +void HelloTriangleApplication::mainLoop() +{ + while (!glfwWindowShouldClose(window)) + { + glfwPollEvents(); + drawFrame(); + } + + vkDeviceWaitIdle(device); +} + +VkShaderModule HelloTriangleApplication::createShaderModule(const std::vector &code) +{ + VkShaderModuleCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + createInfo.codeSize = code.size(); + createInfo.pCode = reinterpret_cast(code.data()); + + VkShaderModule shaderModule; + if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) + { + throw std::runtime_error("failed to create shader module!"); + } + + return shaderModule; +} \ No newline at end of file diff --git a/Image.cpp b/Image.cpp new file mode 100644 index 0000000..4bbf0b2 --- /dev/null +++ b/Image.cpp @@ -0,0 +1,29 @@ +#include "HelloTriangleApplication.h" + +void HelloTriangleApplication::createImageViews() +{ + swapChainImageViews.resize(swapChainImages.size()); + + for (size_t i = 0; i < swapChainImages.size(); i++) + { + VkImageViewCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + createInfo.image = swapChainImages[i]; + createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + createInfo.format = swapChainImageFormat; + createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + createInfo.subresourceRange.baseMipLevel = 0; + createInfo.subresourceRange.levelCount = 1; + createInfo.subresourceRange.baseArrayLayer = 0; + createInfo.subresourceRange.layerCount = 1; + + if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) + { + throw std::runtime_error("failed to create image views!"); + } + } +} \ No newline at end of file diff --git a/LogicDevice.cpp b/LogicDevice.cpp new file mode 100644 index 0000000..f6a3867 --- /dev/null +++ b/LogicDevice.cpp @@ -0,0 +1,51 @@ +#include "HelloTriangleApplication.h" + +void HelloTriangleApplication::createLogicalDevice() +{ + QueueFamilyIndices indices = findQueueFamilies(physicalDevice); + + std::vector queueCreateInfos; + std::set uniqueQueueFamilies = {indices.graphicsFamily.value(), indices.presentFamily.value()}; + + float queuePriority = 1.0f; + for (uint32_t queueFamily : uniqueQueueFamilies) + { + VkDeviceQueueCreateInfo queueCreateInfo{}; + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.queueFamilyIndex = queueFamily; + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = &queuePriority; + queueCreateInfos.push_back(queueCreateInfo); + } + + VkPhysicalDeviceFeatures deviceFeatures{}; + + VkDeviceCreateInfo createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + + createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); + createInfo.pQueueCreateInfos = queueCreateInfos.data(); + + createInfo.pEnabledFeatures = &deviceFeatures; + + createInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); + createInfo.ppEnabledExtensionNames = deviceExtensions.data(); + + if (enableValidationLayers) + { + createInfo.enabledLayerCount = static_cast(validationLayers.size()); + createInfo.ppEnabledLayerNames = validationLayers.data(); + } + else + { + createInfo.enabledLayerCount = 0; + } + + if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) + { + throw std::runtime_error("failed to create logical device!"); + } + + vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue); + vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue); +} \ No newline at end of file diff --git a/PhysicalDevice.cpp b/PhysicalDevice.cpp new file mode 100644 index 0000000..29937dc --- /dev/null +++ b/PhysicalDevice.cpp @@ -0,0 +1,43 @@ +#include "HelloTriangleApplication.h" + +void HelloTriangleApplication::pickPhysicalDevice() +{ + uint32_t deviceCount = 0; + vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); + + if (deviceCount == 0) + { + throw std::runtime_error("failed to find GPUs with Vulkan support!"); + } + + std::vector devices(deviceCount); + vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); + + for (const auto &device : devices) + { + if (isDeviceSuitable(device)) + { + physicalDevice = device; + break; + } + } + + if (physicalDevice == VK_NULL_HANDLE) + { + throw std::runtime_error("failed to find a suitable GPU!"); + } +} + +bool HelloTriangleApplication::isDeviceSuitable(VkPhysicalDevice device) { + QueueFamilyIndices indices = findQueueFamilies(device); + + bool extensionsSupported = checkDeviceExtensionSupport(device); + + bool swapChainAdequate = false; + if (extensionsSupported) { + SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device); + swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty(); + } + + return indices.isComplete() && extensionsSupported && swapChainAdequate; +} \ No newline at end of file diff --git a/Pipeline.cpp b/Pipeline.cpp new file mode 100644 index 0000000..31e21aa --- /dev/null +++ b/Pipeline.cpp @@ -0,0 +1,115 @@ +#include "HelloTriangleApplication.h" +void HelloTriangleApplication::createGraphicsPipeline() +{ + auto vertShaderCode = readFile("shaders/vert.spv"); + auto fragShaderCode = readFile("shaders/frag.spv"); + + VkShaderModule vertShaderModule = createShaderModule(vertShaderCode); + VkShaderModule fragShaderModule = createShaderModule(fragShaderCode); + + VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; + vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; + vertShaderStageInfo.module = vertShaderModule; + vertShaderStageInfo.pName = "main"; + + VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; + fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; + fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; + fragShaderStageInfo.module = fragShaderModule; + fragShaderStageInfo.pName = "main"; + + VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo}; + + VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; + vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; + vertexInputInfo.vertexBindingDescriptionCount = 0; + vertexInputInfo.vertexAttributeDescriptionCount = 0; + + VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; + inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; + inputAssembly.primitiveRestartEnable = VK_FALSE; + + VkViewport viewport{}; + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = (float)swapChainExtent.width; + viewport.height = (float)swapChainExtent.height; + viewport.minDepth = 0.0f; + viewport.maxDepth = 1.0f; + + VkRect2D scissor{}; + scissor.offset = {0, 0}; + scissor.extent = swapChainExtent; + + VkPipelineViewportStateCreateInfo viewportState{}; + viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + viewportState.viewportCount = 1; + viewportState.pViewports = &viewport; + viewportState.scissorCount = 1; + viewportState.pScissors = &scissor; + + VkPipelineRasterizationStateCreateInfo rasterizer{}; + rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; + rasterizer.depthClampEnable = VK_FALSE; + rasterizer.rasterizerDiscardEnable = VK_FALSE; + rasterizer.polygonMode = VK_POLYGON_MODE_FILL; + rasterizer.lineWidth = 1.0f; + rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; + rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; + rasterizer.depthBiasEnable = VK_FALSE; + + VkPipelineMultisampleStateCreateInfo multisampling{}; + multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + multisampling.sampleShadingEnable = VK_FALSE; + multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; + + VkPipelineColorBlendAttachmentState colorBlendAttachment{}; + colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; + colorBlendAttachment.blendEnable = VK_FALSE; + + VkPipelineColorBlendStateCreateInfo colorBlending{}; + colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; + colorBlending.logicOpEnable = VK_FALSE; + colorBlending.logicOp = VK_LOGIC_OP_COPY; + colorBlending.attachmentCount = 1; + colorBlending.pAttachments = &colorBlendAttachment; + colorBlending.blendConstants[0] = 0.0f; + colorBlending.blendConstants[1] = 0.0f; + colorBlending.blendConstants[2] = 0.0f; + colorBlending.blendConstants[3] = 0.0f; + + VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; + pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; + pipelineLayoutInfo.setLayoutCount = 0; + pipelineLayoutInfo.pushConstantRangeCount = 0; + + if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) + { + throw std::runtime_error("failed to create pipeline layout!"); + } + + VkGraphicsPipelineCreateInfo pipelineInfo{}; + pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + pipelineInfo.stageCount = 2; + pipelineInfo.pStages = shaderStages; + pipelineInfo.pVertexInputState = &vertexInputInfo; + pipelineInfo.pInputAssemblyState = &inputAssembly; + pipelineInfo.pViewportState = &viewportState; + pipelineInfo.pRasterizationState = &rasterizer; + pipelineInfo.pMultisampleState = &multisampling; + pipelineInfo.pColorBlendState = &colorBlending; + pipelineInfo.layout = pipelineLayout; + pipelineInfo.renderPass = renderPass; + pipelineInfo.subpass = 0; + pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; + + if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) + { + throw std::runtime_error("failed to create graphics pipeline!"); + } + + vkDestroyShaderModule(device, fragShaderModule, nullptr); + vkDestroyShaderModule(device, vertShaderModule, nullptr); +} \ No newline at end of file diff --git a/Render.cpp b/Render.cpp new file mode 100644 index 0000000..a4bf340 --- /dev/null +++ b/Render.cpp @@ -0,0 +1,101 @@ +#include "HelloTriangleApplication.h" + +void HelloTriangleApplication::createSyncObjects() +{ + imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT); + renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT); + inFlightFences.resize(MAX_FRAMES_IN_FLIGHT); + imagesInFlight.resize(swapChainImages.size(), VK_NULL_HANDLE); + + VkSemaphoreCreateInfo semaphoreInfo{}; + semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; + + VkFenceCreateInfo fenceInfo{}; + fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; + fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; + + for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) + { + if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]) != VK_SUCCESS || + vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS || + vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) + { + throw std::runtime_error("failed to create synchronization objects for a frame!"); + } + } +} + +void HelloTriangleApplication::drawFrame() +{ + vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); + + uint32_t imageIndex; + VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); + + if (result == VK_ERROR_OUT_OF_DATE_KHR) + { + recreateSwapChain(); + return; + } + else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) + { + throw std::runtime_error("failed to acquire swap chain image!"); + } + + // Check if a previous frame is using this image (i.e. there is its fence to wait on) + if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) + { + vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX); + } + // Mark the image as now being in use by this frame + imagesInFlight[imageIndex] = inFlightFences[currentFrame]; + + VkSubmitInfo submitInfo{}; + submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + + VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame]}; + VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; + submitInfo.waitSemaphoreCount = 1; + submitInfo.pWaitSemaphores = waitSemaphores; + submitInfo.pWaitDstStageMask = waitStages; + + submitInfo.commandBufferCount = 1; + submitInfo.pCommandBuffers = &commandBuffers[imageIndex]; + + VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]}; + submitInfo.signalSemaphoreCount = 1; + submitInfo.pSignalSemaphores = signalSemaphores; + + vkResetFences(device, 1, &inFlightFences[currentFrame]); + + if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) + { + throw std::runtime_error("failed to submit draw command buffer!"); + } + + VkPresentInfoKHR presentInfo{}; + presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; + + presentInfo.waitSemaphoreCount = 1; + presentInfo.pWaitSemaphores = signalSemaphores; + + VkSwapchainKHR swapChains[] = {swapChain}; + presentInfo.swapchainCount = 1; + presentInfo.pSwapchains = swapChains; + + presentInfo.pImageIndices = &imageIndex; + + result = vkQueuePresentKHR(presentQueue, &presentInfo); + + if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) + { + framebufferResized = false; + recreateSwapChain(); + } + else if (result != VK_SUCCESS) + { + throw std::runtime_error("failed to present swap chain image!"); + } + + currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; +} \ No newline at end of file diff --git a/RenderPass.cpp b/RenderPass.cpp new file mode 100644 index 0000000..b052b76 --- /dev/null +++ b/RenderPass.cpp @@ -0,0 +1,45 @@ +#include "HelloTriangleApplication.h" + +void HelloTriangleApplication::createRenderPass() +{ + VkAttachmentDescription colorAttachment{}; + colorAttachment.format = swapChainImageFormat; + colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; + colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; + colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; + colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; + colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; + + VkAttachmentReference colorAttachmentRef{}; + colorAttachmentRef.attachment = 0; + colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; + + VkSubpassDescription subpass{}; + subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; + subpass.colorAttachmentCount = 1; + subpass.pColorAttachments = &colorAttachmentRef; + + VkSubpassDependency dependency{}; + dependency.srcSubpass = VK_SUBPASS_EXTERNAL; + dependency.dstSubpass = 0; + dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.srcAccessMask = 0; + dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + VkRenderPassCreateInfo renderPassInfo{}; + renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; + renderPassInfo.attachmentCount = 1; + renderPassInfo.pAttachments = &colorAttachment; + renderPassInfo.subpassCount = 1; + renderPassInfo.pSubpasses = &subpass; + renderPassInfo.dependencyCount = 1; + renderPassInfo.pDependencies = &dependency; + + if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) + { + throw std::runtime_error("failed to create render pass!"); + } +} \ No newline at end of file diff --git a/SwapChain.cpp b/SwapChain.cpp new file mode 100644 index 0000000..8a15a9a --- /dev/null +++ b/SwapChain.cpp @@ -0,0 +1,157 @@ +#include "HelloTriangleApplication.h" + +void HelloTriangleApplication::createSwapChain() +{ + SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice); + + VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats); + VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes); + VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities); + + uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1; + if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) + { + imageCount = swapChainSupport.capabilities.maxImageCount; + } + + VkSwapchainCreateInfoKHR createInfo{}; + createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; + createInfo.surface = surface; + + createInfo.minImageCount = imageCount; + createInfo.imageFormat = surfaceFormat.format; + createInfo.imageColorSpace = surfaceFormat.colorSpace; + createInfo.imageExtent = extent; + createInfo.imageArrayLayers = 1; + createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + + QueueFamilyIndices indices = findQueueFamilies(physicalDevice); + uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(), indices.presentFamily.value()}; + + if (indices.graphicsFamily != indices.presentFamily) + { + createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; + createInfo.queueFamilyIndexCount = 2; + createInfo.pQueueFamilyIndices = queueFamilyIndices; + } + else + { + createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; + } + + createInfo.preTransform = swapChainSupport.capabilities.currentTransform; + createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; + createInfo.presentMode = presentMode; + createInfo.clipped = VK_TRUE; + + if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) + { + throw std::runtime_error("failed to create swap chain!"); + } + + vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr); + swapChainImages.resize(imageCount); + vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data()); + + swapChainImageFormat = surfaceFormat.format; + swapChainExtent = extent; +} + +VkSurfaceFormatKHR HelloTriangleApplication::chooseSwapSurfaceFormat(const std::vector &availableFormats) +{ + for (const auto &availableFormat : availableFormats) + { + if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + { + return availableFormat; + } + } + + return availableFormats[0]; +} + +VkPresentModeKHR HelloTriangleApplication::chooseSwapPresentMode(const std::vector &availablePresentModes) +{ + for (const auto &availablePresentMode : availablePresentModes) + { + if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) + { + return availablePresentMode; + } + } + + return VK_PRESENT_MODE_FIFO_KHR; +} + +VkExtent2D HelloTriangleApplication::chooseSwapExtent(const VkSurfaceCapabilitiesKHR &capabilities) +{ + if (capabilities.currentExtent.width != UINT32_MAX) + { + return capabilities.currentExtent; + } + else + { + int width, height; + glfwGetFramebufferSize(window, &width, &height); + + VkExtent2D actualExtent = { + static_cast(width), + static_cast(height)}; + + actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); + actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); + + return actualExtent; + } +} + +SwapChainSupportDetails HelloTriangleApplication::querySwapChainSupport(VkPhysicalDevice device) +{ + SwapChainSupportDetails details; + + vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities); + + uint32_t formatCount; + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr); + + if (formatCount != 0) + { + details.formats.resize(formatCount); + vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data()); + } + + uint32_t presentModeCount; + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr); + + if (presentModeCount != 0) + { + details.presentModes.resize(presentModeCount); + vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data()); + } + + return details; +} + +void HelloTriangleApplication::recreateSwapChain() +{ + int width = 0, height = 0; + glfwGetFramebufferSize(window, &width, &height); + while (width == 0 || height == 0) + { + glfwGetFramebufferSize(window, &width, &height); + glfwWaitEvents(); + } + + vkDeviceWaitIdle(device); + + cleanupSwapChain(); + + createSwapChain(); + createImageViews(); + createRenderPass(); + createGraphicsPipeline(); + createFramebuffers(); + createCommandBuffers(); + + imagesInFlight.resize(swapChainImages.size(), VK_NULL_HANDLE); +} \ No newline at end of file diff --git a/VulkanDebug.cpp b/VulkanDebug.cpp new file mode 100644 index 0000000..bf0746d --- /dev/null +++ b/VulkanDebug.cpp @@ -0,0 +1,37 @@ +#include "HelloTriangleApplication.h" + + +VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pDebugMessenger) +{ + auto func = (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); + if (func != nullptr) + { + return func(instance, pCreateInfo, pAllocator, pDebugMessenger); + } + else + { + return VK_ERROR_EXTENSION_NOT_PRESENT; + } +} + +void HelloTriangleApplication::setupDebugMessenger() +{ + if (!enableValidationLayers) + return; + + VkDebugUtilsMessengerCreateInfoEXT createInfo; + populateDebugMessengerCreateInfo(createInfo); + + if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) + { + throw std::runtime_error("failed to set up debug messenger!"); + } +} + +void HelloTriangleApplication::populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) { + createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + 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; + 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; + createInfo.pfnUserCallback = debugCallback; +} \ No newline at end of file diff --git a/build/CMakeFiles/4.1.0-rc4/CompilerIdCXX/CMakeCXXCompilerId.cpp b/build/CMakeFiles/4.1.0-rc4/CompilerIdCXX/CMakeCXXCompilerId.cpp new file mode 100644 index 0000000..b35f567 --- /dev/null +++ b/build/CMakeFiles/4.1.0-rc4/CompilerIdCXX/CMakeCXXCompilerId.cpp @@ -0,0 +1,949 @@ +/* This source file must have a .cpp extension so that all C++ compilers + recognize the extension without flags. Borland does not know .cxx for + example. */ +#ifndef __cplusplus +# error "A C compiler has been selected for C++." +#endif + +#if !defined(__has_include) +/* If the compiler does not have __has_include, pretend the answer is + always no. */ +# define __has_include(x) 0 +#endif + + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# if defined(__GNUC__) +# define SIMULATE_ID "GNU" +# endif + /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later, + except that a few beta releases use the old format with V=2021. */ +# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111 +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# if defined(__INTEL_COMPILER_UPDATE) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE) +# else +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# endif +# else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE) + /* The third version component from --version is an update index, + but no macro is provided for it. */ +# define COMPILER_VERSION_PATCH DEC(0) +# endif +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER) +# define COMPILER_ID "IntelLLVM" +#if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +#endif +#if defined(__GNUC__) +# define SIMULATE_ID "GNU" +#endif +/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and + * later. Look for 6 digit vs. 8 digit version number to decide encoding. + * VVVV is no smaller than the current year when a version is released. + */ +#if __INTEL_LLVM_COMPILER < 1000000L +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10) +#else +# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000) +# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100) +#endif +#if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +#endif +#if defined(__GNUC__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +#elif defined(__GNUG__) +# define SIMULATE_VERSION_MAJOR DEC(__GNUG__) +#endif +#if defined(__GNUC_MINOR__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +#endif +#if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +#endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) && __WATCOMC__ < 1200 +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__WATCOMC__) +# define COMPILER_ID "OpenWatcom" + /* __WATCOMC__ = VVRP + 1100 */ +# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100) +# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10) +# if (__WATCOMC__ % 10) > 0 +# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10) +# endif + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) && defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__open_xl__) && defined(__clang__) +# define COMPILER_ID "IBMClang" +# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__) +# define COMPILER_VERSION_MINOR DEC(__open_xl_release__) +# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__ibmxl__) && defined(__clang__) +# define COMPILER_ID "XLClang" +# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__) +# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__) +# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__) +# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__) + + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800 +# define COMPILER_ID "XL" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800 +# define COMPILER_ID "VisualAge" + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) + +#elif defined(__NVCOMPILER) +# define COMPILER_ID "NVHPC" +# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__) +# if defined(__NVCOMPILER_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(__clang__) && defined(__cray__) +# define COMPILER_ID "CrayClang" +# define COMPILER_VERSION_MAJOR DEC(__cray_major__) +# define COMPILER_VERSION_MINOR DEC(__cray_minor__) +# define COMPILER_VERSION_PATCH DEC(__cray_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__CLANG_FUJITSU) +# define COMPILER_ID "FujitsuClang" +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# define COMPILER_VERSION_INTERNAL_STR __clang_version__ + + +#elif defined(__FUJITSU) +# define COMPILER_ID "Fujitsu" +# if defined(__FCC_version__) +# define COMPILER_VERSION __FCC_version__ +# elif defined(__FCC_major__) +# define COMPILER_VERSION_MAJOR DEC(__FCC_major__) +# define COMPILER_VERSION_MINOR DEC(__FCC_minor__) +# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__) +# endif +# if defined(__fcc_version) +# define COMPILER_VERSION_INTERNAL DEC(__fcc_version) +# elif defined(__FCC_VERSION) +# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION) +# endif + + +#elif defined(__ghs__) +# define COMPILER_ID "GHS" +/* __GHS_VERSION_NUMBER = VVVVRP */ +# ifdef __GHS_VERSION_NUMBER +# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100) +# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10) +# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10) +# endif + +#elif defined(__TASKING__) +# define COMPILER_ID "Tasking" + # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000) + # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100) +# define COMPILER_VERSION_INTERNAL DEC(__VERSION__) + +#elif defined(__ORANGEC__) +# define COMPILER_ID "OrangeC" +# define COMPILER_VERSION_MAJOR DEC(__ORANGEC_MAJOR__) +# define COMPILER_VERSION_MINOR DEC(__ORANGEC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__ORANGEC_PATCHLEVEL__) + +#elif defined(__RENESAS__) +# define COMPILER_ID "Renesas" +/* __RENESAS_VERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__RENESAS_VERSION__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR HEX(__RENESAS_VERSION__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__RENESAS_VERSION__ >> 8 & 0xFF) + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__ARMCC_VERSION) && !defined(__clang__) +# define COMPILER_ID "ARMCC" +#if __ARMCC_VERSION >= 1000000 + /* __ARMCC_VERSION = VRRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#else + /* __ARMCC_VERSION = VRPPPP */ + # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000) + # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10) + # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000) +#endif + + +#elif defined(__clang__) && defined(__apple_build_version__) +# define COMPILER_ID "AppleClang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif +# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__) + +#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION) +# define COMPILER_ID "ARMClang" + # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000) + # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100) + # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION/100 % 100) +# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION) + +#elif defined(__clang__) && defined(__ti__) +# define COMPILER_ID "TIClang" + # define COMPILER_VERSION_MAJOR DEC(__ti_major__) + # define COMPILER_VERSION_MINOR DEC(__ti_minor__) + # define COMPILER_VERSION_PATCH DEC(__ti_patchlevel__) +# define COMPILER_VERSION_INTERNAL DEC(__ti_version__) + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# if defined(_MSC_VER) +# define SIMULATE_ID "MSVC" +# endif +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) +# if defined(_MSC_VER) + /* _MSC_VER = VVRR */ +# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100) +# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100) +# endif + +#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__)) +# define COMPILER_ID "LCC" +# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100) +# if defined(__LCC_MINOR__) +# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__) +# endif +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define SIMULATE_ID "GNU" +# define SIMULATE_VERSION_MAJOR DEC(__GNUC__) +# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif +# endif + +#elif defined(__GNUC__) || defined(__GNUG__) +# define COMPILER_ID "GNU" +# if defined(__GNUC__) +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# else +# define COMPILER_VERSION_MAJOR DEC(__GNUG__) +# endif +# if defined(__GNUC_MINOR__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# endif +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +#elif defined(_ADI_COMPILER) +# define COMPILER_ID "ADSP" +#if defined(__VERSIONNUM__) + /* __VERSIONNUM__ = 0xVVRRPPTT */ +# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF) +# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF) +# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF) +# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF) +#endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" +# if defined(__VER__) && defined(__ICCARM__) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000) +# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000) +# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__)) +# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100) +# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100)) +# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__) +# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__) +# endif + +#elif defined(__DCC__) && defined(_DIAB_TOOL) +# define COMPILER_ID "Diab" + # define COMPILER_VERSION_MAJOR DEC(__VERSION_MAJOR_NUMBER__) + # define COMPILER_VERSION_MINOR DEC(__VERSION_MINOR_NUMBER__) + # define COMPILER_VERSION_PATCH DEC(__VERSION_ARCH_FEATURE_NUMBER__) + # define COMPILER_VERSION_TWEAK DEC(__VERSION_BUG_FIX_NUMBER__) + + + +/* These compilers are either not known or too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; +#ifdef SIMULATE_ID +char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]"; +#endif + +#ifdef __QNXNTO__ +char const* qnxnto = "INFO" ":" "qnxnto[]"; +#endif + +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) +char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]"; +#endif + +#define STRINGIFY_HELPER(X) #X +#define STRINGIFY(X) STRINGIFY_HELPER(X) + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__MSYS__) +# define PLATFORM_ID "MSYS" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#elif defined(__WATCOMC__) +# if defined(__LINUX__) +# define PLATFORM_ID "Linux" + +# elif defined(__DOS__) +# define PLATFORM_ID "DOS" + +# elif defined(__OS2__) +# define PLATFORM_ID "OS2" + +# elif defined(__WINDOWS__) +# define PLATFORM_ID "Windows3x" + +# elif defined(__VXWORKS__) +# define PLATFORM_ID "VxWorks" + +# else /* unknown platform */ +# define PLATFORM_ID +# endif + +#elif defined(__INTEGRITY) +# if defined(INT_178B) +# define PLATFORM_ID "Integrity178" + +# else /* regular Integrity */ +# define PLATFORM_ID "Integrity" +# endif + +# elif defined(_ADI_COMPILER) +# define PLATFORM_ID "ADSP" + +#else /* unknown platform */ +# define PLATFORM_ID + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_ARM64EC) +# define ARCHITECTURE_ID "ARM64EC" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM64) +# define ARCHITECTURE_ID "ARM64" + +# elif defined(_M_ARM) +# if _M_ARM == 4 +# define ARCHITECTURE_ID "ARMV4I" +# elif _M_ARM == 5 +# define ARCHITECTURE_ID "ARMV5I" +# else +# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM) +# endif + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__WATCOMC__) +# if defined(_M_I86) +# define ARCHITECTURE_ID "I86" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC) +# if defined(__ICCARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__ICCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__ICCRH850__) +# define ARCHITECTURE_ID "RH850" + +# elif defined(__ICCRL78__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__ICCRISCV__) +# define ARCHITECTURE_ID "RISCV" + +# elif defined(__ICCAVR__) +# define ARCHITECTURE_ID "AVR" + +# elif defined(__ICC430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__ICCV850__) +# define ARCHITECTURE_ID "V850" + +# elif defined(__ICC8051__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__ICCSTM8__) +# define ARCHITECTURE_ID "STM8" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__ghs__) +# if defined(__PPC64__) +# define ARCHITECTURE_ID "PPC64" + +# elif defined(__ppc__) +# define ARCHITECTURE_ID "PPC" + +# elif defined(__ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__x86_64__) +# define ARCHITECTURE_ID "x64" + +# elif defined(__i386__) +# define ARCHITECTURE_ID "X86" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__clang__) && defined(__ti__) +# if defined(__ARM_ARCH) +# define ARCHITECTURE_ID "ARM" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__TI_COMPILER_VERSION__) +# if defined(__TI_ARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__MSP430__) +# define ARCHITECTURE_ID "MSP430" + +# elif defined(__TMS320C28XX__) +# define ARCHITECTURE_ID "TMS320C28x" + +# elif defined(__TMS320C6X__) || defined(_TMS320C6X) +# define ARCHITECTURE_ID "TMS320C6x" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +# elif defined(__ADSPSHARC__) +# define ARCHITECTURE_ID "SHARC" + +# elif defined(__ADSPBLACKFIN__) +# define ARCHITECTURE_ID "Blackfin" + +#elif defined(__TASKING__) + +# if defined(__CTC__) || defined(__CPTC__) +# define ARCHITECTURE_ID "TriCore" + +# elif defined(__CMCS__) +# define ARCHITECTURE_ID "MCS" + +# elif defined(__CARM__) || defined(__CPARM__) +# define ARCHITECTURE_ID "ARM" + +# elif defined(__CARC__) +# define ARCHITECTURE_ID "ARC" + +# elif defined(__C51__) +# define ARCHITECTURE_ID "8051" + +# elif defined(__CPCP__) +# define ARCHITECTURE_ID "PCP" + +# else +# define ARCHITECTURE_ID "" +# endif + +#elif defined(__RENESAS__) +# if defined(__CCRX__) +# define ARCHITECTURE_ID "RX" + +# elif defined(__CCRL__) +# define ARCHITECTURE_ID "RL78" + +# elif defined(__CCRH__) +# define ARCHITECTURE_ID "RH850" + +# else +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number. */ +#ifdef COMPILER_VERSION +char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]"; + +/* Construct a string literal encoding the version number components. */ +#elif defined(COMPILER_VERSION_MAJOR) +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct a string literal encoding the internal version number. */ +#ifdef COMPILER_VERSION_INTERNAL +char const info_version_internal[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_', + 'i','n','t','e','r','n','a','l','[', + COMPILER_VERSION_INTERNAL,']','\0'}; +#elif defined(COMPILER_VERSION_INTERNAL_STR) +char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]"; +#endif + +/* Construct a string literal encoding the version number components. */ +#ifdef SIMULATE_VERSION_MAJOR +char const info_simulate_version[] = { + 'I', 'N', 'F', 'O', ':', + 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[', + SIMULATE_VERSION_MAJOR, +# ifdef SIMULATE_VERSION_MINOR + '.', SIMULATE_VERSION_MINOR, +# ifdef SIMULATE_VERSION_PATCH + '.', SIMULATE_VERSION_PATCH, +# ifdef SIMULATE_VERSION_TWEAK + '.', SIMULATE_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +#define CXX_STD_98 199711L +#define CXX_STD_11 201103L +#define CXX_STD_14 201402L +#define CXX_STD_17 201703L +#define CXX_STD_20 202002L +#define CXX_STD_23 202302L + +#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) +# if _MSVC_LANG > CXX_STD_17 +# define CXX_STD _MSVC_LANG +# elif _MSVC_LANG == CXX_STD_17 && defined(__cpp_aggregate_paren_init) +# define CXX_STD CXX_STD_20 +# elif _MSVC_LANG > CXX_STD_14 && __cplusplus > CXX_STD_17 +# define CXX_STD CXX_STD_20 +# elif _MSVC_LANG > CXX_STD_14 +# define CXX_STD CXX_STD_17 +# elif defined(__INTEL_CXX11_MODE__) && defined(__cpp_aggregate_nsdmi) +# define CXX_STD CXX_STD_14 +# elif defined(__INTEL_CXX11_MODE__) +# define CXX_STD CXX_STD_11 +# else +# define CXX_STD CXX_STD_98 +# endif +#elif defined(_MSC_VER) && defined(_MSVC_LANG) +# if _MSVC_LANG > __cplusplus +# define CXX_STD _MSVC_LANG +# else +# define CXX_STD __cplusplus +# endif +#elif defined(__NVCOMPILER) +# if __cplusplus == CXX_STD_17 && defined(__cpp_aggregate_paren_init) +# define CXX_STD CXX_STD_20 +# else +# define CXX_STD __cplusplus +# endif +#elif defined(__INTEL_COMPILER) || defined(__PGI) +# if __cplusplus == CXX_STD_11 && defined(__cpp_namespace_attributes) +# define CXX_STD CXX_STD_17 +# elif __cplusplus == CXX_STD_11 && defined(__cpp_aggregate_nsdmi) +# define CXX_STD CXX_STD_14 +# else +# define CXX_STD __cplusplus +# endif +#elif (defined(__IBMCPP__) || defined(__ibmxl__)) && defined(__linux__) +# if __cplusplus == CXX_STD_11 && defined(__cpp_aggregate_nsdmi) +# define CXX_STD CXX_STD_14 +# else +# define CXX_STD __cplusplus +# endif +#elif __cplusplus == 1 && defined(__GXX_EXPERIMENTAL_CXX0X__) +# define CXX_STD CXX_STD_11 +#else +# define CXX_STD __cplusplus +#endif + +const char* info_language_standard_default = "INFO" ":" "standard_default[" +#if CXX_STD > CXX_STD_23 + "26" +#elif CXX_STD > CXX_STD_20 + "23" +#elif CXX_STD > CXX_STD_17 + "20" +#elif CXX_STD > CXX_STD_14 + "17" +#elif CXX_STD > CXX_STD_11 + "14" +#elif CXX_STD >= CXX_STD_11 + "11" +#else + "98" +#endif +"]"; + +const char* info_language_extensions_default = "INFO" ":" "extensions_default[" +#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \ + defined(__TI_COMPILER_VERSION__) || defined(__RENESAS__)) && \ + !defined(__STRICT_ANSI__) + "ON" +#else + "OFF" +#endif +"]"; + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif +#if defined(COMPILER_VERSION_INTERNAL) || defined(COMPILER_VERSION_INTERNAL_STR) + require += info_version_internal[argc]; +#endif +#ifdef SIMULATE_ID + require += info_simulate[argc]; +#endif +#ifdef SIMULATE_VERSION_MAJOR + require += info_simulate_version[argc]; +#endif +#if defined(__CRAYXT_COMPUTE_LINUX_TARGET) + require += info_cray[argc]; +#endif + require += info_language_standard_default[argc]; + require += info_language_extensions_default[argc]; + (void)argv; + return require; +} diff --git a/main.cpp b/main.cpp index 522f96a..bf6e044 100644 --- a/main.cpp +++ b/main.cpp @@ -1,955 +1,4 @@ -#define GLFW_INCLUDE_VULKAN -#include - -#define GLM_FORCE_RADIANS -#define GLM_FORCE_DEPTH_ZERO_TO_ONE -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -const int MAX_FRAMES_IN_FLIGHT = 2; - -const uint32_t WIDTH = 800; -const uint32_t HEIGHT = 600; - -const std::vector validationLayers = { - "VK_LAYER_KHRONOS_validation" -}; - -const std::vector deviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME -}; - -#ifdef NDEBUG -const bool enableValidationLayers = false; -#else -const bool enableValidationLayers = true; -#endif - -VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) { - auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); - if (func != nullptr) { - return func(instance, pCreateInfo, pAllocator, pDebugMessenger); - } else { - return VK_ERROR_EXTENSION_NOT_PRESENT; - } -} - -void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) { - auto func = (PFN_vkDestroyDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); - if (func != nullptr) { - func(instance, debugMessenger, pAllocator); - } -} - -struct QueueFamilyIndices { - std::optional graphicsFamily; - std::optional presentFamily; - - bool isComplete() { - return graphicsFamily.has_value() && presentFamily.has_value(); - } -}; - -struct SwapChainSupportDetails { - VkSurfaceCapabilitiesKHR capabilities; - std::vector formats; - std::vector presentModes; -}; - -class HelloTriangleApplication { -public: - void run() { - initWindow(); - initVulkan(); - mainLoop(); - cleanup(); - } - -private: - GLFWwindow* window; - - VkInstance instance; - VkDebugUtilsMessengerEXT debugMessenger; - VkSurfaceKHR surface; - - VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; - VkDevice device; - - VkQueue graphicsQueue; - VkQueue presentQueue; - - VkSwapchainKHR swapChain; - std::vector swapChainImages; - VkFormat swapChainImageFormat; - VkExtent2D swapChainExtent; - std::vector swapChainImageViews; - std::vector swapChainFramebuffers; - - VkRenderPass renderPass; - VkPipelineLayout pipelineLayout; - VkPipeline graphicsPipeline; - - VkCommandPool commandPool; - std::vector commandBuffers; - - std::vector imageAvailableSemaphores; - std::vector renderFinishedSemaphores; - std::vector inFlightFences; - std::vector imagesInFlight; - size_t currentFrame = 0; - - bool framebufferResized = false; - - void initWindow() { - glfwInit(); - - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); - - window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan Triangle", nullptr, nullptr); - glfwSetWindowUserPointer(window, this); - glfwSetFramebufferSizeCallback(window, framebufferResizeCallback); - } - - static void framebufferResizeCallback(GLFWwindow* window, int width, int height) { - auto app = reinterpret_cast(glfwGetWindowUserPointer(window)); - app->framebufferResized = true; - } - - void initVulkan() { - createInstance(); - setupDebugMessenger(); - createSurface(); - pickPhysicalDevice(); - createLogicalDevice(); - createSwapChain(); - createImageViews(); - createRenderPass(); - createGraphicsPipeline(); - createFramebuffers(); - createCommandPool(); - createCommandBuffers(); - createSyncObjects(); - } - - void mainLoop() { - while (!glfwWindowShouldClose(window)) { - glfwPollEvents(); - drawFrame(); - } - - vkDeviceWaitIdle(device); - } - - void cleanupSwapChain() { - for (auto framebuffer : swapChainFramebuffers) { - vkDestroyFramebuffer(device, framebuffer, nullptr); - } - - vkFreeCommandBuffers(device, commandPool, static_cast(commandBuffers.size()), commandBuffers.data()); - - vkDestroyPipeline(device, graphicsPipeline, nullptr); - vkDestroyPipelineLayout(device, pipelineLayout, nullptr); - vkDestroyRenderPass(device, renderPass, nullptr); - - for (auto imageView : swapChainImageViews) { - vkDestroyImageView(device, imageView, nullptr); - } - - vkDestroySwapchainKHR(device, swapChain, nullptr); - } - - void cleanup() { - cleanupSwapChain(); - - for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - vkDestroySemaphore(device, renderFinishedSemaphores[i], nullptr); - vkDestroySemaphore(device, imageAvailableSemaphores[i], nullptr); - vkDestroyFence(device, inFlightFences[i], nullptr); - } - - vkDestroyCommandPool(device, commandPool, nullptr); - - vkDestroyDevice(device, nullptr); - - if (enableValidationLayers) { - DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); - } - - vkDestroySurfaceKHR(instance, surface, nullptr); - vkDestroyInstance(instance, nullptr); - - glfwDestroyWindow(window); - - glfwTerminate(); - } - - void recreateSwapChain() { - int width = 0, height = 0; - glfwGetFramebufferSize(window, &width, &height); - while (width == 0 || height == 0) { - glfwGetFramebufferSize(window, &width, &height); - glfwWaitEvents(); - } - - vkDeviceWaitIdle(device); - - cleanupSwapChain(); - - createSwapChain(); - createImageViews(); - createRenderPass(); - createGraphicsPipeline(); - createFramebuffers(); - createCommandBuffers(); - - imagesInFlight.resize(swapChainImages.size(), VK_NULL_HANDLE); - } - - void createInstance() { - if (enableValidationLayers && !checkValidationLayerSupport()) { - throw std::runtime_error("validation layers requested, but not available!"); - } - - VkApplicationInfo appInfo{}; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "Hello Triangle"; - appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.pEngineName = "No Engine"; - appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.apiVersion = VK_API_VERSION_1_0; - - VkInstanceCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - createInfo.pApplicationInfo = &appInfo; - - auto extensions = getRequiredExtensions(); - createInfo.enabledExtensionCount = static_cast(extensions.size()); - createInfo.ppEnabledExtensionNames = extensions.data(); - - VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; - if (enableValidationLayers) { - createInfo.enabledLayerCount = static_cast(validationLayers.size()); - createInfo.ppEnabledLayerNames = validationLayers.data(); - - populateDebugMessengerCreateInfo(debugCreateInfo); - createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo; - } else { - createInfo.enabledLayerCount = 0; - - createInfo.pNext = nullptr; - } - - if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { - throw std::runtime_error("failed to create instance!"); - } - } - - void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) { - createInfo = {}; - createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; - 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; - 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; - createInfo.pfnUserCallback = debugCallback; - } - - void setupDebugMessenger() { - if (!enableValidationLayers) return; - - VkDebugUtilsMessengerCreateInfoEXT createInfo; - populateDebugMessengerCreateInfo(createInfo); - - if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) { - throw std::runtime_error("failed to set up debug messenger!"); - } - } - - void createSurface() { - if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) { - throw std::runtime_error("failed to create window surface!"); - } - } - - void pickPhysicalDevice() { - uint32_t deviceCount = 0; - vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); - - if (deviceCount == 0) { - throw std::runtime_error("failed to find GPUs with Vulkan support!"); - } - - std::vector devices(deviceCount); - vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); - - for (const auto& device : devices) { - if (isDeviceSuitable(device)) { - physicalDevice = device; - break; - } - } - - if (physicalDevice == VK_NULL_HANDLE) { - throw std::runtime_error("failed to find a suitable GPU!"); - } - } - - void createLogicalDevice() { - QueueFamilyIndices indices = findQueueFamilies(physicalDevice); - - std::vector queueCreateInfos; - std::set uniqueQueueFamilies = {indices.graphicsFamily.value(), indices.presentFamily.value()}; - - float queuePriority = 1.0f; - for (uint32_t queueFamily : uniqueQueueFamilies) { - VkDeviceQueueCreateInfo queueCreateInfo{}; - queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueCreateInfo.queueFamilyIndex = queueFamily; - queueCreateInfo.queueCount = 1; - queueCreateInfo.pQueuePriorities = &queuePriority; - queueCreateInfos.push_back(queueCreateInfo); - } - - VkPhysicalDeviceFeatures deviceFeatures{}; - - VkDeviceCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - - createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); - createInfo.pQueueCreateInfos = queueCreateInfos.data(); - - createInfo.pEnabledFeatures = &deviceFeatures; - - createInfo.enabledExtensionCount = static_cast(deviceExtensions.size()); - createInfo.ppEnabledExtensionNames = deviceExtensions.data(); - - if (enableValidationLayers) { - createInfo.enabledLayerCount = static_cast(validationLayers.size()); - createInfo.ppEnabledLayerNames = validationLayers.data(); - } else { - createInfo.enabledLayerCount = 0; - } - - if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) { - throw std::runtime_error("failed to create logical device!"); - } - - vkGetDeviceQueue(device, indices.graphicsFamily.value(), 0, &graphicsQueue); - vkGetDeviceQueue(device, indices.presentFamily.value(), 0, &presentQueue); - } - - void createSwapChain() { - SwapChainSupportDetails swapChainSupport = querySwapChainSupport(physicalDevice); - - VkSurfaceFormatKHR surfaceFormat = chooseSwapSurfaceFormat(swapChainSupport.formats); - VkPresentModeKHR presentMode = chooseSwapPresentMode(swapChainSupport.presentModes); - VkExtent2D extent = chooseSwapExtent(swapChainSupport.capabilities); - - uint32_t imageCount = swapChainSupport.capabilities.minImageCount + 1; - if (swapChainSupport.capabilities.maxImageCount > 0 && imageCount > swapChainSupport.capabilities.maxImageCount) { - imageCount = swapChainSupport.capabilities.maxImageCount; - } - - VkSwapchainCreateInfoKHR createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - createInfo.surface = surface; - - createInfo.minImageCount = imageCount; - createInfo.imageFormat = surfaceFormat.format; - createInfo.imageColorSpace = surfaceFormat.colorSpace; - createInfo.imageExtent = extent; - createInfo.imageArrayLayers = 1; - createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - - QueueFamilyIndices indices = findQueueFamilies(physicalDevice); - uint32_t queueFamilyIndices[] = {indices.graphicsFamily.value(), indices.presentFamily.value()}; - - if (indices.graphicsFamily != indices.presentFamily) { - createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; - createInfo.queueFamilyIndexCount = 2; - createInfo.pQueueFamilyIndices = queueFamilyIndices; - } else { - createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - } - - createInfo.preTransform = swapChainSupport.capabilities.currentTransform; - createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - createInfo.presentMode = presentMode; - createInfo.clipped = VK_TRUE; - - if (vkCreateSwapchainKHR(device, &createInfo, nullptr, &swapChain) != VK_SUCCESS) { - throw std::runtime_error("failed to create swap chain!"); - } - - vkGetSwapchainImagesKHR(device, swapChain, &imageCount, nullptr); - swapChainImages.resize(imageCount); - vkGetSwapchainImagesKHR(device, swapChain, &imageCount, swapChainImages.data()); - - swapChainImageFormat = surfaceFormat.format; - swapChainExtent = extent; - } - - void createImageViews() { - swapChainImageViews.resize(swapChainImages.size()); - - for (size_t i = 0; i < swapChainImages.size(); i++) { - VkImageViewCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - createInfo.image = swapChainImages[i]; - createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - createInfo.format = swapChainImageFormat; - createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; - createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - createInfo.subresourceRange.baseMipLevel = 0; - createInfo.subresourceRange.levelCount = 1; - createInfo.subresourceRange.baseArrayLayer = 0; - createInfo.subresourceRange.layerCount = 1; - - if (vkCreateImageView(device, &createInfo, nullptr, &swapChainImageViews[i]) != VK_SUCCESS) { - throw std::runtime_error("failed to create image views!"); - } - } - } - - void createRenderPass() { - VkAttachmentDescription colorAttachment{}; - colorAttachment.format = swapChainImageFormat; - colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentReference colorAttachmentRef{}; - colorAttachmentRef.attachment = 0; - colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass{}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorAttachmentRef; - - VkSubpassDependency dependency{}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - VkRenderPassCreateInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = 1; - renderPassInfo.pAttachments = &colorAttachment; - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 1; - renderPassInfo.pDependencies = &dependency; - - if (vkCreateRenderPass(device, &renderPassInfo, nullptr, &renderPass) != VK_SUCCESS) { - throw std::runtime_error("failed to create render pass!"); - } - } - - void createGraphicsPipeline() { - auto vertShaderCode = readFile("shaders/vert.spv"); - auto fragShaderCode = readFile("shaders/frag.spv"); - - VkShaderModule vertShaderModule = createShaderModule(vertShaderCode); - VkShaderModule fragShaderModule = createShaderModule(fragShaderCode); - - VkPipelineShaderStageCreateInfo vertShaderStageInfo{}; - vertShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - vertShaderStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; - vertShaderStageInfo.module = vertShaderModule; - vertShaderStageInfo.pName = "main"; - - VkPipelineShaderStageCreateInfo fragShaderStageInfo{}; - fragShaderStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - fragShaderStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - fragShaderStageInfo.module = fragShaderModule; - fragShaderStageInfo.pName = "main"; - - VkPipelineShaderStageCreateInfo shaderStages[] = {vertShaderStageInfo, fragShaderStageInfo}; - - VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; - vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertexInputInfo.vertexBindingDescriptionCount = 0; - vertexInputInfo.vertexAttributeDescriptionCount = 0; - - VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; - inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - inputAssembly.primitiveRestartEnable = VK_FALSE; - - VkViewport viewport{}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = (float) swapChainExtent.width; - viewport.height = (float) swapChainExtent.height; - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor{}; - scissor.offset = {0, 0}; - scissor.extent = swapChainExtent; - - VkPipelineViewportStateCreateInfo viewportState{}; - viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewportState.viewportCount = 1; - viewportState.pViewports = &viewport; - viewportState.scissorCount = 1; - viewportState.pScissors = &scissor; - - VkPipelineRasterizationStateCreateInfo rasterizer{}; - rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizer.depthClampEnable = VK_FALSE; - rasterizer.rasterizerDiscardEnable = VK_FALSE; - rasterizer.polygonMode = VK_POLYGON_MODE_FILL; - rasterizer.lineWidth = 1.0f; - rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; - rasterizer.depthBiasEnable = VK_FALSE; - - VkPipelineMultisampleStateCreateInfo multisampling{}; - multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisampling.sampleShadingEnable = VK_FALSE; - multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - - VkPipelineColorBlendAttachmentState colorBlendAttachment{}; - colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - colorBlendAttachment.blendEnable = VK_FALSE; - - VkPipelineColorBlendStateCreateInfo colorBlending{}; - colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - colorBlending.logicOpEnable = VK_FALSE; - colorBlending.logicOp = VK_LOGIC_OP_COPY; - colorBlending.attachmentCount = 1; - colorBlending.pAttachments = &colorBlendAttachment; - colorBlending.blendConstants[0] = 0.0f; - colorBlending.blendConstants[1] = 0.0f; - colorBlending.blendConstants[2] = 0.0f; - colorBlending.blendConstants[3] = 0.0f; - - VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; - pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutInfo.setLayoutCount = 0; - pipelineLayoutInfo.pushConstantRangeCount = 0; - - if (vkCreatePipelineLayout(device, &pipelineLayoutInfo, nullptr, &pipelineLayout) != VK_SUCCESS) { - throw std::runtime_error("failed to create pipeline layout!"); - } - - VkGraphicsPipelineCreateInfo pipelineInfo{}; - pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineInfo.stageCount = 2; - pipelineInfo.pStages = shaderStages; - pipelineInfo.pVertexInputState = &vertexInputInfo; - pipelineInfo.pInputAssemblyState = &inputAssembly; - pipelineInfo.pViewportState = &viewportState; - pipelineInfo.pRasterizationState = &rasterizer; - pipelineInfo.pMultisampleState = &multisampling; - pipelineInfo.pColorBlendState = &colorBlending; - pipelineInfo.layout = pipelineLayout; - pipelineInfo.renderPass = renderPass; - pipelineInfo.subpass = 0; - pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; - - if (vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &graphicsPipeline) != VK_SUCCESS) { - throw std::runtime_error("failed to create graphics pipeline!"); - } - - vkDestroyShaderModule(device, fragShaderModule, nullptr); - vkDestroyShaderModule(device, vertShaderModule, nullptr); - } - - void createFramebuffers() { - swapChainFramebuffers.resize(swapChainImageViews.size()); - - for (size_t i = 0; i < swapChainImageViews.size(); i++) { - VkImageView attachments[] = { - swapChainImageViews[i] - }; - - VkFramebufferCreateInfo framebufferInfo{}; - framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebufferInfo.renderPass = renderPass; - framebufferInfo.attachmentCount = 1; - framebufferInfo.pAttachments = attachments; - framebufferInfo.width = swapChainExtent.width; - framebufferInfo.height = swapChainExtent.height; - framebufferInfo.layers = 1; - - if (vkCreateFramebuffer(device, &framebufferInfo, nullptr, &swapChainFramebuffers[i]) != VK_SUCCESS) { - throw std::runtime_error("failed to create framebuffer!"); - } - } - } - - void createCommandPool() { - QueueFamilyIndices queueFamilyIndices = findQueueFamilies(physicalDevice); - - VkCommandPoolCreateInfo poolInfo{}; - poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - poolInfo.queueFamilyIndex = queueFamilyIndices.graphicsFamily.value(); - - if (vkCreateCommandPool(device, &poolInfo, nullptr, &commandPool) != VK_SUCCESS) { - throw std::runtime_error("failed to create graphics command pool!"); - } - } - - void createCommandBuffers() { - commandBuffers.resize(swapChainFramebuffers.size()); - - VkCommandBufferAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.commandPool = commandPool; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandBufferCount = (uint32_t) commandBuffers.size(); - - if (vkAllocateCommandBuffers(device, &allocInfo, commandBuffers.data()) != VK_SUCCESS) { - throw std::runtime_error("failed to allocate command buffers!"); - } - - for (size_t i = 0; i < commandBuffers.size(); i++) { - VkCommandBufferBeginInfo beginInfo{}; - beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - - if (vkBeginCommandBuffer(commandBuffers[i], &beginInfo) != VK_SUCCESS) { - throw std::runtime_error("failed to begin recording command buffer!"); - } - - VkRenderPassBeginInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassInfo.renderPass = renderPass; - renderPassInfo.framebuffer = swapChainFramebuffers[i]; - renderPassInfo.renderArea.offset = {0, 0}; - renderPassInfo.renderArea.extent = swapChainExtent; - - VkClearValue clearColor = {{{0.0f, 0.0f, 0.0f, 1.0f}}}; - renderPassInfo.clearValueCount = 1; - renderPassInfo.pClearValues = &clearColor; - - vkCmdBeginRenderPass(commandBuffers[i], &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); - - vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, graphicsPipeline); - - vkCmdDraw(commandBuffers[i], 3, 1, 0, 0); - - vkCmdEndRenderPass(commandBuffers[i]); - - - if (vkEndCommandBuffer(commandBuffers[i]) != VK_SUCCESS) { - throw std::runtime_error("failed to record command buffer!"); - } - } - } - - void createSyncObjects() { - imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT); - renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT); - inFlightFences.resize(MAX_FRAMES_IN_FLIGHT); - imagesInFlight.resize(swapChainImages.size(), VK_NULL_HANDLE); - - - VkSemaphoreCreateInfo semaphoreInfo{}; - semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - - VkFenceCreateInfo fenceInfo{}; - fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) { - if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]) != VK_SUCCESS || - vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS || - vkCreateFence(device, &fenceInfo, nullptr, &inFlightFences[i]) != VK_SUCCESS) { - throw std::runtime_error("failed to create synchronization objects for a frame!"); - } - } - } - - void drawFrame() { - vkWaitForFences(device, 1, &inFlightFences[currentFrame], VK_TRUE, UINT64_MAX); - - uint32_t imageIndex; - VkResult result = vkAcquireNextImageKHR(device, swapChain, UINT64_MAX, imageAvailableSemaphores[currentFrame], VK_NULL_HANDLE, &imageIndex); - - if (result == VK_ERROR_OUT_OF_DATE_KHR) { - recreateSwapChain(); - return; - } else if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR) { - throw std::runtime_error("failed to acquire swap chain image!"); - } - - // Check if a previous frame is using this image (i.e. there is its fence to wait on) - if (imagesInFlight[imageIndex] != VK_NULL_HANDLE) { - vkWaitForFences(device, 1, &imagesInFlight[imageIndex], VK_TRUE, UINT64_MAX); - } - // Mark the image as now being in use by this frame - imagesInFlight[imageIndex] = inFlightFences[currentFrame]; - - VkSubmitInfo submitInfo{}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - - VkSemaphore waitSemaphores[] = {imageAvailableSemaphores[currentFrame]}; - VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; - submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = waitSemaphores; - submitInfo.pWaitDstStageMask = waitStages; - - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &commandBuffers[imageIndex]; - - VkSemaphore signalSemaphores[] = {renderFinishedSemaphores[currentFrame]}; - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = signalSemaphores; - - vkResetFences(device, 1, &inFlightFences[currentFrame]); - - if (vkQueueSubmit(graphicsQueue, 1, &submitInfo, inFlightFences[currentFrame]) != VK_SUCCESS) { - throw std::runtime_error("failed to submit draw command buffer!"); - } - - VkPresentInfoKHR presentInfo{}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - - presentInfo.waitSemaphoreCount = 1; - presentInfo.pWaitSemaphores = signalSemaphores; - - VkSwapchainKHR swapChains[] = {swapChain}; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = swapChains; - - presentInfo.pImageIndices = &imageIndex; - - result = vkQueuePresentKHR(presentQueue, &presentInfo); - - if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized) { - framebufferResized = false; - recreateSwapChain(); - } else if (result != VK_SUCCESS) { - throw std::runtime_error("failed to present swap chain image!"); - } - - currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT; - } - - VkShaderModule createShaderModule(const std::vector& code) { - VkShaderModuleCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.codeSize = code.size(); - createInfo.pCode = reinterpret_cast(code.data()); - - VkShaderModule shaderModule; - if (vkCreateShaderModule(device, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) { - throw std::runtime_error("failed to create shader module!"); - } - - return shaderModule; - } - - VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector& availableFormats) { - for (const auto& availableFormat : availableFormats) { - if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - return availableFormat; - } - } - - return availableFormats[0]; - } - - VkPresentModeKHR chooseSwapPresentMode(const std::vector& availablePresentModes) { - for (const auto& availablePresentMode : availablePresentModes) { - if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) { - return availablePresentMode; - } - } - - return VK_PRESENT_MODE_FIFO_KHR; - } - - VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities) { - if (capabilities.currentExtent.width != UINT32_MAX) { - return capabilities.currentExtent; - } else { - int width, height; - glfwGetFramebufferSize(window, &width, &height); - - VkExtent2D actualExtent = { - static_cast(width), - static_cast(height) - }; - - actualExtent.width = std::clamp(actualExtent.width, capabilities.minImageExtent.width, capabilities.maxImageExtent.width); - actualExtent.height = std::clamp(actualExtent.height, capabilities.minImageExtent.height, capabilities.maxImageExtent.height); - - return actualExtent; - } - } - - SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device) { - SwapChainSupportDetails details; - - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &details.capabilities); - - uint32_t formatCount; - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, nullptr); - - if (formatCount != 0) { - details.formats.resize(formatCount); - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &formatCount, details.formats.data()); - } - - uint32_t presentModeCount; - vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, nullptr); - - if (presentModeCount != 0) { - details.presentModes.resize(presentModeCount); - vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &presentModeCount, details.presentModes.data()); - } - - return details; - } - - bool isDeviceSuitable(VkPhysicalDevice device) { - QueueFamilyIndices indices = findQueueFamilies(device); - - bool extensionsSupported = checkDeviceExtensionSupport(device); - - bool swapChainAdequate = false; - if (extensionsSupported) { - SwapChainSupportDetails swapChainSupport = querySwapChainSupport(device); - swapChainAdequate = !swapChainSupport.formats.empty() && !swapChainSupport.presentModes.empty(); - } - - return indices.isComplete() && extensionsSupported && swapChainAdequate; - } - - bool checkDeviceExtensionSupport(VkPhysicalDevice device) { - uint32_t extensionCount; - vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); - - std::vector availableExtensions(extensionCount); - vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data()); - - std::set requiredExtensions(deviceExtensions.begin(), deviceExtensions.end()); - - for (const auto& extension : availableExtensions) { - requiredExtensions.erase(extension.extensionName); - } - - return requiredExtensions.empty(); - } - - QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device) { - QueueFamilyIndices indices; - - uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); - - std::vector queueFamilies(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data()); - - int i = 0; - for (const auto& queueFamily : queueFamilies) { - if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - indices.graphicsFamily = i; - } - - VkBool32 presentSupport = false; - vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport); - - if (presentSupport) { - indices.presentFamily = i; - } - - if (indices.isComplete()) { - break; - } - - i++; - } - - return indices; - } - - std::vector getRequiredExtensions() { - uint32_t glfwExtensionCount = 0; - const char** glfwExtensions; - glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); - - std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); - - if (enableValidationLayers) { - extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); - } - - return extensions; - } - - bool checkValidationLayerSupport() { - uint32_t layerCount; - vkEnumerateInstanceLayerProperties(&layerCount, nullptr); - - std::vector availableLayers(layerCount); - vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); - - for (const char* layerName : validationLayers) { - bool layerFound = false; - - for (const auto& layerProperties : availableLayers) { - if (strcmp(layerName, layerProperties.layerName) == 0) { - layerFound = true; - break; - } - } - - if (!layerFound) { - return false; - } - } - - return true; - } - - static std::vector readFile(const std::string& filename) { - std::ifstream file(filename, std::ios::ate | std::ios::binary); - - if (!file.is_open()) { - throw std::runtime_error("failed to open file!"); - } - - size_t fileSize = (size_t) file.tellg(); - std::vector buffer(fileSize); - - file.seekg(0); - file.read(buffer.data(), fileSize); - - file.close(); - - return buffer; - } - - static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) { - std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl; - - return VK_FALSE; - } -}; - +#include "HelloTriangleApplication.h" int main() { HelloTriangleApplication app;