| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <vector> |
| |
| #include "magma_system.h" |
| #include "magma_util/macros.h" |
| #include "vulkan_shim.h" |
| |
| class TestWsiMagma { |
| public: |
| bool Init(); |
| bool Run(uint32_t frame_count); |
| |
| private: |
| VkInstance instance_; |
| VkDevice device_; |
| VkSurfaceKHR surface_; |
| VkExtent2D extent_; |
| VkSwapchainKHR swapchain_; |
| VkQueue queue_; |
| |
| PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR_; |
| PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fpGetPhysicalDeviceSurfaceCapabilitiesKHR_; |
| PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fpGetPhysicalDeviceSurfaceFormatsKHR_; |
| PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fpGetPhysicalDeviceSurfacePresentModesKHR_; |
| PFN_vkCreateSwapchainKHR fpCreateSwapchainKHR_; |
| PFN_vkDestroySwapchainKHR fpDestroySwapchainKHR_; |
| PFN_vkGetSwapchainImagesKHR fpGetSwapchainImagesKHR_; |
| PFN_vkAcquireNextImageKHR fpAcquireNextImageKHR_; |
| PFN_vkQueuePresentKHR fpQueuePresentKHR_; |
| }; |
| |
| bool operator==(VkExtent2D& a, VkExtent2D b) { return a.width == b.width && a.height == b.height; } |
| |
| bool TestWsiMagma::Init() |
| { |
| // Enumerate and create a device - use the anv_magma_stubs though |
| VkInstanceCreateInfo create_info{ |
| VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // VkStructureType sType; |
| nullptr, // const void* pNext; |
| 0, // VkInstanceCreateFlags flags; |
| nullptr, // const VkApplicationInfo* pApplicationInfo; |
| 0, // uint32_t enabledLayerCount; |
| nullptr, // const char* const* ppEnabledLayerNames; |
| 0, // uint32_t enabledExtensionCount; |
| nullptr, // const char* const* ppEnabledExtensionNames; |
| }; |
| |
| VkResult result; |
| |
| result = vkCreateInstance(&create_info, nullptr /*allocation_callbacks*/, &instance_); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "vkCreateInstance failed %d", result); |
| |
| printf("vkCreateInstance succeeded\n"); |
| |
| fpGetPhysicalDeviceSurfaceSupportKHR_ = |
| reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>( |
| vkGetInstanceProcAddr(instance_, "vkGetPhysicalDeviceSurfaceSupportKHR")); |
| assert(fpGetPhysicalDeviceSurfaceSupportKHR_); |
| fpGetPhysicalDeviceSurfaceCapabilitiesKHR_ = |
| reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>( |
| vkGetInstanceProcAddr(instance_, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR")); |
| assert(fpGetPhysicalDeviceSurfaceCapabilitiesKHR_); |
| fpGetPhysicalDeviceSurfaceFormatsKHR_ = |
| reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>( |
| vkGetInstanceProcAddr(instance_, "vkGetPhysicalDeviceSurfaceFormatsKHR")); |
| assert(fpGetPhysicalDeviceSurfaceFormatsKHR_); |
| fpGetPhysicalDeviceSurfacePresentModesKHR_ = |
| reinterpret_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>( |
| vkGetInstanceProcAddr(instance_, "vkGetPhysicalDeviceSurfacePresentModesKHR")); |
| assert(fpGetPhysicalDeviceSurfacePresentModesKHR_); |
| fpCreateSwapchainKHR_ = reinterpret_cast<PFN_vkCreateSwapchainKHR>( |
| vkGetInstanceProcAddr(instance_, "vkCreateSwapchainKHR")); |
| assert(fpCreateSwapchainKHR_); |
| fpDestroySwapchainKHR_ = reinterpret_cast<PFN_vkDestroySwapchainKHR>( |
| vkGetInstanceProcAddr(instance_, "vkDestroySwapchainKHR")); |
| assert(fpDestroySwapchainKHR_); |
| fpGetSwapchainImagesKHR_ = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>( |
| vkGetInstanceProcAddr(instance_, "vkGetSwapchainImagesKHR")); |
| assert(fpGetSwapchainImagesKHR_); |
| fpAcquireNextImageKHR_ = reinterpret_cast<PFN_vkAcquireNextImageKHR>( |
| vkGetInstanceProcAddr(instance_, "vkAcquireNextImageKHR")); |
| assert(fpAcquireNextImageKHR_); |
| fpQueuePresentKHR_ = reinterpret_cast<PFN_vkQueuePresentKHR>( |
| vkGetInstanceProcAddr(instance_, "vkQueuePresentKHR")); |
| assert(fpQueuePresentKHR_); |
| |
| uint32_t physical_device_count; |
| result = vkEnumeratePhysicalDevices(instance_, &physical_device_count, nullptr); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "vkEnumeratePhysicalDevices failed %d", result); |
| |
| if (physical_device_count < 1) |
| return DRETF(false, "unexpected physical_device_count %d", physical_device_count); |
| |
| printf("vkEnumeratePhysicalDevices returned count %d\n", physical_device_count); |
| |
| std::vector<VkPhysicalDevice> physical_devices(physical_device_count); |
| if ((result = vkEnumeratePhysicalDevices(instance_, &physical_device_count, |
| physical_devices.data())) != VK_SUCCESS) |
| return DRETF(false, "vkEnumeratePhysicalDevices failed %d", result); |
| |
| uint32_t queue_family_count; |
| vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[0], &queue_family_count, nullptr); |
| |
| if (queue_family_count < 1) |
| return DRETF(false, "invalid queue_family_count %d", queue_family_count); |
| |
| std::vector<VkQueueFamilyProperties> queue_family_properties(queue_family_count); |
| vkGetPhysicalDeviceQueueFamilyProperties(physical_devices[0], &queue_family_count, |
| queue_family_properties.data()); |
| |
| VkMagmaSurfaceCreateInfoKHR createInfo = { |
| .sType = VK_STRUCTURE_TYPE_MAGMA_SURFACE_CREATE_INFO_KHR, .pNext = nullptr, |
| }; |
| |
| result = vkCreateMagmaSurfaceKHR(instance_, &createInfo, nullptr, &surface_); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "vkCreateMagmaSurfaceKHR failed: %d", result); |
| |
| uint32_t queue_family_index = UINT32_MAX; |
| |
| for (uint32_t i = 0; i < queue_family_count; i++) { |
| VkBool32 supports_present; |
| fpGetPhysicalDeviceSurfaceSupportKHR_(physical_devices[0], i, surface_, &supports_present); |
| if (supports_present) |
| queue_family_index = i; |
| } |
| |
| if (queue_family_index == UINT32_MAX) |
| return DRETF(false, "couldn't find a queue supporting present"); |
| |
| uint32_t formatCount; |
| result = |
| fpGetPhysicalDeviceSurfaceFormatsKHR_(physical_devices[0], surface_, &formatCount, nullptr); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "fpGetPhysicalDeviceSurfaceFormatsKHR failed %d", result); |
| |
| std::vector<VkSurfaceFormatKHR> surfFormats(formatCount); |
| result = fpGetPhysicalDeviceSurfaceFormatsKHR_(physical_devices[0], surface_, &formatCount, |
| surfFormats.data()); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "fpGetPhysicalDeviceSurfaceFormatsKHR failed %d", result); |
| |
| if (surfFormats.size() != 1) |
| return DRETF(false, "unexpected number of surface formats %zd", surfFormats.size()); |
| |
| if (surfFormats[0].format != VK_FORMAT_B8G8R8A8_UNORM) |
| return DRETF(false, "unexpected surface format 0x%x", surfFormats[0].format); |
| |
| uint32_t presentModeCount; |
| result = fpGetPhysicalDeviceSurfacePresentModesKHR_(physical_devices[0], surface_, |
| &presentModeCount, nullptr); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "fpGetPhysicalDeviceSurfacePresentModesKHR failed %d", result); |
| |
| std::vector<VkPresentModeKHR> presentModes(presentModeCount); |
| result = fpGetPhysicalDeviceSurfacePresentModesKHR_(physical_devices[0], surface_, |
| &presentModeCount, presentModes.data()); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "fpGetPhysicalDeviceSurfacePresentModesKHR failed %d", result); |
| |
| if (presentModes.size() != 1) |
| return DRETF(false, "unexpected number of present modes %zd", presentModes.size()); |
| |
| if (presentModes[0] != VK_PRESENT_MODE_FIFO_KHR) |
| return DRETF(false, "unexpected present mode 0x%x", presentModes[0]); |
| |
| VkSurfaceCapabilitiesKHR surf_caps; |
| result = fpGetPhysicalDeviceSurfaceCapabilitiesKHR_(physical_devices[0], surface_, &surf_caps); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "fpGetPhysicalDeviceSurfaceCapabilitiesKHR_ failed %d", result); |
| |
| if (surf_caps.currentExtent == VkExtent2D{0, 0}) |
| return DRETF(false, "unexpected extent"); |
| |
| if (!(surf_caps.currentExtent == VkExtent2D{UINT32_MAX, UINT32_MAX})) |
| return DRETF(false, "unexpected extent"); |
| |
| if (!(surf_caps.minImageExtent == VkExtent2D{1,1})) |
| return DRETF(false, "unexpected minImageExtent"); |
| |
| if (!(surf_caps.maxImageExtent == VkExtent2D{UINT32_MAX, UINT32_MAX})) |
| return DRETF(false, "unexpected maxImageExtent"); |
| |
| extent_ = VkExtent2D{1024,768}; |
| |
| if (surf_caps.supportedCompositeAlpha != |
| (VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR | VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR)) |
| return DRETF(false, "unexpected supportedCompositeAlpha 0x%x", |
| surf_caps.supportedCompositeAlpha); |
| |
| if (surf_caps.minImageCount != 3) |
| return DRETF(false, "unexpected minImageCount %d", surf_caps.minImageCount); |
| |
| if (surf_caps.maxImageCount != 3) |
| return DRETF(false, "unexpected minImageCount %d", surf_caps.maxImageCount); |
| |
| if (surf_caps.supportedTransforms != VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) |
| return DRETF(false, "unexpected supportedTransforms 0x%x", surf_caps.supportedTransforms); |
| |
| if (surf_caps.maxImageArrayLayers != 1) |
| return DRETF(false, "unexpected maxImageArrayLayers 0x%x", surf_caps.maxImageArrayLayers); |
| |
| if (surf_caps.supportedUsageFlags != |
| (VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | |
| VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)) |
| return DRETF(false, "unexpected supportedUsageFlags 0x%x", surf_caps.supportedUsageFlags); |
| |
| // Create the device. |
| |
| float queue_priorities[1] = {0.0}; |
| |
| VkDeviceQueueCreateInfo queue_create_info = {.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, |
| .pNext = nullptr, |
| .flags = 0, |
| .queueFamilyIndex = queue_family_index, |
| .queueCount = 1, |
| .pQueuePriorities = queue_priorities}; |
| VkDeviceCreateInfo device_create_info = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, |
| .pNext = nullptr, |
| .flags = 0, |
| .queueCreateInfoCount = 1, |
| .pQueueCreateInfos = &queue_create_info, |
| .enabledLayerCount = 0, |
| .ppEnabledLayerNames = nullptr, |
| .enabledExtensionCount = 0, |
| .ppEnabledExtensionNames = nullptr, |
| .pEnabledFeatures = nullptr}; |
| |
| result = vkCreateDevice(physical_devices[0], &device_create_info, |
| nullptr /* allocationcallbacks */, &device_); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "vkCreateDevice failed: %d", result); |
| |
| vkGetDeviceQueue(device_, queue_family_index, 0, &queue_); |
| |
| VkSwapchainCreateInfoKHR swapchain_create_info = { |
| .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR, |
| .pNext = nullptr, |
| .surface = surface_, |
| .minImageCount = 2, |
| .imageFormat = VK_FORMAT_B8G8R8A8_UNORM, |
| .imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR, // the only supported value? |
| .imageExtent = extent_, |
| .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, |
| .preTransform = surf_caps.currentTransform, |
| .compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR, |
| .imageArrayLayers = 1, |
| .imageSharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| .queueFamilyIndexCount = 0, |
| .pQueueFamilyIndices = NULL, |
| .presentMode = presentModes[0], |
| .oldSwapchain = VK_NULL_HANDLE, |
| .clipped = true, |
| }; |
| |
| result = fpCreateSwapchainKHR_(device_, &swapchain_create_info, nullptr, &swapchain_); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "fpCreateSwapchainKHR failed: %d", result); |
| |
| return true; |
| } |
| |
| bool TestWsiMagma::Run(uint32_t frame_count) |
| { |
| uint32_t image_count; |
| |
| VkResult result = fpGetSwapchainImagesKHR_(device_, swapchain_, &image_count, nullptr); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "fpGetSwapchainImagesKHR failed: %d", result); |
| |
| std::vector<VkImage> images(image_count); |
| |
| result = fpGetSwapchainImagesKHR_(device_, swapchain_, &image_count, images.data()); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "fpGetSwapchainImagesKHR failed: %d", result); |
| |
| uint32_t image_index; |
| |
| for (uint32_t frame = 0; frame < frame_count; frame++) { |
| result = fpAcquireNextImageKHR_(device_, swapchain_, 0, VK_NULL_HANDLE, VK_NULL_HANDLE, |
| &image_index); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "fpAcquireNextImageKHR_ failed: %d", result); |
| |
| VkPresentInfoKHR present = { |
| .sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR, |
| .pNext = nullptr, |
| .waitSemaphoreCount = 0, |
| .pWaitSemaphores = nullptr, |
| .swapchainCount = 1, |
| .pSwapchains = &swapchain_, |
| .pImageIndices = &image_index, |
| }; |
| |
| result = fpQueuePresentKHR_(queue_, &present); |
| if (result != VK_SUCCESS) |
| return DRETF(false, "fpQueuePresentKHR_ failed (image index %u): %d", image_index, result); |
| } |
| |
| return true; |
| } |
| |
| int main(int argc, char** argv) |
| { |
| VulkanShimInit(); |
| |
| TestWsiMagma test; |
| if (!test.Init()) |
| return -1; |
| if (!test.Run(100)) |
| return 0; |
| } |