| @@ -2,13 +2,17 @@ | |||
| #include <vulkan/vulkan.h> | |||
| #include <iostream> | |||
| #include <string> | |||
| #include <vector> | |||
| const uint32_t kWidth = 16; | |||
| const uint32_t kHeight = 16; | |||
| int main() { | |||
| // Example code for creating a VkInstance. | |||
| #define ERROR(message) \ | |||
| std::cerr << message << std::endl; \ | |||
| std::exit(EXIT_FAILURE) | |||
| VkInstance CreateVkInstance() { | |||
| VkApplicationInfo app_info = {}; | |||
| app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; | |||
| app_info.apiVersion = VK_API_VERSION_1_1; | |||
| @@ -22,11 +26,97 @@ int main() { | |||
| create_info.ppEnabledLayerNames = nullptr; | |||
| VkInstance instance; | |||
| VkResult res = vkCreateInstance(&create_info, nullptr, &instance); | |||
| if (res != VK_SUCCESS) { | |||
| std::cerr << "Error creating VkInstance: " << res; | |||
| VkResult result = vkCreateInstance(&create_info, nullptr, &instance); | |||
| if (result != VK_SUCCESS) { | |||
| ERROR("Error creating VkInstance: " << result); | |||
| } | |||
| return instance; | |||
| } | |||
| VkPhysicalDevice ChooseVkPhysicalDevice(VkInstance instance) { | |||
| uint32_t device_count = 0; | |||
| VkResult result = vkEnumeratePhysicalDevices(instance, &device_count, nullptr); | |||
| if (result != VK_SUCCESS) { | |||
| ERROR("Error enumerating VkPhysicalDevices: " << result); | |||
| } | |||
| if (device_count == 0) { | |||
| ERROR("No available VkPhysicalDevices"); | |||
| } | |||
| std::vector<VkPhysicalDevice> devices(device_count); | |||
| result = vkEnumeratePhysicalDevices(instance, &device_count, devices.data()); | |||
| if (result != VK_SUCCESS) { | |||
| ERROR("Error fetching VkPhysicalDevices: " << result); | |||
| } | |||
| std::cout << "Found " << device_count << " device(s):" << std::endl; | |||
| VkPhysicalDevice chosen_device = VK_NULL_HANDLE; | |||
| for (VkPhysicalDevice device : devices) { | |||
| VkPhysicalDeviceProperties device_props; | |||
| vkGetPhysicalDeviceProperties(device, &device_props); | |||
| std::cout << "\t- " << device_props.deviceName << " [V: " << | |||
| VK_VERSION_MAJOR(device_props.apiVersion) << "." << | |||
| VK_VERSION_MINOR(device_props.apiVersion) << "." << | |||
| VK_VERSION_PATCH(device_props.apiVersion) << "]" << std::endl; | |||
| // Currently, any device with Vulkan API version 1.1 is fine. | |||
| if (chosen_device == VK_NULL_HANDLE && device_props.apiVersion >= VK_API_VERSION_1_1) { | |||
| chosen_device = device; | |||
| } | |||
| } | |||
| if (chosen_device == VK_NULL_HANDLE) { | |||
| ERROR("Unable to find suitable VkPhysicalDevice"); | |||
| } | |||
| return chosen_device; | |||
| } | |||
| uint32_t ChooseDeviceQueueFamilyIndex(VkPhysicalDevice physical_device) { | |||
| uint32_t props_count; | |||
| vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &props_count, nullptr); | |||
| std::vector<VkQueueFamilyProperties> props(props_count); | |||
| vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &props_count, props.data()); | |||
| // Simply choose the first graphics queue. | |||
| for (size_t i = 0; i < props_count; i++) { | |||
| const VkQueueFamilyProperties& prop = props[i]; | |||
| if ((prop.queueFlags & VK_QUEUE_GRAPHICS_BIT) && prop.queueCount > 0) { | |||
| return i; | |||
| } | |||
| } | |||
| ERROR("Unable to find suitable queue family"); | |||
| } | |||
| VkDevice CreateVkDevice(VkPhysicalDevice physical_device, uint32_t device_queue_family_index) { | |||
| VkDeviceQueueCreateInfo queue_create_info = {}; | |||
| queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; | |||
| queue_create_info.queueFamilyIndex = device_queue_family_index; | |||
| queue_create_info.queueCount = 1; | |||
| float queue_priority = 1.0f; | |||
| queue_create_info.pQueuePriorities = &queue_priority; | |||
| VkDeviceCreateInfo device_create_info = {}; | |||
| device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; | |||
| device_create_info.queueCreateInfoCount = 1; | |||
| device_create_info.pQueueCreateInfos = &queue_create_info; | |||
| // Let's not use any device extensions for now. | |||
| device_create_info.enabledExtensionCount = 0; | |||
| device_create_info.ppEnabledExtensionNames = nullptr; | |||
| VkDevice device; | |||
| VkResult result = vkCreateDevice(physical_device, &device_create_info, nullptr, &device); | |||
| if (result != VK_SUCCESS) { | |||
| ERROR("Unable to create logical device"); | |||
| } | |||
| return device; | |||
| } | |||
| int main() { | |||
| VkInstance instance = CreateVkInstance(); | |||
| VkPhysicalDevice physical_device = ChooseVkPhysicalDevice(instance); | |||
| uint32_t device_queue_family_index = ChooseDeviceQueueFamilyIndex(physical_device); | |||
| VkDevice device = CreateVkDevice(physical_device, device_queue_family_index); | |||
| // Example code for exporting a PNG. | |||
| FILE *f = fopen("triangle.png", "wb"); | |||
| @@ -47,10 +137,10 @@ int main() { | |||
| image_info.height = kHeight; | |||
| image_info.format = PNG_FORMAT_RGBA; | |||
| if (png_image_write_to_stdio(&image_info, f, 0, pixels.data(), kWidth * 4, nullptr) == 0) { | |||
| std::cout << "Error writing PNG: " << image_info.message << std::endl; | |||
| ERROR("Error writing PNG: " << image_info.message); | |||
| } | |||
| fclose(f); | |||
| return 0; | |||
| return EXIT_SUCCESS; | |||
| } | |||