blob: 3b7d31df7c002c18a91de699f60b3c2f76644e7c [file] [log] [blame]
// Copyright 2017 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 "gtest/gtest.h"
#if defined(MAGMA_USE_SHIM)
#include "vulkan_shim.h"
#else
#include <vulkan/vulkan.h>
#endif
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include "magma_util/dlog.h"
#include "magma_util/macros.h"
namespace {
class VulkanTest {
public:
static bool CheckExtensions();
bool Initialize();
bool Exec();
private:
bool InitVulkan();
bool InitImage();
bool is_initialized_ = false;
VkPhysicalDevice vk_physical_device_;
VkDevice vk_device_;
VkQueue vk_queue_;
VkImage vk_image_;
VkDeviceMemory vk_device_memory_;
VkCommandPool vk_command_pool_;
VkCommandBuffer vk_command_buffer_;
};
bool VulkanTest::CheckExtensions()
{
uint32_t count;
VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
if (result != VK_SUCCESS)
return DRETF(false, "vkEnumerateInstanceExtensionProperties returned %d\n", result);
std::vector<VkExtensionProperties> extension_properties(count);
result = vkEnumerateInstanceExtensionProperties(nullptr, &count, extension_properties.data());
if (result != VK_SUCCESS)
return DRETF(false, "vkEnumerateInstanceExtensionProperties returned %d\n", result);
uint32_t found_count = 0;
for (auto& prop : extension_properties) {
DLOG("extension name %s version %u", prop.extensionName, prop.specVersion);
if (strcmp(prop.extensionName, VK_GOOGLE_IMAGE_USAGE_SCANOUT_EXTENSION_NAME) == 0)
found_count++;
}
return found_count == 1;
}
bool VulkanTest::Initialize()
{
if (is_initialized_)
return false;
if (!InitVulkan())
return DRETF(false, "failed to initialize Vulkan");
is_initialized_ = true;
return true;
}
bool VulkanTest::InitVulkan()
{
std::vector<const char*> enabled_extensions{VK_GOOGLE_IMAGE_USAGE_SCANOUT_EXTENSION_NAME};
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;
static_cast<uint32_t>(enabled_extensions.size()),
enabled_extensions.data(),
};
VkAllocationCallbacks* allocation_callbacks = nullptr;
VkInstance instance;
VkResult result;
if ((result = vkCreateInstance(&create_info, allocation_callbacks, &instance)) != VK_SUCCESS)
return DRETF(false, "vkCreateInstance failed %d", result);
DLOG("vkCreateInstance succeeded");
uint32_t physical_device_count;
if ((result = vkEnumeratePhysicalDevices(instance, &physical_device_count, nullptr)) !=
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);
DLOG("vkEnumeratePhysicalDevices returned count %d", 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);
for (auto device : physical_devices) {
VkPhysicalDeviceProperties properties;
vkGetPhysicalDeviceProperties(device, &properties);
DLOG("PHYSICAL DEVICE: %s", properties.deviceName);
DLOG("apiVersion 0x%x", properties.apiVersion);
DLOG("driverVersion 0x%x", properties.driverVersion);
DLOG("vendorID 0x%x", properties.vendorID);
DLOG("deviceID 0x%x", properties.deviceID);
DLOG("deviceType 0x%x", properties.deviceType);
}
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());
int32_t queue_family_index = -1;
for (uint32_t i = 0; i < queue_family_count; i++) {
if (queue_family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
queue_family_index = i;
break;
}
}
if (queue_family_index < 0)
return DRETF(false, "couldn't find an appropriate queue");
float queue_priorities[1] = {0.0};
VkDeviceQueueCreateInfo queue_create_info = {.sType =
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.pNext = nullptr,
.flags = 0,
.queueFamilyIndex = 0,
.queueCount = 1,
.pQueuePriorities = queue_priorities};
VkDeviceCreateInfo createInfo = {.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};
VkDevice vkdevice;
if ((result = vkCreateDevice(physical_devices[0], &createInfo,
nullptr /* allocationcallbacks */, &vkdevice)) != VK_SUCCESS)
return DRETF(false, "vkCreateDevice failed: %d", result);
vk_physical_device_ = physical_devices[0];
vk_device_ = vkdevice;
vkGetDeviceQueue(vkdevice, queue_family_index, 0, &vk_queue_);
return true;
}
bool VulkanTest::Exec()
{
VkResult result;
VkImageCreateInfo image_create_info = {
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
.pNext = nullptr,
.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT,
.imageType = VK_IMAGE_TYPE_2D,
.format = VK_FORMAT_R8G8B8A8_UNORM,
.extent = VkExtent3D{64, 64, 1},
.mipLevels = 1,
.arrayLayers = 1,
.samples = VK_SAMPLE_COUNT_1_BIT,
.tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SCANOUT_BIT_GOOGLE,
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
.queueFamilyIndexCount = 0, // not used since not sharing
.pQueueFamilyIndices = nullptr, // not used since not sharing
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
};
result = vkCreateImage(vk_device_, &image_create_info, nullptr, &vk_image_);
if (result != VK_SUCCESS)
return DRETF(false, "vkCreateImage failed: %d", result);
DLOG("scanout tiling image created");
vkDestroyImage(vk_device_, vk_image_, nullptr);
DLOG("scanout tiling image destroyed");
return true;
}
TEST(VulkanExtension, Scanout)
{
ASSERT_TRUE(VulkanTest::CheckExtensions());
VulkanTest test;
ASSERT_TRUE(test.Initialize());
ASSERT_TRUE(test.Exec());
}
} // namespace