Directory:
Solution\
Project\
Dependencies\
GLFW\
glfw3.h
glfw3native.h
lib\
glfw3.lib
glfw3_mt.lib
I included glfw3.lib and glfw3_mt.lib and my directory is in dependencies
I fixed the error by setting another project to require the project but now I just have unresolved external symbols for Vulkan
unresolved external symbol 'private: static struct VkInstance_T*'
unresolved external symbol 'private: static struct VkDebugUtilsMessengerEXT_T*'
I have gotten the error again
Welcome to the GLFW forum.
It looks like you are using Visual Studio. If you open the C/C++>General
properties page for your project and then click on the arrow to the right of the Additional Include Directories
you will open up a dialogue which shows the evaluated values of the include directories. Check that the Dependencies
directory is correctly listed there (i.e that $(ProjectDir)
evaluates to Solution\Project
).
For Vulkan you need to link to the Vulkan libraries. You might want to follow a tutorial for Visual Studio such as the one:
It is pointing to dependencies
I would try the following project:
Use CMake to create a project with GLFW - Multi-platform Windows, Linux and MacOS. - GitHub - juliettef/GLFW-CMake-starter: Use CMake to create a project with GLFW - Multi-platform Windows, Linux a...
This uses CMake and OpenGL, but if you follow the instructions it will create a working Visual Studio project. You can then use that to help you figure out why your own project isn’t working.
I fixed it by including it in the other project that is using it but I am getting:
You need to link to the Vulkan library, the link to the Vulkan tutorial I posted has an example of how to do that.
Ah, apologies I didn’t read the image properly since it was so small on my monitor. You have multiple definitions of the Vulkan struct VkInstance_T* initVulkan::instance
etc. I can’t see the full error message (please paste full text not images of part of the compilation & link output if possible) so it’s difficult to tell why.
One common reason this can happen is you have both declared and defined a function in a header file, but not declared it as inline. For example if you have:
// in a MyClass.h
struct MyClass
{
void MyFunc();
};
void MyClass::MyFunc() { return; } // This will cause multiple definition errors.
This can be fixed as:
// in a MyClass.h
struct MyClass
{
inline void MyFunc();
};
inline void MyClass::MyFunc() { return; } // This will cause multiple definition errors.
Please do note it’s really hard to help when I don’t have the code, project, full error messages etc.
I dont have that problem. Here is my code:
// InitVulkan.h
#pragma once
#define GLFW_INCLUDE_VULKAN
#include "../../Errors.h"
#include "GLFW/glfw3.h"
#include <iostream>
#include <vector>
#include <map>
#include <optional>
#include <string>
namespace InitVulkan
{
VkInstance instance;
VkDebugUtilsMessengerEXT debugMessenger;
ANDROERRORS CreateInstance();
ANDROERRORS CreateDebugger();
ANDROERRORS Init();
ANDROERRORS Cleanup();
};
// InitVulkan.cpp
#include "InitVulkan.h"
const std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
};
#ifdef NDEBUG
const bool enableValidationLayers = false;
#else
const bool enableValidationLayers = true;
#endif
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;
}
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);
}
}
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;
}
bool checkValidationLayerSupport() {
uint32_t layerCount;
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
std::vector<VkLayerProperties> availableLayers(layerCount);
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
return false;
}
ANDROERRORS InitVulkan::CreateDebugger()
{
if (!enableValidationLayers) return ANDROERRORS::NONE;
VkDebugUtilsMessengerCreateInfoEXT createInfo;
populateDebugMessengerCreateInfo(createInfo);
if (CreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger) != VK_SUCCESS) {
return ANDROERRORS::VULKAN_DEBUGGER_CREATION_FAILED;
}
return ANDROERRORS::NONE;
}
ANDROERRORS InitVulkan::Init() {
ANDROERRORS error = CreateInstance();
if (error != ANDROERRORS::NONE)
return error;
error = CreateDebugger();
if (error != ANDROERRORS::NONE)
return error;
}
ANDROERRORS InitVulkan::CreateInstance() {
if (enableValidationLayers && !checkValidationLayerSupport()) {
return ANDROERRORS::VULKAN_VALIDATION_REQUESTED_NONE_FOUND;
}
/*
VkStructureType sType;
const void* pNext;
const char* pApplicationName;
uint32_t applicationVersion;
const char* pEngineName;
uint32_t engineVersion;
uint32_t apiVersion;
*/
VkApplicationInfo appInfo{};
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
appInfo.pApplicationName = "Andromeda";
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
appInfo.pEngineName = "Vulkan";
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;
uint32_t glfwExtensionCount = 0;
const char** glfwExtensions;
glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount);
createInfo.enabledExtensionCount = glfwExtensionCount;
createInfo.ppEnabledExtensionNames = glfwExtensions;
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
if (enableValidationLayers) {
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
populateDebugMessengerCreateInfo(debugCreateInfo);
createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*)&debugCreateInfo;
}
else {
createInfo.enabledLayerCount = 0;
createInfo.pNext = nullptr;
}
std::vector<const char*> requiredExtensions;
for (uint32_t i = 0; i < glfwExtensionCount; i++) {
requiredExtensions.emplace_back(glfwExtensions[i]);
}
requiredExtensions.emplace_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
createInfo.flags |= VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
createInfo.enabledExtensionCount = (uint32_t)requiredExtensions.size();
createInfo.ppEnabledExtensionNames = requiredExtensions.data();
uint32_t extensionCount = 0;
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
std::vector<VkExtensionProperties> extensions(extensionCount);
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
return ANDROERRORS::VULKAN_INIT_FAILED;
}
return ANDROERRORS::NONE;
}
ANDROERRORS InitVulkan::Cleanup() {
if (enableValidationLayers) {
DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr);
}
vkDestroyInstance(instance, nullptr);
return ANDROERRORS::NONE;
}
You have two variables defined in the header file:
namespace InitVulkan
{
VkInstance instance;
VkDebugUtilsMessengerEXT debugMessenger;
This will cause a multiple definition error in the linker by breaking the One Definition Rule (ODR) if this header is included by more than one source file, see:
https://en.cppreference.com/w/cpp/language/definition
To fix this you could pass the variables as part of the function parameters and return values, or make the variables static members of a struct (and define them in the C++ file).
So you could do:
ANDROERRORS Init( VkInstance& instance, VkDebugUtilsMessengerEXT& debugMessenger);
and then define these variables in your main function and pass them to the Init function etc.