diff --git a/Makefile b/Makefile index 6d538e3..da07ff1 100644 --- a/Makefile +++ b/Makefile @@ -1,15 +1,18 @@ CFLAGS = -std=c++11 LDFLAGS = -L/usr/local/lib -lglfw -lrt -lm -ldl -lXrandr -lXinerama -lXxf86vm -lXext -lXcursor -lXrender -lXfixes -lX11 -lpthread -lxcb -lXau -lvulkan -all: VulkanTest +all: VulkanTest VulkanComputeTest VulkanTest: main.cpp g++ $(CFLAGS) -g -o VulkanTest main.cpp $(LDFLAGS) +VulkanComputeTest: compute.cpp + clang++ $(CFLAGS) -g -o VulkanComputeTest compute.cpp -lvulkan + .PHONY: test clean test: VulkanTest LD_LIBRARY_PATH=$(VULKAN_SDK_PATH)/lib VK_LAYER_PATH=$(VULKAN_SDK_PATH)/etc/explicit_layer.d ./VulkanTest clean: - rm -f VulkanTest + rm -f VulkanTest VulkanComputeTest diff --git a/compute.cpp b/compute.cpp new file mode 100644 index 0000000..ca44de0 --- /dev/null +++ b/compute.cpp @@ -0,0 +1,181 @@ +#include +#include + +#include + +const std::vector validationLayers = { + "VK_LAYER_LUNARG_standard_validation" +}; +#ifdef NDEBUG + const bool enableValidationLayers = false; +#else + const bool enableValidationLayers = true; +#endif + +// Wrappers for extension functions that must be located using vkGetInstanceProcAddr +VkResult CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT* pCreateInfo, +const VkAllocationCallbacks* pAllocator, VkDebugReportCallbackEXT* pCallback) { + auto func = (PFN_vkCreateDebugReportCallbackEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"); + if(func != nullptr) { + return func(instance, pCreateInfo, pAllocator, pCallback); + } else { + return VK_ERROR_EXTENSION_NOT_PRESENT; + } +} + +void DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks* pAllocator) { + auto func = (PFN_vkDestroyDebugReportCallbackEXT) vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT"); + if(func != nullptr) { + func(instance, callback, pAllocator); + } +} + +class HelloVkCompute +{ + private: + /* data */ + VkInstance instance; + VkDebugReportCallbackEXT callback; + VkPhysicalDevice physicalDevice; + + // Check if the validation layers are supported. + 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; + } + + // Set up our debug report callback to get information back from the validation layers. + void setupDebugCallback() { + if (!enableValidationLayers) return; + + VkDebugReportCallbackCreateInfoEXT createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; + createInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; + createInfo.pfnCallback = debugCallback; + + if(CreateDebugReportCallbackEXT(instance, &createInfo, nullptr, &callback) != VK_SUCCESS) { + throw std::runtime_error("failed to setup debug callback!"); + } + } + + void cleanupDebugCallback() { + if (!enableValidationLayers) return; + + DestroyDebugReportCallbackEXT(instance, callback, nullptr); + } + + void initVulkan() { + if(enableValidationLayers && !checkValidationLayerSupport()) { + throw std::runtime_error("validation layers requested, but not supported"); + } + + // Create VkApplicationInfo + VkApplicationInfo appInfo = {}; + appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + appInfo.pApplicationName = "Hello Vk Compute"; + 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; + + // Create VkInstanceCreateInfo and have it point to VkApplicationInfo + VkInstanceCreateInfo createInfo = {}; + createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + createInfo.pApplicationInfo = &appInfo; + + // Enable the validation layers if they are requested + if(enableValidationLayers) { + createInfo.enabledLayerCount = validationLayers.size(); + createInfo.ppEnabledLayerNames = validationLayers.data(); + } else { + createInfo.enabledLayerCount = 0; + } + + if(vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { + throw std::runtime_error("failed to create Vulkan instance!"); + } + + uint32_t extensionCount = 0; + + vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); + std::vector extensions(extensionCount); + vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); + + std::cout << "available extensions:" << std::endl; + + for(const auto& extension : extensions) { + std::cout << "\t" << extension.extensionName << std::endl; + } + + } + + void pickDevice() { + uint32_t deviceCount = 0; + vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); + + if(deviceCount == 0) { + throw std::runtime_error("Failed to find a device 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 device!"); + } + } +public: + // our debug callback function, just prints the message from the Validation layer to stderr + static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( VkDebugReportFlagsEXT flags, + VkDebugReportObjectTypeEXT objType, uint64_t obj, size_t location, int32_t code, + const char* layerPrefix, const char* msg, void* userData) { + std::cerr << "[Validation Layer]: " << msg << std::endl; + + return VK_FALSE; + } + + void run() { + initVulkan(); + pickDevice(); + } + +}; + +int main() { + HelloVkCompute app; + try { + app.run(); + } catch (const std::runtime_error& e) { + std::cerr << e.what() << std::endl; + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/main.cpp b/main.cpp index 020240b..1a17f74 100644 --- a/main.cpp +++ b/main.cpp @@ -198,7 +198,7 @@ private: vkDestroyInstance(instance, nullptr); } - // Check if the validation layers are supported.s + // Check if the validation layers are supported. bool checkValidationLayerSupport() { uint32_t layerCount; vkEnumerateInstanceLayerProperties(&layerCount, nullptr);