blob: ef5e39f920d661d529479f794606afe4af89fabb [file] [log] [blame]
// Copyright 2018 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 <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/zx/channel.h>
#include <cstdio>
#include <vector>
#include <gtest/gtest.h>
#include <vulkan/vulkan.h>
#include "src/lib/debug/backtrace-request.h"
class TestSurface {
public:
TestSurface(bool use_framebuffer = false) : use_framebuffer_(use_framebuffer) {
const char* layer_name = use_framebuffer ? "VK_LAYER_FUCHSIA_imagepipe_swapchain_fb"
: "VK_LAYER_FUCHSIA_imagepipe_swapchain";
std::vector<const char*> instance_layers{layer_name};
std::vector<const char*> instance_ext{VK_KHR_SURFACE_EXTENSION_NAME,
VK_FUCHSIA_IMAGEPIPE_SURFACE_EXTENSION_NAME};
VkInstanceCreateInfo inst_info = {
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
.pNext = nullptr,
.pApplicationInfo = nullptr,
.enabledLayerCount = static_cast<uint32_t>(instance_layers.size()),
.ppEnabledLayerNames = instance_layers.data(),
.enabledExtensionCount = static_cast<uint32_t>(instance_ext.size()),
.ppEnabledExtensionNames = instance_ext.data(),
};
VkResult ret = vkCreateInstance(&inst_info, nullptr, &vk_instance_);
if (ret != VK_SUCCESS) {
fprintf(stderr, "ERROR: vkCreateInstance() returned: %d\n", ret);
return;
}
init_ = true;
}
~TestSurface() {
if (vk_instance_) {
vkDestroyInstance(vk_instance_, nullptr);
}
}
void CreateSurface(bool use_dynamic_symbol) {
ASSERT_TRUE(init_);
PFN_vkCreateImagePipeSurfaceFUCHSIA f_vkCreateImagePipeSurfaceFUCHSIA =
use_dynamic_symbol
? reinterpret_cast<PFN_vkCreateImagePipeSurfaceFUCHSIA>(
vkGetInstanceProcAddr(vk_instance_, "vkCreateImagePipeSurfaceFUCHSIA"))
: vkCreateImagePipeSurfaceFUCHSIA;
ASSERT_TRUE(f_vkCreateImagePipeSurfaceFUCHSIA);
zx::channel endpoint0, endpoint1;
if (!use_framebuffer_) {
EXPECT_EQ(ZX_OK, zx::channel::create(0, &endpoint0, &endpoint1));
}
VkImagePipeSurfaceCreateInfoFUCHSIA create_info = {
.sType = VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA,
.pNext = nullptr,
.imagePipeHandle = use_framebuffer_ ? ZX_HANDLE_INVALID : endpoint0.release(),
};
VkSurfaceKHR surface = VK_NULL_HANDLE;
VkResult result =
f_vkCreateImagePipeSurfaceFUCHSIA(vk_instance_, &create_info, nullptr, &surface);
EXPECT_EQ(VK_SUCCESS, result);
if (VK_SUCCESS == result) {
vkDestroySurfaceKHR(vk_instance_, surface, nullptr);
}
}
void GetPresentModes() {
ASSERT_TRUE(init_);
zx::channel endpoint0, endpoint1;
if (!use_framebuffer_) {
EXPECT_EQ(ZX_OK, zx::channel::create(0, &endpoint0, &endpoint1));
}
VkImagePipeSurfaceCreateInfoFUCHSIA create_info = {
.sType = VK_STRUCTURE_TYPE_IMAGEPIPE_SURFACE_CREATE_INFO_FUCHSIA,
.pNext = nullptr,
.imagePipeHandle = use_framebuffer_ ? ZX_HANDLE_INVALID : endpoint0.release(),
};
VkSurfaceKHR surface = VK_NULL_HANDLE;
ASSERT_EQ(VK_SUCCESS,
vkCreateImagePipeSurfaceFUCHSIA(vk_instance_, &create_info, nullptr, &surface));
uint32_t count;
ASSERT_EQ(VK_SUCCESS, vkEnumeratePhysicalDevices(vk_instance_, &count, nullptr));
ASSERT_GE(count, 1u);
std::vector<VkPhysicalDevice> devices(count);
EXPECT_EQ(VK_SUCCESS, vkEnumeratePhysicalDevices(vk_instance_, &count, devices.data()));
EXPECT_EQ(VK_SUCCESS,
vkGetPhysicalDeviceSurfacePresentModesKHR(devices[0], surface, &count, nullptr));
std::vector<VkPresentModeKHR> present_modes(count);
ASSERT_GE(count, 1u);
EXPECT_EQ(VK_SUCCESS, vkGetPhysicalDeviceSurfacePresentModesKHR(devices[0], surface, &count,
present_modes.data()));
bool found_fifo = false;
for (auto mode : present_modes) {
if (mode == VK_PRESENT_MODE_FIFO_KHR) {
found_fifo = true;
break;
}
}
EXPECT_TRUE(found_fifo);
vkDestroySurfaceKHR(vk_instance_, surface, nullptr);
}
bool use_framebuffer_ = false;
VkInstance vk_instance_ = VK_NULL_HANDLE;
bool init_ = false;
};
TEST(Surface, CreateImagePipeSurface) {
TestSurface(false /* use_framebuffer */).CreateSurface(false /* use_dynamic_symbol */);
}
TEST(Surface, CreateImagePipeSurfaceDynamicSymbol) { TestSurface(false).CreateSurface(true); }
// Flaking: see https://fxbug.dev/42143937
TEST(Surface, DISABLED_CreateFramebufferSurface) { TestSurface(true).CreateSurface(false); }
TEST(Surface, CreateFramebufferSurfaceDynamicSymbol) {
async::Loop loop(&kAsyncLoopConfigNeverAttachToThread);
loop.StartThread();
// Perform a backtrace if the test takes too long to try to diagnose https://fxbug.dev/42060352
async::PostDelayedTask(
loop.dispatcher(), []() { backtrace_request_all_threads(); }, zx::sec(20));
TestSurface(true).CreateSurface(true);
// Cancels the backtrace request if it hasn't yet executed.
loop.Shutdown();
}
TEST(Surface, GetPresentModes) { TestSurface(true).GetPresentModes(); }