• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 Google LLC
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "vkr_instance.h"
7 
8 #include "venus-protocol/vn_protocol_renderer_info.h"
9 #include "venus-protocol/vn_protocol_renderer_instance.h"
10 
11 #include "vkr_context.h"
12 #include "vkr_physical_device.h"
13 
14 static void
vkr_dispatch_vkEnumerateInstanceVersion(UNUSED struct vn_dispatch_context * dispatch,struct vn_command_vkEnumerateInstanceVersion * args)15 vkr_dispatch_vkEnumerateInstanceVersion(UNUSED struct vn_dispatch_context *dispatch,
16                                         struct vn_command_vkEnumerateInstanceVersion *args)
17 {
18    vn_replace_vkEnumerateInstanceVersion_args_handle(args);
19    args->ret = vkEnumerateInstanceVersion(args->pApiVersion);
20 }
21 
22 static void
vkr_dispatch_vkEnumerateInstanceExtensionProperties(UNUSED struct vn_dispatch_context * dispatch,struct vn_command_vkEnumerateInstanceExtensionProperties * args)23 vkr_dispatch_vkEnumerateInstanceExtensionProperties(
24    UNUSED struct vn_dispatch_context *dispatch,
25    struct vn_command_vkEnumerateInstanceExtensionProperties *args)
26 {
27    VkExtensionProperties private_extensions[] = {
28       {
29          .extensionName = "VK_EXT_command_serialization",
30       },
31       {
32          .extensionName = "VK_MESA_venus_protocol",
33       },
34    };
35 
36    if (!args->pProperties) {
37       *args->pPropertyCount = ARRAY_SIZE(private_extensions);
38       args->ret = VK_SUCCESS;
39       return;
40    }
41 
42    for (uint32_t i = 0; i < ARRAY_SIZE(private_extensions); i++) {
43       VkExtensionProperties *props = &private_extensions[i];
44       props->specVersion = vn_info_extension_spec_version(props->extensionName);
45    }
46 
47    const uint32_t count = MIN2(*args->pPropertyCount, ARRAY_SIZE(private_extensions));
48    memcpy(args->pProperties, private_extensions, sizeof(*args->pProperties) * count);
49    *args->pPropertyCount = count;
50    args->ret = count == ARRAY_SIZE(private_extensions) ? VK_SUCCESS : VK_INCOMPLETE;
51 }
52 
53 static VkBool32
vkr_validation_callback(UNUSED VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,UNUSED VkDebugUtilsMessageTypeFlagsEXT messageTypes,const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData,void * pUserData)54 vkr_validation_callback(UNUSED VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
55                         UNUSED VkDebugUtilsMessageTypeFlagsEXT messageTypes,
56                         const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
57                         void *pUserData)
58 {
59    struct vkr_context *ctx = pUserData;
60 
61    vkr_log(pCallbackData->pMessage);
62 
63    if (!ctx->validate_fatal)
64       return false;
65 
66    vkr_cs_decoder_set_fatal(&ctx->decoder);
67 
68    /* The spec says we "should" return false, because the meaning of true is
69     * layer-defined and is reserved for layer development.  And we know that,
70     * for VK_LAYER_KHRONOS_validation, the return value indicates whether the
71     * call should be skipped.  Let's do it for now and seek advices.
72     */
73    return true;
74 }
75 
76 static void
vkr_dispatch_vkCreateInstance(struct vn_dispatch_context * dispatch,struct vn_command_vkCreateInstance * args)77 vkr_dispatch_vkCreateInstance(struct vn_dispatch_context *dispatch,
78                               struct vn_command_vkCreateInstance *args)
79 {
80    struct vkr_context *ctx = dispatch->data;
81 
82    if (ctx->instance) {
83       vkr_cs_decoder_set_fatal(&ctx->decoder);
84       return;
85    }
86 
87    if (args->pCreateInfo->enabledLayerCount) {
88       args->ret = VK_ERROR_LAYER_NOT_PRESENT;
89       return;
90    }
91 
92    if (args->pCreateInfo->enabledExtensionCount) {
93       args->ret = VK_ERROR_EXTENSION_NOT_PRESENT;
94       return;
95    }
96 
97    uint32_t instance_version;
98    args->ret = vkEnumerateInstanceVersion(&instance_version);
99    if (args->ret != VK_SUCCESS)
100       return;
101 
102    /* require Vulkan 1.1 */
103    if (instance_version < VK_API_VERSION_1_1) {
104       args->ret = VK_ERROR_INITIALIZATION_FAILED;
105       return;
106    }
107 
108    VkInstanceCreateInfo *create_info = (VkInstanceCreateInfo *)args->pCreateInfo;
109    const char *layer_names[8];
110    const char *ext_names[8];
111    uint32_t layer_count = 0;
112    uint32_t ext_count = 0;
113 
114    /* TODO enable more validation features */
115    const VkValidationFeatureDisableEXT validation_feature_disables_on[] = {
116       VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT,
117       VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT,
118       VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT,
119       VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT,
120       VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT,
121    };
122    /* we are single-threaded */
123    const VkValidationFeatureDisableEXT validation_feature_disables_full[] = {
124       VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT,
125    };
126    VkValidationFeaturesEXT validation_features;
127    VkDebugUtilsMessengerCreateInfoEXT messenger_create_info;
128    if (ctx->validate_level != VKR_CONTEXT_VALIDATE_NONE) {
129       /* let vkCreateInstance return VK_ERROR_LAYER_NOT_PRESENT or
130        * VK_ERROR_EXTENSION_NOT_PRESENT when the layer or extensions are
131        * missing
132        */
133       layer_names[layer_count++] = "VK_LAYER_KHRONOS_validation";
134       ext_names[ext_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
135       ext_names[ext_count++] = VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME;
136 
137       validation_features = (const VkValidationFeaturesEXT){
138          .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
139          .pNext = create_info->pNext,
140       };
141       if (ctx->validate_level == VKR_CONTEXT_VALIDATE_ON) {
142          validation_features.disabledValidationFeatureCount =
143             ARRAY_SIZE(validation_feature_disables_on);
144          validation_features.pDisabledValidationFeatures = validation_feature_disables_on;
145       } else {
146          validation_features.disabledValidationFeatureCount =
147             ARRAY_SIZE(validation_feature_disables_full);
148          validation_features.pDisabledValidationFeatures =
149             validation_feature_disables_full;
150       }
151       messenger_create_info = (VkDebugUtilsMessengerCreateInfoEXT){
152          .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
153          .pNext = &validation_features,
154          .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
155          .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
156          .pfnUserCallback = vkr_validation_callback,
157          .pUserData = ctx,
158       };
159 
160       create_info->pNext = &messenger_create_info;
161    }
162 
163    assert(layer_count <= ARRAY_SIZE(layer_names));
164    create_info->enabledLayerCount = layer_count;
165    create_info->ppEnabledLayerNames = layer_names;
166 
167    assert(ext_count <= ARRAY_SIZE(ext_names));
168    create_info->enabledExtensionCount = ext_count;
169    create_info->ppEnabledExtensionNames = ext_names;
170 
171    /* patch apiVersion */
172    VkApplicationInfo app_info = {
173       .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
174       .apiVersion = VK_API_VERSION_1_1,
175    };
176    if (create_info->pApplicationInfo) {
177       app_info = *create_info->pApplicationInfo;
178       if (app_info.apiVersion < VK_API_VERSION_1_1)
179          app_info.apiVersion = VK_API_VERSION_1_1;
180    }
181    create_info->pApplicationInfo = &app_info;
182 
183    struct vkr_instance *instance = vkr_context_alloc_object(
184       ctx, sizeof(*instance), VK_OBJECT_TYPE_INSTANCE, args->pInstance);
185    if (!instance) {
186       args->ret = VK_ERROR_OUT_OF_HOST_MEMORY;
187       return;
188    }
189 
190    instance->api_version = app_info.apiVersion;
191 
192    vn_replace_vkCreateInstance_args_handle(args);
193    args->ret = vkCreateInstance(create_info, NULL, &instance->base.handle.instance);
194    if (args->ret != VK_SUCCESS) {
195       free(instance);
196       return;
197    }
198 
199    instance->get_memory_fd = (PFN_vkGetMemoryFdKHR)vkGetInstanceProcAddr(
200       instance->base.handle.instance, "vkGetMemoryFdKHR");
201    instance->get_fence_fd = (PFN_vkGetFenceFdKHR)vkGetInstanceProcAddr(
202       instance->base.handle.instance, "vkGetFenceFdKHR");
203 
204    if (ctx->validate_level != VKR_CONTEXT_VALIDATE_NONE) {
205       instance->create_debug_utils_messenger =
206          (PFN_vkCreateDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
207             instance->base.handle.instance, "vkCreateDebugUtilsMessengerEXT");
208       instance->destroy_debug_utils_messenger =
209          (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(
210             instance->base.handle.instance, "vkDestroyDebugUtilsMessengerEXT");
211 
212       messenger_create_info.pNext = NULL;
213       args->ret = instance->create_debug_utils_messenger(instance->base.handle.instance,
214                                                          &messenger_create_info, NULL,
215                                                          &instance->validation_messenger);
216       if (args->ret != VK_SUCCESS) {
217          vkDestroyInstance(instance->base.handle.instance, NULL);
218          free(instance);
219          return;
220       }
221    }
222 
223    vkr_context_add_instance(ctx, instance, app_info.pApplicationName);
224 }
225 
226 void
vkr_instance_destroy(struct vkr_context * ctx,struct vkr_instance * instance)227 vkr_instance_destroy(struct vkr_context *ctx, struct vkr_instance *instance)
228 {
229    for (uint32_t i = 0; i < instance->physical_device_count; i++) {
230       struct vkr_physical_device *physical_dev = instance->physical_devices[i];
231       if (!physical_dev)
232          break;
233 
234       vkr_physical_device_destroy(ctx, physical_dev);
235    }
236 
237    if (ctx->validate_level != VKR_CONTEXT_VALIDATE_NONE) {
238       instance->destroy_debug_utils_messenger(instance->base.handle.instance,
239                                               instance->validation_messenger, NULL);
240    }
241 
242    vkDestroyInstance(instance->base.handle.instance, NULL);
243 
244    free(instance->physical_device_handles);
245    free(instance->physical_devices);
246 
247    vkr_context_remove_instance(ctx, instance);
248 }
249 
250 static void
vkr_dispatch_vkDestroyInstance(struct vn_dispatch_context * dispatch,struct vn_command_vkDestroyInstance * args)251 vkr_dispatch_vkDestroyInstance(struct vn_dispatch_context *dispatch,
252                                struct vn_command_vkDestroyInstance *args)
253 {
254    struct vkr_context *ctx = dispatch->data;
255    struct vkr_instance *instance = vkr_instance_from_handle(args->instance);
256 
257    if (ctx->instance != instance) {
258       vkr_cs_decoder_set_fatal(&ctx->decoder);
259       return;
260    }
261 
262    vkr_instance_destroy(ctx, instance);
263 }
264 
265 void
vkr_context_init_instance_dispatch(struct vkr_context * ctx)266 vkr_context_init_instance_dispatch(struct vkr_context *ctx)
267 {
268    struct vn_dispatch_context *dispatch = &ctx->dispatch;
269 
270    dispatch->dispatch_vkEnumerateInstanceVersion =
271       vkr_dispatch_vkEnumerateInstanceVersion;
272    dispatch->dispatch_vkEnumerateInstanceExtensionProperties =
273       vkr_dispatch_vkEnumerateInstanceExtensionProperties;
274    /* we don't advertise layers (and should never) */
275    dispatch->dispatch_vkEnumerateInstanceLayerProperties = NULL;
276    dispatch->dispatch_vkCreateInstance = vkr_dispatch_vkCreateInstance;
277    dispatch->dispatch_vkDestroyInstance = vkr_dispatch_vkDestroyInstance;
278    dispatch->dispatch_vkGetInstanceProcAddr = NULL;
279 }
280