KhronosGroup / Vulkan-Docs

The Vulkan API Specification and related tools
Other
2.7k stars 452 forks source link

VulkanSDK 1.3.280.0 semaphore validation error #2337

Closed CiRazDeveloper closed 3 months ago

CiRazDeveloper commented 3 months ago

Additional Libraries:

Compiler, OS:

Windows

Details:

My Issue/Question:

Hello, I get an error related to the semaphore but I can not seem to find a fix for it.

Error:

VUID-vkAcquireNextImageKHR-semaphore-01779(ERROR / SPEC): msgNum: 1461184347 - Validation Error: [ VUID-vkAcquireNextImageKHR-semaphore-01779 ] | MessageID = 0x5717e75b | vkAcquireNextImageKHR(): Semaphore must not have any pending operations. The Vulkan spec states: If semaphore is not VK_NULL_HANDLE it must not have any uncompleted signal or wait operations pending (https://vulkan.lunarg.com/doc/view/1.3.280.0/windows/1.3-extensions/vkspec.html#VUID-vkAcquireNextImageKHR-semaphore-01779) Objects: 0

Small Code View

VkDevice device;
VkSwapchainKHR swapchain;
VkSemaphore semaphoreImageAvailable;

uint32_t imageIndex;

vkAcquireNextImageKHR(device, swapchain, (std::numeric_limits<uint64_t>::max)(), semaphoreImageAvailable, VK_NULL_HANDLE, &imageIndex);

Steps to recreate the issue start here

This is a Visual Studio 2022 C++ empty Project called "Vulkan" Cpp Language Standard: ISO C++17 Standard (/std:c++17)

Pictures to understand the settings:

Here we are in the Configuration Properties -> C/C++ -> General (Settings for the "Additional Include Directories):

32bit Configuration

VulkanCppAdditionalIncludeDirectories32

64bit Configuration

VulkanCppAdditionalIncludeDirectories64

Here we are in the Configuration Properties -> Linker -> General (Settings for the "Additional Library Directories):

32bit Configuration

VulkanLinkerAdditionalLibraryDirectories32

64bit Configuration VulkanLinkerAdditionalLibraryDirectories64

Here we are in the Configuration Properties -> Linker -> Input (Settings for the "Additional Dependenciess):

All Platforms Configurations (so 32 and 64 bit Configuration settings together)

VulkanLinkerAdditionalDependencies32and64

NOTE: In the Configuration of the Vulkan Project I added a Pre-Build Event (in Command Line) to run the runCompiler.bat file, so i do not have to manually run it every time I want to change the color of the Triangle.

(Vulkan Properties (All Platforms selected) --> Build Events --> Pre-Build Event)

VulkanPreBuildEvent

Project Structure:

VulkanProjectStructure

Note:

VulkanVSProjectStructure

Complete and Verifiable Example code:

shader.frag file code

version 460

extension GL_ARB_separate_shader_objects : enable

extension GL_EXT_debug_printf : enable

layout(location = 0) out vec4 outColor;

void main() { outColor = vec4(0.0, 1.0, 0.0, 1.0); }

shader.vert file code

version 460

extension GL_ARB_separate_shader_objects : enable

extension GL_EXT_debug_printf : enable

out gl_PerVertex { vec4 gl_Position; };

vec2 positions[3] = vec2[]( vec2(0.0, -0.5), vec2(0.5, 0.5), vec2(-0.5, 0.5) );

void main() { gl_Position = vec4(positions[gl_VertexIndex], 0.0, 1.0); }

runCompiler.bat file code

E:\VulkanSDK\1.3.280.0\Bin\glslangValidator.exe -V shader.vert E:\VulkanSDK\1.3.280.0\Bin\glslangValidator.exe -V shader.frag pause

(The runCompiler.bat code spits out 2 files that vulkan generated called "frag.spv" and "vert.spv" like you can see above in the picture of the Windows Explorer) (Note that the VulkanSDK is not located on the C-Drive, where Windows is installed)

vulkHeader.h code

#pragma once

#define VK_USE_PLATFORM_WIN32_KHR
#define GLFW_INCLUDE_VULKAN

main.cpp code


#include "vulkHeaders.h" //includes all necessary headers for the project, related to vulkan (look a bit above this code)

#include <GLFW/glfw3.h>
#include "vulkErrors.h" //is basically a switch-case with all errors that vulkan has (is at the very bottom of this page)
#include <iostream>
#include <vector>
#include <fstream>

//global variables
VkInstance instance;
VkSurfaceKHR surface;
VkDevice device;
VkSwapchainKHR swapchain;
VkImageView *imageViews;
VkFramebuffer* frameBuffers;
VkShaderModule shaderModuleVert;
VkShaderModule shaderModuleFrag;
VkPipelineLayout pipelineLayout;
VkRenderPass renderPass;
VkPipeline pipeline;
VkCommandPool commandPool;
VkCommandBuffer *commandBuffers;
VkSemaphore semaphoreImageAvailable;
VkSemaphore semaphoreRenderingDone;
VkQueue queue;
GLFWwindow* window;

const uint32_t wWidth = 400;
const uint32_t wHeight = 300;
const VkFormat format_R8G8B8A8_SRGB = VK_FORMAT_R8G8B8A8_SRGB; //TODO civ

uint32_t amountOfImagesInSwapchain = 0;

void printStats(VkPhysicalDevice& device) {
    VkPhysicalDeviceProperties physicalDeviceProperties;
    vkGetPhysicalDeviceProperties(device, &physicalDeviceProperties);
    uint32_t apiVer = physicalDeviceProperties.apiVersion;

    std::cout << ">>> Device Properties <<<" << std::endl;
    std::cout << "API Version:          " << VK_VERSION_MAJOR(apiVer) << "." << VK_VERSION_MINOR(apiVer) << "." << VK_VERSION_PATCH(apiVer) << std::endl;
    std::cout << "Device ID:            " << physicalDeviceProperties.deviceID << std::endl;
    std::cout << "Device Name:          " << physicalDeviceProperties.deviceName << std::endl;
    std::cout << "Device Type:          " << physicalDeviceProperties.deviceType << std::endl;
    std::cout << "Discrete Queue Props: " << physicalDeviceProperties.limits.discreteQueuePriorities << std::endl;
    std::cout << "Driver Version:       " << physicalDeviceProperties.driverVersion << std::endl;
    std::cout << "Vendor ID:            " << physicalDeviceProperties.vendorID << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;

    VkPhysicalDeviceFeatures physicalDeviceFeatures;
    vkGetPhysicalDeviceFeatures(device, &physicalDeviceFeatures);

    std::cout << ">>> Device Feautures <<<" << std::endl;
    std::cout << "Geometry Shader: " << physicalDeviceFeatures.geometryShader << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;

    VkPhysicalDeviceMemoryProperties physicalDeviceMemoryProperties;
    vkGetPhysicalDeviceMemoryProperties(device, &physicalDeviceMemoryProperties);

    std::cout << ">>> Device Memory Properties <<<" << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;

    uint32_t amountOfQueueFamilies = 0;
    vkGetPhysicalDeviceQueueFamilyProperties(device, &amountOfQueueFamilies, nullptr);
    VkQueueFamilyProperties* queuefamilyProperties = new VkQueueFamilyProperties[amountOfQueueFamilies];

    vkGetPhysicalDeviceQueueFamilyProperties(device, &amountOfQueueFamilies, queuefamilyProperties);

    std::cout << ">>> Queue Family Properties <<<" << std::endl;
    std::cout << "Amount of Queue Families: " << amountOfQueueFamilies << std::endl;
    std::cout << std::endl;

    for (int i = 0; i < amountOfQueueFamilies; i++)
    {
        std::cout << "Queue Family #" << i << std::endl;
        std::cout << "VK_QUEUE_GRAPHICS_BIT:            " << ((queuefamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0) << std::endl;
        std::cout << "VK_QUEUE_COMPUTE_BIT:             " << ((queuefamilyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) != 0) << std::endl;
        std::cout << "VK_QUEUE_TRANSFER_BIT_            " << ((queuefamilyProperties[i].queueFlags & VK_QUEUE_TRANSFER_BIT) != 0) << std::endl;
        std::cout << "VK_QUEUE_SPARSE_BINDING_BIT:      " << ((queuefamilyProperties[i].queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) != 0) << std::endl;
        std::cout << "Queue Count:                      " << queuefamilyProperties[i].queueCount << std::endl;
        std::cout << "Timestamp Valid Bits:             " << queuefamilyProperties[i].timestampValidBits << std::endl;
        uint32_t width = queuefamilyProperties[i].minImageTransferGranularity.width;
        uint32_t height = queuefamilyProperties[i].minImageTransferGranularity.height;
        uint32_t depth = queuefamilyProperties[i].minImageTransferGranularity.depth;
        std::cout << "Min Image Timestamp Granularity:  " << width << "," << height << "," << depth << std::endl;
        std::cout << std::endl;
    }
    std::cout << std::endl;

    VkSurfaceCapabilitiesKHR surfaceCapabilities;
    vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface, &surfaceCapabilities);

    std::cout << ">>> Surface Capabilities <<<" << std::endl;
    std::cout << "Min Image Count:                 " << surfaceCapabilities.minImageCount << std::endl;
    std::cout << "Max Image Count:                 " << surfaceCapabilities.maxImageCount << std::endl;
    std::cout << "Current Extent (Width/Height):   " << surfaceCapabilities.currentExtent.width << "/" << surfaceCapabilities.currentExtent.height << std::endl;
    std::cout << "Min Image Extent (Width/Height): " << surfaceCapabilities.minImageExtent.width << "/" << surfaceCapabilities.minImageExtent.height << std::endl;
    std::cout << "Max Image Extent (Width/Height): " << surfaceCapabilities.maxImageExtent.width << "/" << surfaceCapabilities.maxImageExtent.height << std::endl;
    std::cout << "Max Image Array Layers:          " << surfaceCapabilities.maxImageArrayLayers << std::endl;
    std::cout << "Supported Transforms:            " << surfaceCapabilities.supportedTransforms << std::endl;
    std::cout << "Current Transform:               " << surfaceCapabilities.currentTransform << std::endl;
    std::cout << "Supported Composite Alpha:       " << surfaceCapabilities.supportedCompositeAlpha << std::endl;
    std::cout << "Supported Usage Flags:           " << surfaceCapabilities.supportedUsageFlags << std::endl;
    std::cout << std::endl;
    std::cout << std::endl;

    uint32_t amountOfFormats = 0;
    vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &amountOfFormats, nullptr);
    VkSurfaceFormatKHR* surfaceFormats = new VkSurfaceFormatKHR[amountOfFormats];
    vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface, &amountOfFormats, surfaceFormats);

    std::cout << ">>> Surface Formats <<<" << std::endl;
    std::cout << "Amount of Formats: " << amountOfFormats << std::endl;
    std::cout << std::endl;

    for (int i = 0; i < amountOfFormats; i++)
    {
        std::cout << "Format: " << surfaceFormats[i].format << std::endl;
    }
    std::cout << std::endl;
    std::cout << std::endl;

    uint32_t amountOfPresentationModes = 0;
    vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &amountOfPresentationModes, nullptr);
    VkPresentModeKHR* presentModes = new VkPresentModeKHR[amountOfPresentationModes];
    vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface, &amountOfPresentationModes, presentModes);

    std::cout << ">>> Surface Presentation Modes <<<" << std::endl;
    std::cout << "Amount of Presentation Modes: " << amountOfPresentationModes << std::endl;
    std::cout << std::endl;

    for (int i = 0; i < amountOfPresentationModes; i++)
    {
        std::cout << "Presentation Mode: " << presentModes[i] << std::endl;
    }
    std::cout << std::endl;
    std::cout << std::endl;

    delete[] queuefamilyProperties;
    delete[] surfaceFormats;
    delete[] presentModes;
}

std::vector<char> readFile(const std::string &filename) {
    std::ifstream file(filename, std::ios::binary | std::ios::ate);

    if (file) {
        size_t fileSize = (size_t)file.tellg();
        std::vector<char> fileBuffer(fileSize);
        file.seekg(0);
        file.read(fileBuffer.data(), fileSize);
        file.close();
        return fileBuffer;
    }
    else {
        throw std::runtime_error("Vulkan error: Failed to open the file!");
    }
}

void startGlfw() {
    glfwInit();
    glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
    glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);

    window = glfwCreateWindow(wWidth, wHeight, "CiRazEngine", nullptr, nullptr);
}

void createShaderModule(const std::vector<char>& code, VkShaderModule *shaderModule) {
    VkShaderModuleCreateInfo shaderModuleCreateInfo;
    shaderModuleCreateInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
    shaderModuleCreateInfo.pNext = nullptr;
    shaderModuleCreateInfo.flags = 0;
    shaderModuleCreateInfo.codeSize = code.size();
    shaderModuleCreateInfo.pCode = (uint32_t*)code.data();

    VkResult result = vkCreateShaderModule(device, &shaderModuleCreateInfo, nullptr, shaderModule);
    ASSERT_VULKAN(result);
}

void startVulkan() {
    VkApplicationInfo applicationInfo;
    applicationInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
    applicationInfo.pNext = nullptr;
    applicationInfo.pApplicationName = "First CiRazEngine App";
    // e.g.: 0.0.0:
    // First number stands for variant: Not shown in the actual version
    // Second number stands for major: Big update jumps (from Beta 0, to Release 1)
    // Third number stands for minor: For new feautures
    // Fourth number stands for patch: Hot fixes, and so on
    applicationInfo.applicationVersion = VK_MAKE_API_VERSION(0, 0, 0, 0);
    applicationInfo.pEngineName = "CiRazEngine";
    applicationInfo.engineVersion = VK_MAKE_API_VERSION(0, 0, 0, 0);
    applicationInfo.apiVersion = VK_API_VERSION_1_0;

    uint32_t amountOfLayers = 0;
    vkEnumerateInstanceLayerProperties(&amountOfLayers, nullptr);
    VkLayerProperties* layerProperties = new VkLayerProperties[amountOfLayers];
    vkEnumerateInstanceLayerProperties(&amountOfLayers, layerProperties);

    std::cout << ">>> Layer Properties <<<" << amountOfLayers << std::endl;
    std::cout << "Amount of Instance Layers: " << amountOfLayers << std::endl;
    std::cout << std::endl;

    for (int i = 0; i < amountOfLayers; i++) {
        std::cout << "Layer #" << i << std::endl;
        std::cout << "Description:            " << layerProperties[i].description << std::endl;
        std::cout << "Implementation Version: " << layerProperties[i].implementationVersion << std::endl;
        std::cout << "Name:                   " << layerProperties[i].layerName << std::endl;
        std::cout << "Specified Version:      " << layerProperties[i].specVersion << std::endl;
        std::cout << std::endl;
    }
    std::cout << std::endl;

    uint32_t amountOfExtensions = 0;
    vkEnumerateInstanceExtensionProperties(nullptr, &amountOfExtensions, nullptr);
    VkExtensionProperties* extensionProperties = new VkExtensionProperties[amountOfExtensions];
    vkEnumerateInstanceExtensionProperties(nullptr, &amountOfExtensions, extensionProperties);

    std::cout << ">>> Extension Properties <<<" << amountOfExtensions << std::endl;
    std::cout << "Amount of Extensions: " << amountOfExtensions << std::endl;
    std::cout << std::endl;

    for (int i = 0; i < amountOfExtensions; i++) {
        std::cout << "Extension #" << i << std::endl;
        std::cout << "Name:              " << extensionProperties[i].extensionName << std::endl;
        std::cout << "Specified Version: " << extensionProperties[i].specVersion << std::endl;
        std::cout << std::endl;
    }
    std::cout << std::endl;

    const std::vector<const char*> validationLayers = {
        "VK_LAYER_KHRONOS_validation"
    };

    uint32_t amountOfGlfwExtensions = 0;
    auto glfwExtensions = glfwGetRequiredInstanceExtensions(&amountOfGlfwExtensions);

    VkInstanceCreateInfo instanceCreateInfo;
    instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
    instanceCreateInfo.pNext = nullptr;
    instanceCreateInfo.flags = 0;
    instanceCreateInfo.pApplicationInfo = &applicationInfo;
    instanceCreateInfo.enabledLayerCount = validationLayers.size();
    instanceCreateInfo.ppEnabledLayerNames = validationLayers.data();
    instanceCreateInfo.enabledExtensionCount = amountOfGlfwExtensions;
    instanceCreateInfo.ppEnabledExtensionNames = glfwExtensions;

    VkResult result = vkCreateInstance(&instanceCreateInfo, nullptr, &instance);
    ASSERT_VULKAN(result);

    result = glfwCreateWindowSurface(instance, window, nullptr, &surface);
    ASSERT_VULKAN(result);

    uint32_t amountOfPhysicalDevices = 0;
    result = vkEnumeratePhysicalDevices(instance, &amountOfPhysicalDevices, nullptr);
    ASSERT_VULKAN(result);

    VkPhysicalDevice* physicalDevices = new VkPhysicalDevice[amountOfPhysicalDevices];

    result = vkEnumeratePhysicalDevices(instance, &amountOfPhysicalDevices, physicalDevices);
    ASSERT_VULKAN(result);

    for (int i = 0; i < amountOfPhysicalDevices; i++) {
        printStats(physicalDevices[i]);
    }

    float queuePriorities[] = { 1.0f, 1.0f,  1.0f,  1.0f };

    VkDeviceQueueCreateInfo deviceQueueCreateInfo;
    deviceQueueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
    deviceQueueCreateInfo.pNext = nullptr;
    deviceQueueCreateInfo.flags = 0;
    deviceQueueCreateInfo.queueFamilyIndex = 0; //TODO: Choose correct family index
    deviceQueueCreateInfo.queueCount = 1; //TODO: Chek if this amount is valid
    deviceQueueCreateInfo.pQueuePriorities = queuePriorities;

    VkPhysicalDeviceFeatures physicalDeviceFeatures = {};

    const std::vector<const char*> deviceExtensions = {
        VK_KHR_SWAPCHAIN_EXTENSION_NAME
    };

    VkDeviceCreateInfo deviceCrateInfo;
    deviceCrateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
    deviceCrateInfo.pNext = nullptr;
    deviceCrateInfo.flags = 0;
    deviceCrateInfo.queueCreateInfoCount = 1;
    deviceCrateInfo.pQueueCreateInfos = &deviceQueueCreateInfo;
    deviceCrateInfo.enabledLayerCount = 0;
    deviceCrateInfo.ppEnabledLayerNames = nullptr;
    deviceCrateInfo.enabledExtensionCount = deviceExtensions.size();
    deviceCrateInfo.ppEnabledExtensionNames = deviceExtensions.data();
    deviceCrateInfo.pEnabledFeatures = &physicalDeviceFeatures;

    //TODO: pick "best device" instead of first device
    result = vkCreateDevice(physicalDevices[0], &deviceCrateInfo, nullptr, &device);
    ASSERT_VULKAN(result);

    vkGetDeviceQueue(device, 0, 0, &queue);

    VkBool32 surfaceSupport = false;

    result = vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevices[0], 0, surface, &surfaceSupport);
    ASSERT_VULKAN(result);

    if (!surfaceSupport) {
        std::cerr << "Surface not supported!" << std::endl;
        __debugbreak();
    }

    VkSwapchainCreateInfoKHR swapchainCreateInfo;
    swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
    swapchainCreateInfo.pNext = nullptr;
    swapchainCreateInfo.flags = 0;
    swapchainCreateInfo.surface = surface;
    swapchainCreateInfo.minImageCount = 3; //TODO check if valid
    swapchainCreateInfo.imageFormat = format_R8G8B8A8_SRGB; // TODO civ
    swapchainCreateInfo.imageColorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; //TODO civ
    swapchainCreateInfo.imageExtent = VkExtent2D{ wWidth, wHeight };
    swapchainCreateInfo.imageArrayLayers = 1;
    swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
    swapchainCreateInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; //TODO civ
    swapchainCreateInfo.queueFamilyIndexCount = 0;
    swapchainCreateInfo.pQueueFamilyIndices = nullptr;
    swapchainCreateInfo.preTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
    swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
    swapchainCreateInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR; //TODO civ
    swapchainCreateInfo.clipped = VK_TRUE;
    swapchainCreateInfo.oldSwapchain = VK_NULL_HANDLE;

    result = vkCreateSwapchainKHR(device, &swapchainCreateInfo, nullptr, &swapchain);
    ASSERT_VULKAN(result);

    vkGetSwapchainImagesKHR(device, swapchain, &amountOfImagesInSwapchain, nullptr);
    VkImage* swapchainImages = new VkImage[amountOfImagesInSwapchain];
    result = vkGetSwapchainImagesKHR(device, swapchain, &amountOfImagesInSwapchain, swapchainImages);
    ASSERT_VULKAN(result);

    imageViews = new VkImageView[amountOfImagesInSwapchain];
    for (int i = 0; i < amountOfImagesInSwapchain; i++) {
        VkImageViewCreateInfo imageViewCreateInfo;
        imageViewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
        imageViewCreateInfo.pNext = nullptr;
        imageViewCreateInfo.flags = 0;
        imageViewCreateInfo.image = swapchainImages[i];
        imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
        imageViewCreateInfo.format = format_R8G8B8A8_SRGB; //TODO civ
        imageViewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
        imageViewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
        imageViewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
        imageViewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
        imageViewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        imageViewCreateInfo.subresourceRange.baseMipLevel = 0;
        imageViewCreateInfo.subresourceRange.levelCount = 1;
        imageViewCreateInfo.subresourceRange.baseArrayLayer = 0;
        imageViewCreateInfo.subresourceRange.layerCount = 1;

        result = vkCreateImageView(device, &imageViewCreateInfo, nullptr, &imageViews[i]);
        ASSERT_VULKAN(result);
    }

    auto shaderCodeVert = readFile("vert.spv");
    auto shaderCodeFrag = readFile("frag.spv");

    createShaderModule(shaderCodeVert, &shaderModuleVert);
    createShaderModule(shaderCodeFrag, &shaderModuleFrag);

    VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfoVert;
    pipelineShaderStageCreateInfoVert.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
    pipelineShaderStageCreateInfoVert.pNext = nullptr;
    pipelineShaderStageCreateInfoVert.flags = 0;
    pipelineShaderStageCreateInfoVert.stage = VK_SHADER_STAGE_VERTEX_BIT;
    pipelineShaderStageCreateInfoVert.module = shaderModuleVert;
    pipelineShaderStageCreateInfoVert.pName = "main";
    pipelineShaderStageCreateInfoVert.pSpecializationInfo = nullptr;

    VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfoFrag;
    pipelineShaderStageCreateInfoFrag.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
    pipelineShaderStageCreateInfoFrag.pNext = nullptr;
    pipelineShaderStageCreateInfoFrag.flags = 0;
    pipelineShaderStageCreateInfoFrag.stage = VK_SHADER_STAGE_FRAGMENT_BIT;
    pipelineShaderStageCreateInfoFrag.module = shaderModuleFrag;
    pipelineShaderStageCreateInfoFrag.pName = "main";
    pipelineShaderStageCreateInfoFrag.pSpecializationInfo = nullptr;

    VkPipelineShaderStageCreateInfo pipelineShaderStagesCreateInfo[] = { pipelineShaderStageCreateInfoVert, pipelineShaderStageCreateInfoFrag };

    VkPipelineVertexInputStateCreateInfo pipelineVertexInputCreateInfo;
    pipelineVertexInputCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
    pipelineVertexInputCreateInfo.pNext = nullptr;
    pipelineVertexInputCreateInfo.flags = 0;
    pipelineVertexInputCreateInfo.vertexBindingDescriptionCount = 0;
    pipelineVertexInputCreateInfo.pVertexBindingDescriptions = nullptr;
    pipelineVertexInputCreateInfo.vertexAttributeDescriptionCount = 0;
    pipelineVertexInputCreateInfo.pVertexAttributeDescriptions = nullptr;

    VkPipelineInputAssemblyStateCreateInfo pipelineInputAssembyCreateInfo;
    pipelineInputAssembyCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
    pipelineInputAssembyCreateInfo.pNext = nullptr;
    pipelineInputAssembyCreateInfo.flags = 0;
    pipelineInputAssembyCreateInfo.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
    pipelineInputAssembyCreateInfo.primitiveRestartEnable = VK_FALSE;

    VkViewport viewport;
    viewport.x = 0.0f;
    viewport.y = 0.0f;
    viewport.width = wWidth;
    viewport.height = wHeight;
    viewport.minDepth = 0.0f;
    viewport.maxDepth = 1.0f;

    VkRect2D scissor;
    scissor.offset = { 0,0 };
    scissor.extent = { wWidth, wHeight };

    VkPipelineViewportStateCreateInfo pipelineViewportStateCreateInfo;
    pipelineViewportStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
    pipelineViewportStateCreateInfo.pNext = nullptr;
    pipelineViewportStateCreateInfo.flags = 0;
    pipelineViewportStateCreateInfo.viewportCount = 1;
    pipelineViewportStateCreateInfo.pViewports = &viewport;
    pipelineViewportStateCreateInfo.scissorCount = 1;
    pipelineViewportStateCreateInfo.pScissors = &scissor;

    VkPipelineRasterizationStateCreateInfo pipelineRasterizationStateCreateInfo;
    pipelineRasterizationStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
    pipelineRasterizationStateCreateInfo.pNext = nullptr;
    pipelineRasterizationStateCreateInfo.flags = 0;
    pipelineRasterizationStateCreateInfo.depthClampEnable = VK_FALSE;
    pipelineRasterizationStateCreateInfo.rasterizerDiscardEnable = VK_FALSE;
    pipelineRasterizationStateCreateInfo.polygonMode = VK_POLYGON_MODE_FILL;
    pipelineRasterizationStateCreateInfo.cullMode = VK_CULL_MODE_BACK_BIT;
    pipelineRasterizationStateCreateInfo.frontFace = VK_FRONT_FACE_CLOCKWISE;
    pipelineRasterizationStateCreateInfo.depthBiasEnable = VK_FALSE;
    pipelineRasterizationStateCreateInfo.depthBiasConstantFactor = 0.0f;
    pipelineRasterizationStateCreateInfo.depthBiasClamp = 0.0f;
    pipelineRasterizationStateCreateInfo.depthBiasSlopeFactor = 0.0f;
    pipelineRasterizationStateCreateInfo.lineWidth = 1.0f;

    VkPipelineMultisampleStateCreateInfo pipelineMultiSampleStateCreateInfo;
    pipelineMultiSampleStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
    pipelineMultiSampleStateCreateInfo.pNext = nullptr;
    pipelineMultiSampleStateCreateInfo.flags = 0;
    pipelineMultiSampleStateCreateInfo.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
    pipelineMultiSampleStateCreateInfo.sampleShadingEnable = VK_FALSE;
    pipelineMultiSampleStateCreateInfo.minSampleShading = 1.0f;
    pipelineMultiSampleStateCreateInfo.pSampleMask = nullptr;
    pipelineMultiSampleStateCreateInfo.alphaToCoverageEnable = VK_FALSE;
    pipelineMultiSampleStateCreateInfo.alphaToOneEnable = VK_FALSE;

    VkPipelineColorBlendAttachmentState pipelineColorBlendAttachmentState;
    pipelineColorBlendAttachmentState.blendEnable = VK_TRUE;
    pipelineColorBlendAttachmentState.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
    pipelineColorBlendAttachmentState.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
    pipelineColorBlendAttachmentState.colorBlendOp = VK_BLEND_OP_ADD;
    pipelineColorBlendAttachmentState.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
    pipelineColorBlendAttachmentState.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
    pipelineColorBlendAttachmentState.alphaBlendOp = VK_BLEND_OP_ADD;
    pipelineColorBlendAttachmentState.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;

    VkPipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo;
    pipelineColorBlendStateCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
    pipelineColorBlendStateCreateInfo.pNext = nullptr;
    pipelineColorBlendStateCreateInfo.flags = 0;
    pipelineColorBlendStateCreateInfo.logicOpEnable = VK_FALSE;
    pipelineColorBlendStateCreateInfo.logicOp = VK_LOGIC_OP_NO_OP;
    pipelineColorBlendStateCreateInfo.attachmentCount = 1;
    pipelineColorBlendStateCreateInfo.pAttachments = &pipelineColorBlendAttachmentState;
    pipelineColorBlendStateCreateInfo.blendConstants[0] = 0.0f;
    pipelineColorBlendStateCreateInfo.blendConstants[1] = 0.0f;
    pipelineColorBlendStateCreateInfo.blendConstants[2] = 0.0f;
    pipelineColorBlendStateCreateInfo.blendConstants[3] = 0.0f;

    VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo;
    pipelineLayoutCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
    pipelineLayoutCreateInfo.pNext = nullptr;
    pipelineLayoutCreateInfo.flags = 0;
    pipelineLayoutCreateInfo.setLayoutCount = 0;
    pipelineLayoutCreateInfo.pSetLayouts = nullptr;
    pipelineLayoutCreateInfo.pushConstantRangeCount = 0;
    pipelineLayoutCreateInfo.pPushConstantRanges = nullptr;

    vkCreatePipelineLayout(device, &pipelineLayoutCreateInfo, nullptr, &pipelineLayout);
    ASSERT_VULKAN(result);

    VkAttachmentDescription attachmentDescription;
    attachmentDescription.flags = 0;
    attachmentDescription.format = format_R8G8B8A8_SRGB;
    attachmentDescription.samples = VK_SAMPLE_COUNT_1_BIT;
    attachmentDescription.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
    attachmentDescription.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
    attachmentDescription.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
    attachmentDescription.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
    attachmentDescription.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    attachmentDescription.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;

    VkAttachmentReference attachmentReference;
    attachmentReference.attachment = 0;
    attachmentReference.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

    VkSubpassDescription subpassDescription;
    subpassDescription.flags = 0;
    subpassDescription.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
    subpassDescription.inputAttachmentCount = 0;
    subpassDescription.pInputAttachments = nullptr;
    subpassDescription.colorAttachmentCount = 1;
    subpassDescription.pColorAttachments = &attachmentReference;
    subpassDescription.pResolveAttachments = nullptr;
    subpassDescription.pDepthStencilAttachment = nullptr;
    subpassDescription.preserveAttachmentCount = 0;
    subpassDescription.pPreserveAttachments = nullptr;

    VkSubpassDependency subpassDependency;
    subpassDependency.srcSubpass = VK_SUBPASS_EXTERNAL;
    subpassDependency.dstSubpass = 0;
    subpassDependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    subpassDependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    subpassDependency.srcAccessMask = 0;
    subpassDependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
    subpassDependency.dependencyFlags = 0;

    VkRenderPassCreateInfo renderPassCreateInfo;
    renderPassCreateInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
    renderPassCreateInfo.pNext = nullptr;
    renderPassCreateInfo.flags = 0;
    renderPassCreateInfo.attachmentCount = 1;
    renderPassCreateInfo.pAttachments = &attachmentDescription;
    renderPassCreateInfo.subpassCount = 1;
    renderPassCreateInfo.pSubpasses = &subpassDescription;
    renderPassCreateInfo.dependencyCount = 1;
    renderPassCreateInfo.pDependencies = &subpassDependency;

    result = vkCreateRenderPass(device, &renderPassCreateInfo, nullptr, &renderPass);
    ASSERT_VULKAN(result);

    VkGraphicsPipelineCreateInfo graphicsPipelineCreateInfo;
    graphicsPipelineCreateInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
    graphicsPipelineCreateInfo.pNext = nullptr;
    graphicsPipelineCreateInfo.flags = 0;
    graphicsPipelineCreateInfo.stageCount = 2;
    graphicsPipelineCreateInfo.pStages = pipelineShaderStagesCreateInfo;
    graphicsPipelineCreateInfo.pVertexInputState = &pipelineVertexInputCreateInfo;
    graphicsPipelineCreateInfo.pInputAssemblyState = &pipelineInputAssembyCreateInfo;
    graphicsPipelineCreateInfo.pTessellationState = nullptr;
    graphicsPipelineCreateInfo.pViewportState = &pipelineViewportStateCreateInfo;
    graphicsPipelineCreateInfo.pRasterizationState = &pipelineRasterizationStateCreateInfo;
    graphicsPipelineCreateInfo.pMultisampleState = &pipelineMultiSampleStateCreateInfo;
    graphicsPipelineCreateInfo.pDepthStencilState = nullptr;
    graphicsPipelineCreateInfo.pColorBlendState = &pipelineColorBlendStateCreateInfo;
    graphicsPipelineCreateInfo.pDynamicState = nullptr;
    graphicsPipelineCreateInfo.layout = pipelineLayout;
    graphicsPipelineCreateInfo.renderPass = renderPass;
    graphicsPipelineCreateInfo.subpass = 0;
    graphicsPipelineCreateInfo.basePipelineHandle = VK_NULL_HANDLE;
    graphicsPipelineCreateInfo.basePipelineIndex = -1;

    result = vkCreateGraphicsPipelines(device, VK_NULL_HANDLE, 1, &graphicsPipelineCreateInfo, nullptr, &pipeline);
    ASSERT_VULKAN(result);

    frameBuffers = new VkFramebuffer[amountOfImagesInSwapchain];

    for (size_t i = 0; i < amountOfImagesInSwapchain; i++) {
        VkFramebufferCreateInfo framebufferCreateInfo;
        framebufferCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
        framebufferCreateInfo.pNext = nullptr;
        framebufferCreateInfo.flags = 0;
        framebufferCreateInfo.renderPass = renderPass;
        framebufferCreateInfo.attachmentCount = 1;
        framebufferCreateInfo.pAttachments = &(imageViews[i]);
        framebufferCreateInfo.width = wWidth;
        framebufferCreateInfo.height = wHeight;
        framebufferCreateInfo.layers = 1;

        result = vkCreateFramebuffer(device, &framebufferCreateInfo, nullptr, &(frameBuffers[i]));
        ASSERT_VULKAN(result);
    }

    VkCommandPoolCreateInfo commandPoolCreateInfo;
    commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
    commandPoolCreateInfo.pNext = nullptr;
    commandPoolCreateInfo.flags = 0;
    commandPoolCreateInfo.queueFamilyIndex = 0; //TODO civ

    result = vkCreateCommandPool(device, &commandPoolCreateInfo, nullptr, &commandPool);
    ASSERT_VULKAN(result);

    VkCommandBufferAllocateInfo commandBufferAllocateInfo;
    commandBufferAllocateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
    commandBufferAllocateInfo.pNext = nullptr;
    commandBufferAllocateInfo.commandPool = commandPool;
    commandBufferAllocateInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
    commandBufferAllocateInfo.commandBufferCount = amountOfImagesInSwapchain;

    commandBuffers = new VkCommandBuffer[amountOfImagesInSwapchain];
    result = vkAllocateCommandBuffers(device, &commandBufferAllocateInfo, commandBuffers);
    ASSERT_VULKAN(result);

    VkCommandBufferBeginInfo commandBufferBeginInfo;
    commandBufferBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
    commandBufferBeginInfo.pNext = nullptr;
    commandBufferBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT;
    commandBufferBeginInfo.pInheritanceInfo = nullptr;

    for (size_t i = 0; i < amountOfImagesInSwapchain; i++) {
        result = vkBeginCommandBuffer(commandBuffers[i], &commandBufferBeginInfo);
        ASSERT_VULKAN(result);

        VkRenderPassBeginInfo renderPassBeginInfo;
        renderPassBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
        renderPassBeginInfo.pNext = nullptr;
        renderPassBeginInfo.renderPass = renderPass;
        renderPassBeginInfo.framebuffer = frameBuffers[i];
        renderPassBeginInfo.renderArea.offset = { 0, 0 };
        renderPassBeginInfo.renderArea.extent = { wWidth, wHeight };
        VkClearValue clearValue = { 0.0f, 0.0f, 0.0f, 1.0f };
        renderPassBeginInfo.clearValueCount = 1;
        renderPassBeginInfo.pClearValues = &clearValue;

        vkCmdBeginRenderPass(commandBuffers[i], &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);

        vkCmdBindPipeline(commandBuffers[i], VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);

        vkCmdDraw(commandBuffers[i], 3, 1, 0, 0);

        vkCmdEndRenderPass(commandBuffers[i]);

        result = vkEndCommandBuffer(commandBuffers[i]);
        ASSERT_VULKAN(result);
    }

    VkSemaphoreCreateInfo semaphoreCreateInfo;
    semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    semaphoreCreateInfo.pNext = nullptr;
    semaphoreCreateInfo.flags = 0;

    result = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &semaphoreImageAvailable);
    ASSERT_VULKAN(result);

    result = vkCreateSemaphore(device, &semaphoreCreateInfo, nullptr, &semaphoreRenderingDone);
    ASSERT_VULKAN(result);

    delete[] swapchainImages;
    delete[] layerProperties;
    delete[] extensionProperties;
    delete[] physicalDevices;
}

void drawFrame() {
    uint32_t imageIndex;

    VkResult result = vkAcquireNextImageKHR(device, swapchain, (std::numeric_limits<uint64_t>::max)(), semaphoreImageAvailable, VK_NULL_HANDLE, &imageIndex);
    ASSERT_VULKAN(result);

    VkSubmitInfo submitInfo;
    submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
    submitInfo.pNext = nullptr;
    submitInfo.waitSemaphoreCount = 1;
    submitInfo.pWaitSemaphores = &semaphoreImageAvailable;
    VkPipelineStageFlags waitStageMask[] = { VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
    submitInfo.pWaitDstStageMask = waitStageMask;
    submitInfo.commandBufferCount = 1;
    submitInfo.pCommandBuffers = &(commandBuffers[imageIndex]);
    submitInfo.signalSemaphoreCount = 1;
    submitInfo.pSignalSemaphores = &semaphoreRenderingDone;

    result = vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE);
    ASSERT_VULKAN(result);

    VkPresentInfoKHR presentInfo;
    presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    presentInfo.pNext = nullptr;
    presentInfo.waitSemaphoreCount = 1;
    presentInfo.pWaitSemaphores = &semaphoreRenderingDone;
    presentInfo.swapchainCount = 1;
    presentInfo.pSwapchains = &swapchain;
    presentInfo.pImageIndices = &imageIndex;
    presentInfo.pResults = nullptr;

    result = vkQueuePresentKHR(queue, &presentInfo);
    ASSERT_VULKAN(result);
}

void gameLoop() {
    while (!glfwWindowShouldClose(window)) {
        glfwPollEvents();
        drawFrame();
    }
}

void shutdownVulkan() {
    vkDeviceWaitIdle(device);

    vkDestroySemaphore(device, semaphoreImageAvailable, nullptr);
    vkDestroySemaphore(device, semaphoreRenderingDone, nullptr);

    vkFreeCommandBuffers(device, commandPool, amountOfImagesInSwapchain, commandBuffers);
    delete[] commandBuffers;

    vkDestroyCommandPool(device, commandPool, nullptr);

    for (size_t i = 0; i < amountOfImagesInSwapchain; i++) {
        vkDestroyFramebuffer(device, frameBuffers[i], nullptr);
    }
    delete[] frameBuffers;

    vkDestroyRenderPass(device, renderPass, nullptr);
    vkDestroyPipeline(device, pipeline, nullptr);

    for (int i = 0; i < amountOfImagesInSwapchain; i++) {
        vkDestroyImageView(device, imageViews[i], nullptr);
    }
    delete[] imageViews;
    vkDestroyPipelineLayout(device, pipelineLayout, nullptr);
    vkDestroyShaderModule(device, shaderModuleVert, nullptr);
    vkDestroyShaderModule(device, shaderModuleFrag, nullptr);
    vkDestroySwapchainKHR(device, swapchain, nullptr);
    vkDestroyDevice(device, nullptr);
    vkDestroySurfaceKHR(instance, surface, nullptr);
    vkDestroyInstance(instance, nullptr);
}

void shutdownGlfw() {
    glfwDestroyWindow(window);
}

int main()
{
    startGlfw();
    startVulkan();
    gameLoop();
    shutdownVulkan();
    shutdownGlfw();

    return 0;
}

vulkErrors.h code


#pragma once
#include "vulkHeaders.h"

#define ASSERT_VULKAN(val)\
switch(val) {\
    case VK_SUCCESS:\
        break; \
    case VK_NOT_READY:\
        std::cout << "Vulkan error VK_NOT_READY: A resource (such as an image or buffer) is not yet ready for use! \n"; \
        break; \
    case VK_TIMEOUT:\
        std::cout << "Vulkan error VK_TIMEOUT: An operation timed out! \n"; \
        break; \
    case VK_EVENT_SET:\
        std::cout << "Vulkan error VK_EVENT_SET: An event object has been signaled (set) by another part of your application! \n"; \
        break; \
    case VK_EVENT_RESET:\
        std::cout << "Vulkan error VK_EVENT_RESET: An event object has been reset! \n"; \
        break; \
    case VK_INCOMPLETE:\
        std::cout << "Vulkan error VK_INCOMPLETE: The operation did not complete fully but made partial progress! \n"; \
        break; \
    case VK_ERROR_OUT_OF_HOST_MEMORY:\
        std::cout << "Vulkan error VK_ERROR_OUT_OF_HOST_MEMORY: The implementation ran out of host (CPU) memory while trying to allocate resources! \n"; \
        break; \
    case VK_ERROR_OUT_OF_DEVICE_MEMORY:\
        std::cout << "Vulkan error VK_ERROR_OUT_OF_DEVICE_MEMORY: The implementation ran out of device (GPU) memory while trying to allocate resources! \n"; \
        break; \
    case VK_ERROR_INITIALIZATION_FAILED:\
        std::cout << "Vulkan error VK_ERROR_INITIALIZATION_FAILED: Failed to create an instance or device! \n"; \
        break; \
    case VK_ERROR_DEVICE_LOST:\
        std::cout << "Vulkan error VK_ERROR_DEVICE_LOST: The physical device (GPU) has been lost or is no longer available! \n"; \
        break; \
    case VK_ERROR_MEMORY_MAP_FAILED:\
        std::cout << "Vulkan error VK_ERROR_MEMORY_MAP_FAILED: Mapping memory failed (e.g., mapping a buffer or an image)! \n"; \
        break; \
    case VK_ERROR_LAYER_NOT_PRESENT:\
        std::cout << "Vulkan error VK_ERROR_LAYER_NOT_PRESENT: A requested layer is not available! \n"; \
        break; \
    case VK_ERROR_EXTENSION_NOT_PRESENT:\
        std::cout << "Vulkan error VK_ERROR_EXTENSION_NOT_PRESENT: A requested extension is not available! \n"; \
        break; \
    case VK_ERROR_FEATURE_NOT_PRESENT:\
        std::cout << "Vulkan error VK_ERROR_FEATURE_NOT_PRESENT: A requested feature is not supported! \n"; \
        break; \
    case VK_ERROR_INCOMPATIBLE_DRIVER:\
        std::cout << "Vulkan error VK_ERROR_INCOMPATIBLE_DRIVER: The installed Vulkan driver is incompatible with the application! \n"; \
        break; \
    case VK_ERROR_TOO_MANY_OBJECTS:\
        std::cout << "Vulkan error VK_ERROR_TOO_MANY_OBJECTS: The maximum number of allowed Vulkan objects (e.g., descriptors, pipelines) has been exceeded! \n"; \
        break; \
    case VK_ERROR_FORMAT_NOT_SUPPORTED:\
        std::cout << "Vulkan error VK_ERROR_FORMAT_NOT_SUPPORTED: A requested image or buffer format is not supported! \n"; \
        break; \
    case VK_ERROR_FRAGMENTED_POOL:\
        std::cout << "Vulkan error VK_ERROR_FRAGMENTED_POOL: A memory pool became too fragmented, making it challenging to allocate memory efficiently! \n"; \
        break; \
    case VK_ERROR_UNKNOWN:\
        std::cout << "Vulkan error VK_ERROR_UNKNOWN: Something went wrong, but the specific cause is not explicitly defined! \n"; \
        break; \
    case VK_ERROR_OUT_OF_POOL_MEMORY:\
        std::cout << "Vulkan error VK_ERROR_OUT_OF_POOL_MEMORY: The implementation couldn’t allocate memory from a memory pool! \n"; \
        break; \
    case VK_ERROR_INVALID_EXTERNAL_HANDLE:\
        std::cout << "Vulkan error VK_ERROR_INVALID_EXTERNAL_HANDLE: An external handle (such as a window or surface handle) is invalid or not recognized! \n"; \
        break; \
    case VK_ERROR_FRAGMENTATION:\
        std::cout << "Vulkan error VK_ERROR_FRAGMENTATION: Fragmentation in memory allocation! \n"; \
        break; \
    case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS:\
        std::cout << "Vulkan error VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: An invalid address was encountered when capturing opaque addresses (e.g., pointers) during debugging or profiling! \n"; \
        break; \
    case VK_PIPELINE_COMPILE_REQUIRED:\
        std::cout << "Vulkan error VK_PIPELINE_COMPILE_REQUIRED: A pipeline needs to be recompiled due to changes in shaders or pipeline state! \n"; \
        break; \
    case VK_ERROR_SURFACE_LOST_KHR:\
        std::cout << "Vulkan error VK_ERROR_SURFACE_LOST_KHR: A surface (used for rendering) is lost (e.g., due to window resizing or display changes)! \n"; \
        break; \
    case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR:\
        std::cout << "Vulkan error VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: A native window (such as a platform-specific window handle) is already in use! \n"; \
        break; \
    case VK_SUBOPTIMAL_KHR:\
        std::cout << "Vulkan error VK_SUBOPTIMAL_KHR: The swapchain (used for presenting images to the screen) is suboptimal but still usable (e.g., due to window resizing or something else)! \n"; \
        break; \
    case VK_ERROR_OUT_OF_DATE_KHR:\
        std::cout << "Vulkan error VK_ERROR_OUT_OF_DATE_KHR: The swapchain is out of date. It’s essential to recreate the swapchain in response! \n"; \
        break; \
    case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR:\
        std::cout << "Vulkan error VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: The display system is incompatible with Vulkan! \n"; \
        break; \
    case VK_ERROR_VALIDATION_FAILED_EXT:\
        std::cout << "Vulkan error VK_ERROR_VALIDATION_FAILED_EXT: Validation layers checks failed during Vulkan operation! \n"; \
        break; \
    case VK_ERROR_INVALID_SHADER_NV:\
        std::cout << "Vulkan error VK_ERROR_INVALID_SHADER_NV: An invalid shader is encountered (e.g., during shader compilation)! \n"; \
        break; \
    case VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR:\
        std::cout << "Vulkan error VK_ERROR_IMAGE_USAGE_NOT_SUPPORTED_KHR: Unsupported image usage flags (e.g., the image can not be used in this way)! \n"; \
        break; \
    case VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR:\
        std::cout << "Vulkan error VK_ERROR_VIDEO_PICTURE_LAYOUT_NOT_SUPPORTED_KHR: The video picture layout requested is not supported (e.g., during video decoding and presentation)! \n"; \
        break; \
    case VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR:\
        std::cout << "Vulkan error VK_ERROR_VIDEO_PROFILE_OPERATION_NOT_SUPPORTED_KHR: The requested video profile operation is not supported (e.g., during video decoding and presentation)! \n"; \
        break; \
    case VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR:\
        std::cout << "Vulkan error VK_ERROR_VIDEO_PROFILE_FORMAT_NOT_SUPPORTED_KHR: The requested video profile format is not supported (e.g., during video decoding and presentation)! \n"; \
        break; \
    case VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR:\
        std::cout << "Vulkan error VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR: The specified video codec (e.g., H.264, VP9) is not supported! \n"; \
        break; \
    case VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR:\
        std::cout << "Vulkan error VK_ERROR_VIDEO_STD_VERSION_NOT_SUPPORTED_KHR: The requested video standard version (e.g., MPEG-2, HEVC) is not supported! \n"; \
        break; \
    case VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT:\
        std::cout << "Vulkan error VK_ERROR_INVALID_DRM_FORMAT_MODIFIER_PLANE_LAYOUT_EXT: Invalid format modifier (e.g. DRM (Direct Rendering Manager) format modifiers for plane layouts)! \n"; \
        break; \
    case VK_ERROR_NOT_PERMITTED_KHR:\
        std::cout << "Vulkan error VK_ERROR_NOT_PERMITTED_KHR: An operation is not permitted (e.g., due to security restrictions)! \n"; \
        break; \
    case VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT:\
        std::cout << "Vulkan error VK_ERROR_FULL_SCREEN_EXCLUSIVE_MODE_LOST_EXT: The full-screen exclusive mode is lost (e.g., due to focus changes or display mode switches)! \n"; \
        break; \
    case VK_THREAD_IDLE_KHR:\
        std::cout << "Vulkan error VK_THREAD_IDLE_KHR: A thread is idle (not actively processing Vulkan commands)! \n"; \
        break; \
    case VK_THREAD_DONE_KHR:\
        std::cout << "Vulkan error VK_THREAD_DONE_KHR: A thread has completed its Vulkan work! \n"; \
        break; \
    case VK_OPERATION_DEFERRED_KHR:\
        std::cout << "Vulkan error VK_OPERATION_DEFERRED_KHR: An operation has been deferred (postponed) for later execution! \n"; \
        break; \
    case VK_OPERATION_NOT_DEFERRED_KHR:\
        std::cout << "Vulkan error VK_OPERATION_NOT_DEFERRED_KHR: An operation cannot be deferred and must be executed immediately! \n"; \
        break; \
    case VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR:\
        std::cout << "Vulkan error VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR: The specified video standard parameters (e.g., frame rate, resolution) are invalid! \n"; \
        break; \
    case VK_ERROR_COMPRESSION_EXHAUSTED_EXT:\
        std::cout << "Vulkan error VK_ERROR_COMPRESSION_EXHAUSTED_EXT: The compression algorithm resources are exhausted! \n"; \
        break; \
    case VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT:\
        std::cout << "Vulkan error VK_ERROR_INCOMPATIBLE_SHADER_BINARY_EXT: A shader binary is incompatible!"; \
        break; \
    case VK_RESULT_MAX_ENUM:\
        std::cout << "Vulkan error VK_RESULT_MAX_ENUM: This value represents the maximum possible value for a Vulkan result code! \n"; \
        break; \
    default:\
        std::cout << "Vulkan error completely Unknown! \n"; \
        break; \
}
krOoze commented 3 months ago

This is not really debugging help forum.

Your semaphore indeed seems not retired while you are trying to reuse it.

Your code is basically:

1: vkAcquireNextImageKHR(signal: semaphoreImageAvailable); // no proof that wait for semaphore at step 2 finished
2: vkQueueSubmit(wait: semaphoreImageAvailable);
3: goto 1;
CiRazDeveloper commented 3 months ago

What would I have to do in order to fix the issue? I am new to Vulkan and I am following an old tutorial series that was made 7 years ago because the newer ones do not have such a thorough explanation.

Thank you for taking your time to read this!

krOoze commented 3 months ago

Except some mistakes and inclarities here and there, I believe the tutuorial explains it, or at least does it in the code.

How you know a semaphore is retired is that the batch it was part of completed execution. In Vulkan 1.0 you would generally do this with a Fence. For purposes of learning, you may initially just use vk*WaitIdle().

Here's an example how I would do it. Here's documented the architecture of that, largely implying why I would do it that way (slide 6).

CiRazDeveloper commented 3 months ago

Thank you very much for your time and responses! I will now close this case :)