blob: 81b3e6d225c3c72802f52e4d71b0422acf44fe42 [file] [log] [blame]
/*
* vk_instance.cpp - vulkan instance
*
* Copyright (c) 2018 Intel Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Author: Wind Yuan <[email protected]>
*/
#include "vk_instance.h"
#include "vulkan_common.h"
#define APP_NAME "xcam"
#define ENGINE_NAME "xcam"
#define XCAM_INVALID_VK_QUEUE_IDX UINT32_MAX
namespace XCam {
extern void vk_init_error_string ();
SmartPtr<VKInstance> VKInstance::_instance;
Mutex VKInstance::_instance_mutex;
VKInstance::~VKInstance ()
{
if (XCAM_IS_VALID_VK_ID (_instance_id))
vkDestroyInstance (_instance_id, _allocator.ptr ());
}
VKInstance::VKInstance (VkInstance id, VkAllocationCallbacks *allocator)
: _instance_id (id)
, _allocator (allocator)
, _physical_device (NULL)
, _compute_queue_family_idx (XCAM_INVALID_VK_QUEUE_IDX)
, _graphics_queue_family_idx (XCAM_INVALID_VK_QUEUE_IDX)
{
XCAM_ASSERT (XCAM_IS_VALID_VK_ID (id));
xcam_mem_clear (_device_properties);
xcam_mem_clear (_dev_mem_properties);
}
SmartPtr<VKInstance>
VKInstance::get_instance ()
{
SmartLock locker (_instance_mutex);
if (!_instance.ptr ()) {
vk_init_error_string ();
_instance = create_instance ();
}
return _instance;
}
SmartPtr<VKInstance>
VKInstance::create_instance ()
{
VkApplicationInfo app_info = {};
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
app_info.pApplicationName = APP_NAME;
app_info.applicationVersion = 0;
app_info.pEngineName = ENGINE_NAME;
app_info.engineVersion = xcam_version ();
app_info.apiVersion = VK_API_VERSION_1_0;
VkInstance id;
VkInstanceCreateInfo inst_create_info = {};
inst_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
inst_create_info.pApplicationInfo = &app_info;
inst_create_info.enabledExtensionCount = 0; // TODO, add extensions
XCAM_VK_CHECK_RETURN(
ERROR, vkCreateInstance (&inst_create_info, NULL, &id),
NULL, "create vk instance failed");
XCAM_ASSERT (XCAM_IS_VALID_VK_ID (id));
SmartPtr<VKInstance> vk_instance = new VKInstance (id, NULL);
XCAM_FAIL_RETURN (
ERROR, xcam_ret_is_ok (vk_instance->query_physical_info ()), NULL,
"vk instance query physical info failed");
XCAM_FAIL_RETURN (
ERROR, xcam_ret_is_ok (vk_instance->query_queue_info ()), NULL,
"vk instance query queue info failed");
return vk_instance;
}
static const char *s_device_types[] = {
"OTHER_DEVICE",
"INTEGRATED_GPU",
"DISCRETE_GPU",
"VIRTUAL_GPU",
"CPU_TYPE",
};
static const char*
device_type_to_str(VkPhysicalDeviceType type)
{
size_t number = sizeof (s_device_types) / sizeof (s_device_types[0]);
assert (number == 5);
if ((size_t)type < number)
return s_device_types [type];
return "UNKNOWN_TYPE";
}
XCamReturn
VKInstance::query_physical_info ()
{
#define MAX_DEV_NUM 256
VkPhysicalDevice devs[MAX_DEV_NUM];
uint32_t dev_num = 0;
XCAM_VK_CHECK_RETURN (
ERROR, vkEnumeratePhysicalDevices (_instance_id, &dev_num, NULL),
XCAM_RETURN_ERROR_VULKAN, "enum vk physical devices failed");
XCAM_FAIL_RETURN (
ERROR, dev_num, XCAM_RETURN_ERROR_VULKAN,
"There is NO vk physical devices");
dev_num = XCAM_MIN (dev_num, MAX_DEV_NUM);
vkEnumeratePhysicalDevices (_instance_id, &dev_num, devs);
VkPhysicalDevice gpu_dev[VK_PHYSICAL_DEVICE_TYPE_RANGE_SIZE] = {};
VkPhysicalDeviceProperties dev_prop;
for (uint32_t i = 0; i < dev_num; ++i) {
vkGetPhysicalDeviceProperties (devs[i], &dev_prop);
if (dev_prop.deviceType < VK_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE ||
dev_prop.deviceType > VK_PHYSICAL_DEVICE_TYPE_END_RANGE) {
continue;
}
if (gpu_dev[dev_prop.deviceType]) {
XCAM_LOG_WARNING (
"double vk physical dev, type:%d, name:%s",
dev_prop.deviceType, dev_prop.deviceName);
continue;
}
gpu_dev[dev_prop.deviceType] = devs[i];
#if 0
printf ("found vk physical dev_id:%d, name:%s, type:%d, API:%d\n",
dev_prop.deviceID, dev_prop.deviceName,
device_type_to_str (dev_prop.deviceType), dev_prop.apiVersion);
#endif
}
if (gpu_dev[VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU])
_physical_device = gpu_dev[VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU];
else if (gpu_dev[VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU])
_physical_device = gpu_dev[VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU];
else if (gpu_dev[VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU])
_physical_device = gpu_dev[VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU];
else if (gpu_dev[VK_PHYSICAL_DEVICE_TYPE_CPU]) {
_physical_device = gpu_dev[VK_PHYSICAL_DEVICE_TYPE_CPU];
XCAM_LOG_WARNING ("vk device select physical CPU, performance may slow down");
} else {
XCAM_LOG_ERROR ("did NOT find available vk physical device");
return XCAM_RETURN_ERROR_VULKAN;
}
vkGetPhysicalDeviceProperties (_physical_device, &dev_prop);
XCAM_LOG_INFO ("choose vk physical dev properties dev_id:%d, name:%s, type:%s, API:%d\n",
dev_prop.deviceID, dev_prop.deviceName,
device_type_to_str (dev_prop.deviceType), dev_prop.apiVersion);
_device_properties = dev_prop;
vkGetPhysicalDeviceMemoryProperties (_physical_device, &_dev_mem_properties);
return XCAM_RETURN_NO_ERROR;
}
XCamReturn
VKInstance::query_queue_info ()
{
XCAM_ASSERT (_physical_device);
// get queue family porperties
uint32_t queue_count = 0;
#define MAX_QUEUE_FAMILY_NUM 256
VkQueueFamilyProperties queue_family[MAX_QUEUE_FAMILY_NUM];
vkGetPhysicalDeviceQueueFamilyProperties (
_physical_device, &queue_count, NULL);
XCAM_FAIL_RETURN (
ERROR, queue_count, XCAM_RETURN_ERROR_VULKAN,
"There is NO vk physical devices");
if (queue_count > MAX_QUEUE_FAMILY_NUM)
queue_count = MAX_QUEUE_FAMILY_NUM;
vkGetPhysicalDeviceQueueFamilyProperties (
_physical_device, &queue_count, queue_family);
for (uint32_t i = 0; i < queue_count; ++i) {
if (queue_family[i].queueFlags & VK_QUEUE_COMPUTE_BIT) {
_compute_queue_family_idx = i;
}
if (queue_family[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
_graphics_queue_family_idx = i;
}
}
XCAM_FAIL_RETURN (
ERROR,
_compute_queue_family_idx != XCAM_INVALID_VK_QUEUE_IDX &&
_graphics_queue_family_idx != XCAM_INVALID_VK_QUEUE_IDX,
XCAM_RETURN_ERROR_VULKAN,
"There is NO vk compute/graphics queue family");
return XCAM_RETURN_NO_ERROR;
}
uint32_t
VKInstance::get_mem_type_index (VkMemoryPropertyFlags prop) const
{
for (uint32_t i = 0; i < _dev_mem_properties.memoryTypeCount; ++i) {
if (((uint32_t)(_dev_mem_properties.memoryTypes[i].propertyFlags) & prop) == prop)
return i;
}
return (uint32_t)(-1);
}
}