From 2886bc35e7b023370a8b8d56d78e5335eee2eb98 Mon Sep 17 00:00:00 2001 From: Yong He Date: Fri, 16 Apr 2021 10:35:42 -0700 Subject: Add Hello world example. (#1797) --- examples/hello-world/vulkan-api.cpp | 228 ++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 examples/hello-world/vulkan-api.cpp (limited to 'examples/hello-world/vulkan-api.cpp') diff --git a/examples/hello-world/vulkan-api.cpp b/examples/hello-world/vulkan-api.cpp new file mode 100644 index 000000000..529ca7196 --- /dev/null +++ b/examples/hello-world/vulkan-api.cpp @@ -0,0 +1,228 @@ +#include "vulkan-api.h" +#include "slang.h" + +#include +#include +#include +#include + +#if SLANG_WINDOWS_FAMILY +# include +#else +# include +#endif + +#if _DEBUG +#define ENABLE_VALIDATION_LAYER 1 +#endif + +VKAPI_ATTR VkBool32 VKAPI_CALL debugMessageCallback( + VkDebugReportFlagsEXT /*flags*/, + VkDebugReportObjectTypeEXT /*objType*/, + uint64_t /*srcObject*/, + size_t /*location*/, + int32_t /*msgCode*/, + const char* pLayerPrefix, + const char* pMsg, + void* /*pUserData*/) +{ + printf("[%s]: %s\n", pLayerPrefix, pMsg); + return 1; +} + +int initializeVulkanDevice(VulkanAPI& api) +{ + // Load vulkan library. + const char* dynamicLibraryName = "Unknown"; + +#if SLANG_WINDOWS_FAMILY + dynamicLibraryName = "vulkan-1.dll"; + HMODULE module = ::LoadLibraryA(dynamicLibraryName); + api.vulkanLibraryHandle = (void*)module; +#define VK_API_GET_GLOBAL_PROC(x) api.x = (PFN_##x)GetProcAddress(module, #x); +#else + dynamicLibraryName = "libvulkan.so.1"; + api.vulkanLibraryHandle = dlopen(dynamicLibraryName, RTLD_NOW); +#define VK_API_GET_GLOBAL_PROC(x) api.x = (PFN_##x)dlsym(api.vulkanLibraryHandle, #x); +#endif + + // Initialize all the global functions. + VK_API_ALL_GLOBAL_PROCS(VK_API_GET_GLOBAL_PROC) + if (!api.vkCreateInstance) + return -1; + + // Create Vulkan Instance. + VkApplicationInfo applicationInfo = {VK_STRUCTURE_TYPE_APPLICATION_INFO}; + applicationInfo.pApplicationName = "slang-hello-world"; + applicationInfo.pEngineName = "slang-hello-world"; + applicationInfo.apiVersion = VK_API_VERSION_1_0; + applicationInfo.engineVersion = 1; + applicationInfo.applicationVersion = 1; + const char* instanceExtensions[] = { + VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, + VK_EXT_DEBUG_REPORT_EXTENSION_NAME, + }; + VkInstanceCreateInfo instanceCreateInfo = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO}; + instanceCreateInfo.pApplicationInfo = &applicationInfo; + instanceCreateInfo.enabledExtensionCount = SLANG_COUNT_OF(instanceExtensions); + instanceCreateInfo.ppEnabledExtensionNames = &instanceExtensions[0]; + std::vector layers; +#ifdef ENABLE_VALIDATION_LAYER + layers.push_back("VK_LAYER_KHRONOS_validation"); +#endif + if (layers.size()) + { + instanceCreateInfo.ppEnabledLayerNames = &layers[0]; + instanceCreateInfo.enabledLayerCount = (uint32_t)layers.size(); + } + if (api.vkCreateInstance(&instanceCreateInfo, nullptr, &api.instance) != 0) + return -1; + + // Load instance functions. + api.initInstanceProcs(); + + // Create debug report callback. + if (api.vkCreateDebugReportCallbackEXT) + { + VkDebugReportFlagsEXT debugFlags = + VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; + + VkDebugReportCallbackCreateInfoEXT debugCreateInfo = { + VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT}; + debugCreateInfo.pfnCallback = &debugMessageCallback; + debugCreateInfo.pUserData = nullptr; + debugCreateInfo.flags = debugFlags; + + RETURN_ON_FAIL(api.vkCreateDebugReportCallbackEXT( + api.instance, &debugCreateInfo, nullptr, &api.debugReportCallback)); + } + + // Enumerate physical devices. + uint32_t numPhysicalDevices = 0; + RETURN_ON_FAIL( + api.vkEnumeratePhysicalDevices(api.instance, &numPhysicalDevices, nullptr)); + std::vector physicalDevices; + physicalDevices.resize(numPhysicalDevices); + RETURN_ON_FAIL(api.vkEnumeratePhysicalDevices( + api.instance, &numPhysicalDevices, &physicalDevices[0])); + + // We will use device 0. + api.initPhysicalDevice(physicalDevices[0]); + + VkDeviceCreateInfo deviceCreateInfo = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO}; + deviceCreateInfo.queueCreateInfoCount = 1; + deviceCreateInfo.pEnabledFeatures = &api.deviceFeatures; + + // Find proper queue family index. + uint32_t numQueueFamilies = 0; + api.vkGetPhysicalDeviceQueueFamilyProperties(api.physicalDevice, &numQueueFamilies, nullptr); + + std::vector queueFamilies; + queueFamilies.resize(numQueueFamilies); + api.vkGetPhysicalDeviceQueueFamilyProperties( + api.physicalDevice, &numQueueFamilies, &queueFamilies[0]); + + // Find a queue that can service our needs. + auto requiredQueueFlags = VK_QUEUE_COMPUTE_BIT; + for (int i = 0; i < int(numQueueFamilies); ++i) + { + if ((queueFamilies[i].queueFlags & requiredQueueFlags) == requiredQueueFlags) + { + api.queueFamilyIndex = i; + break; + } + } + if (api.queueFamilyIndex == -1) + return -1; + + VkDeviceQueueCreateInfo queueCreateInfo = {VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO}; + float queuePriority = 0.0f; + queueCreateInfo.queueFamilyIndex = api.queueFamilyIndex; + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = &queuePriority; + deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo; + deviceCreateInfo.enabledExtensionCount = 0; + deviceCreateInfo.ppEnabledExtensionNames = nullptr; + RETURN_ON_FAIL(api.vkCreateDevice(api.physicalDevice, &deviceCreateInfo, nullptr, &api.device)); + + // Load device functions. + api.initDeviceProcs(); + + return 0; +} + +int VulkanAPI::initInstanceProcs() +{ + assert(instance && vkGetInstanceProcAddr != nullptr); + +#define VK_API_GET_INSTANCE_PROC(x) x = (PFN_##x)vkGetInstanceProcAddr(instance, #x); + + VK_API_ALL_INSTANCE_PROCS(VK_API_GET_INSTANCE_PROC) + // Get optional + VK_API_INSTANCE_PROCS_OPT(VK_API_GET_INSTANCE_PROC) + +#undef VK_API_GET_INSTANCE_PROC + + return 0; +} + +int VulkanAPI::initPhysicalDevice(VkPhysicalDevice inPhysicalDevice) +{ + assert(physicalDevice == VK_NULL_HANDLE); + physicalDevice = inPhysicalDevice; + + vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties); + vkGetPhysicalDeviceFeatures(physicalDevice, &deviceFeatures); + vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties); + + return 0; +} + +int VulkanAPI::initDeviceProcs() +{ + assert(instance && device && vkGetDeviceProcAddr != nullptr); + +#define VK_API_GET_DEVICE_PROC(x) x = (PFN_##x)vkGetDeviceProcAddr(device, #x); + VK_API_DEVICE_PROCS(VK_API_GET_DEVICE_PROC) +#undef VK_API_GET_DEVICE_PROC + + return 0; +} + +int VulkanAPI::findMemoryTypeIndex(uint32_t typeBits, VkMemoryPropertyFlags properties) +{ + assert(typeBits); + + const int numMemoryTypes = int(deviceMemoryProperties.memoryTypeCount); + + // bit holds current test bit against typeBits. Ie bit == 1 << typeBits + + uint32_t bit = 1; + for (int i = 0; i < numMemoryTypes; ++i, bit += bit) + { + auto const& memoryType = deviceMemoryProperties.memoryTypes[i]; + if ((typeBits & bit) && (memoryType.propertyFlags & properties) == properties) + { + return i; + } + } + + // assert(!"failed to find a usable memory type"); + return -1; +} + +VulkanAPI::~VulkanAPI() +{ + if (vkDestroyDevice) + { + vkDestroyDevice(device, nullptr); + } + if (vkDestroyDebugReportCallbackEXT) + { + vkDestroyDebugReportCallbackEXT(instance, debugReportCallback, nullptr); + } + if (vkDestroyInstance) + { + vkDestroyInstance(instance, nullptr); + } +} -- cgit v1.2.3