280 lines
9.8 KiB
C
280 lines
9.8 KiB
C
/*
|
|
* Copyright 2020 Google LLC
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "vkr_instance.h"
|
|
|
|
#include "venus-protocol/vn_protocol_renderer_info.h"
|
|
#include "venus-protocol/vn_protocol_renderer_instance.h"
|
|
|
|
#include "vkr_context.h"
|
|
#include "vkr_physical_device.h"
|
|
|
|
static void
|
|
vkr_dispatch_vkEnumerateInstanceVersion(UNUSED struct vn_dispatch_context *dispatch,
|
|
struct vn_command_vkEnumerateInstanceVersion *args)
|
|
{
|
|
vn_replace_vkEnumerateInstanceVersion_args_handle(args);
|
|
args->ret = vkEnumerateInstanceVersion(args->pApiVersion);
|
|
}
|
|
|
|
static void
|
|
vkr_dispatch_vkEnumerateInstanceExtensionProperties(
|
|
UNUSED struct vn_dispatch_context *dispatch,
|
|
struct vn_command_vkEnumerateInstanceExtensionProperties *args)
|
|
{
|
|
VkExtensionProperties private_extensions[] = {
|
|
{
|
|
.extensionName = "VK_EXT_command_serialization",
|
|
},
|
|
{
|
|
.extensionName = "VK_MESA_venus_protocol",
|
|
},
|
|
};
|
|
|
|
if (!args->pProperties) {
|
|
*args->pPropertyCount = ARRAY_SIZE(private_extensions);
|
|
args->ret = VK_SUCCESS;
|
|
return;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < ARRAY_SIZE(private_extensions); i++) {
|
|
VkExtensionProperties *props = &private_extensions[i];
|
|
props->specVersion = vn_info_extension_spec_version(props->extensionName);
|
|
}
|
|
|
|
const uint32_t count = MIN2(*args->pPropertyCount, ARRAY_SIZE(private_extensions));
|
|
memcpy(args->pProperties, private_extensions, sizeof(*args->pProperties) * count);
|
|
*args->pPropertyCount = count;
|
|
args->ret = count == ARRAY_SIZE(private_extensions) ? VK_SUCCESS : VK_INCOMPLETE;
|
|
}
|
|
|
|
static VkBool32
|
|
vkr_validation_callback(UNUSED VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
|
|
UNUSED VkDebugUtilsMessageTypeFlagsEXT messageTypes,
|
|
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
|
|
void *pUserData)
|
|
{
|
|
struct vkr_context *ctx = pUserData;
|
|
|
|
vkr_log(pCallbackData->pMessage);
|
|
|
|
if (!ctx->validate_fatal)
|
|
return false;
|
|
|
|
vkr_cs_decoder_set_fatal(&ctx->decoder);
|
|
|
|
/* The spec says we "should" return false, because the meaning of true is
|
|
* layer-defined and is reserved for layer development. And we know that,
|
|
* for VK_LAYER_KHRONOS_validation, the return value indicates whether the
|
|
* call should be skipped. Let's do it for now and seek advices.
|
|
*/
|
|
return true;
|
|
}
|
|
|
|
static void
|
|
vkr_dispatch_vkCreateInstance(struct vn_dispatch_context *dispatch,
|
|
struct vn_command_vkCreateInstance *args)
|
|
{
|
|
struct vkr_context *ctx = dispatch->data;
|
|
|
|
if (ctx->instance) {
|
|
vkr_cs_decoder_set_fatal(&ctx->decoder);
|
|
return;
|
|
}
|
|
|
|
if (args->pCreateInfo->enabledLayerCount) {
|
|
args->ret = VK_ERROR_LAYER_NOT_PRESENT;
|
|
return;
|
|
}
|
|
|
|
if (args->pCreateInfo->enabledExtensionCount) {
|
|
args->ret = VK_ERROR_EXTENSION_NOT_PRESENT;
|
|
return;
|
|
}
|
|
|
|
uint32_t instance_version;
|
|
args->ret = vkEnumerateInstanceVersion(&instance_version);
|
|
if (args->ret != VK_SUCCESS)
|
|
return;
|
|
|
|
/* require Vulkan 1.1 */
|
|
if (instance_version < VK_API_VERSION_1_1) {
|
|
args->ret = VK_ERROR_INITIALIZATION_FAILED;
|
|
return;
|
|
}
|
|
|
|
VkInstanceCreateInfo *create_info = (VkInstanceCreateInfo *)args->pCreateInfo;
|
|
const char *layer_names[8];
|
|
const char *ext_names[8];
|
|
uint32_t layer_count = 0;
|
|
uint32_t ext_count = 0;
|
|
|
|
/* TODO enable more validation features */
|
|
const VkValidationFeatureDisableEXT validation_feature_disables_on[] = {
|
|
VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT,
|
|
VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT,
|
|
VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT,
|
|
VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT,
|
|
VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT,
|
|
};
|
|
/* we are single-threaded */
|
|
const VkValidationFeatureDisableEXT validation_feature_disables_full[] = {
|
|
VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT,
|
|
};
|
|
VkValidationFeaturesEXT validation_features;
|
|
VkDebugUtilsMessengerCreateInfoEXT messenger_create_info;
|
|
if (ctx->validate_level != VKR_CONTEXT_VALIDATE_NONE) {
|
|
/* let vkCreateInstance return VK_ERROR_LAYER_NOT_PRESENT or
|
|
* VK_ERROR_EXTENSION_NOT_PRESENT when the layer or extensions are
|
|
* missing
|
|
*/
|
|
layer_names[layer_count++] = "VK_LAYER_KHRONOS_validation";
|
|
ext_names[ext_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
|
|
ext_names[ext_count++] = VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME;
|
|
|
|
validation_features = (const VkValidationFeaturesEXT){
|
|
.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
|
|
.pNext = create_info->pNext,
|
|
};
|
|
if (ctx->validate_level == VKR_CONTEXT_VALIDATE_ON) {
|
|
validation_features.disabledValidationFeatureCount =
|
|
ARRAY_SIZE(validation_feature_disables_on);
|
|
validation_features.pDisabledValidationFeatures = validation_feature_disables_on;
|
|
} else {
|
|
validation_features.disabledValidationFeatureCount =
|
|
ARRAY_SIZE(validation_feature_disables_full);
|
|
validation_features.pDisabledValidationFeatures =
|
|
validation_feature_disables_full;
|
|
}
|
|
messenger_create_info = (VkDebugUtilsMessengerCreateInfoEXT){
|
|
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
|
|
.pNext = &validation_features,
|
|
.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
|
|
.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
|
|
.pfnUserCallback = vkr_validation_callback,
|
|
.pUserData = ctx,
|
|
};
|
|
|
|
create_info->pNext = &messenger_create_info;
|
|
}
|
|
|
|
assert(layer_count <= ARRAY_SIZE(layer_names));
|
|
create_info->enabledLayerCount = layer_count;
|
|
create_info->ppEnabledLayerNames = layer_names;
|
|
|
|
assert(ext_count <= ARRAY_SIZE(ext_names));
|
|
create_info->enabledExtensionCount = ext_count;
|
|
create_info->ppEnabledExtensionNames = ext_names;
|
|
|
|
/* patch apiVersion */
|
|
VkApplicationInfo app_info = {
|
|
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
|
.apiVersion = VK_API_VERSION_1_1,
|
|
};
|
|
if (create_info->pApplicationInfo) {
|
|
app_info = *create_info->pApplicationInfo;
|
|
if (app_info.apiVersion < VK_API_VERSION_1_1)
|
|
app_info.apiVersion = VK_API_VERSION_1_1;
|
|
}
|
|
create_info->pApplicationInfo = &app_info;
|
|
|
|
struct vkr_instance *instance = vkr_context_alloc_object(
|
|
ctx, sizeof(*instance), VK_OBJECT_TYPE_INSTANCE, args->pInstance);
|
|
if (!instance) {
|
|
args->ret = VK_ERROR_OUT_OF_HOST_MEMORY;
|
|
return;
|
|
}
|
|
|
|
instance->api_version = app_info.apiVersion;
|
|
|
|
vn_replace_vkCreateInstance_args_handle(args);
|
|
args->ret = vkCreateInstance(create_info, NULL, &instance->base.handle.instance);
|
|
if (args->ret != VK_SUCCESS) {
|
|
free(instance);
|
|
return;
|
|
}
|
|
|
|
instance->get_memory_fd = (PFN_vkGetMemoryFdKHR)vkGetInstanceProcAddr(
|
|
instance->base.handle.instance, "vkGetMemoryFdKHR");
|
|
instance->get_fence_fd = (PFN_vkGetFenceFdKHR)vkGetInstanceProcAddr(
|
|
instance->base.handle.instance, "vkGetFenceFdKHR");
|
|
|
|
if (ctx->validate_level != VKR_CONTEXT_VALIDATE_NONE) {
|
|
instance->create_debug_utils_messenger =
|
|
(PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
|
|
instance->base.handle.instance, "vkCreateDebugUtilsMessengerEXT");
|
|
instance->destroy_debug_utils_messenger =
|
|
(PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
|
|
instance->base.handle.instance, "vkDestroyDebugUtilsMessengerEXT");
|
|
|
|
messenger_create_info.pNext = NULL;
|
|
args->ret = instance->create_debug_utils_messenger(instance->base.handle.instance,
|
|
&messenger_create_info, NULL,
|
|
&instance->validation_messenger);
|
|
if (args->ret != VK_SUCCESS) {
|
|
vkDestroyInstance(instance->base.handle.instance, NULL);
|
|
free(instance);
|
|
return;
|
|
}
|
|
}
|
|
|
|
vkr_context_add_instance(ctx, instance, app_info.pApplicationName);
|
|
}
|
|
|
|
void
|
|
vkr_instance_destroy(struct vkr_context *ctx, struct vkr_instance *instance)
|
|
{
|
|
for (uint32_t i = 0; i < instance->physical_device_count; i++) {
|
|
struct vkr_physical_device *physical_dev = instance->physical_devices[i];
|
|
if (!physical_dev)
|
|
break;
|
|
|
|
vkr_physical_device_destroy(ctx, physical_dev);
|
|
}
|
|
|
|
if (ctx->validate_level != VKR_CONTEXT_VALIDATE_NONE) {
|
|
instance->destroy_debug_utils_messenger(instance->base.handle.instance,
|
|
instance->validation_messenger, NULL);
|
|
}
|
|
|
|
vkDestroyInstance(instance->base.handle.instance, NULL);
|
|
|
|
free(instance->physical_device_handles);
|
|
free(instance->physical_devices);
|
|
|
|
vkr_context_remove_instance(ctx, instance);
|
|
}
|
|
|
|
static void
|
|
vkr_dispatch_vkDestroyInstance(struct vn_dispatch_context *dispatch,
|
|
struct vn_command_vkDestroyInstance *args)
|
|
{
|
|
struct vkr_context *ctx = dispatch->data;
|
|
struct vkr_instance *instance = vkr_instance_from_handle(args->instance);
|
|
|
|
if (ctx->instance != instance) {
|
|
vkr_cs_decoder_set_fatal(&ctx->decoder);
|
|
return;
|
|
}
|
|
|
|
vkr_instance_destroy(ctx, instance);
|
|
}
|
|
|
|
void
|
|
vkr_context_init_instance_dispatch(struct vkr_context *ctx)
|
|
{
|
|
struct vn_dispatch_context *dispatch = &ctx->dispatch;
|
|
|
|
dispatch->dispatch_vkEnumerateInstanceVersion =
|
|
vkr_dispatch_vkEnumerateInstanceVersion;
|
|
dispatch->dispatch_vkEnumerateInstanceExtensionProperties =
|
|
vkr_dispatch_vkEnumerateInstanceExtensionProperties;
|
|
/* we don't advertise layers (and should never) */
|
|
dispatch->dispatch_vkEnumerateInstanceLayerProperties = NULL;
|
|
dispatch->dispatch_vkCreateInstance = vkr_dispatch_vkCreateInstance;
|
|
dispatch->dispatch_vkDestroyInstance = vkr_dispatch_vkDestroyInstance;
|
|
dispatch->dispatch_vkGetInstanceProcAddr = NULL;
|
|
}
|