xref: /aosp_15_r20/external/virglrenderer/src/venus/vkr_instance.c (revision bbecb9d118dfdb95f99bd754f8fa9be01f189df3)
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_instance.h"
9 
10 #include "vkr_context.h"
11 #include "vkr_physical_device.h"
12 
13 static void
vkr_dispatch_vkEnumerateInstanceVersion(UNUSED struct vn_dispatch_context * dispatch,struct vn_command_vkEnumerateInstanceVersion * args)14 vkr_dispatch_vkEnumerateInstanceVersion(UNUSED struct vn_dispatch_context *dispatch,
15                                         struct vn_command_vkEnumerateInstanceVersion *args)
16 {
17    vn_replace_vkEnumerateInstanceVersion_args_handle(args);
18 
19    uint32_t version = 0;
20    args->ret = vkEnumerateInstanceVersion(&version);
21    if (args->ret == VK_SUCCESS)
22       version = vkr_api_version_cap_minor(version, VKR_MAX_API_VERSION);
23 
24    *args->pApiVersion = version;
25 }
26 
27 static void
vkr_dispatch_vkEnumerateInstanceExtensionProperties(UNUSED struct vn_dispatch_context * dispatch,struct vn_command_vkEnumerateInstanceExtensionProperties * args)28 vkr_dispatch_vkEnumerateInstanceExtensionProperties(
29    UNUSED struct vn_dispatch_context *dispatch,
30    struct vn_command_vkEnumerateInstanceExtensionProperties *args)
31 {
32    VkExtensionProperties private_extensions[] = {
33       {
34          .extensionName = "VK_EXT_command_serialization",
35       },
36       {
37          .extensionName = "VK_MESA_venus_protocol",
38       },
39    };
40 
41    if (!args->pProperties) {
42       *args->pPropertyCount = ARRAY_SIZE(private_extensions);
43       args->ret = VK_SUCCESS;
44       return;
45    }
46 
47    for (uint32_t i = 0; i < ARRAY_SIZE(private_extensions); i++) {
48       VkExtensionProperties *props = &private_extensions[i];
49       props->specVersion = vkr_extension_get_spec_version(props->extensionName);
50    }
51 
52    const uint32_t count = MIN2(*args->pPropertyCount, ARRAY_SIZE(private_extensions));
53    memcpy(args->pProperties, private_extensions, sizeof(*args->pProperties) * count);
54    *args->pPropertyCount = count;
55    args->ret = count == ARRAY_SIZE(private_extensions) ? VK_SUCCESS : VK_INCOMPLETE;
56 }
57 
58 static VkBool32
vkr_validation_callback(UNUSED VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,UNUSED VkDebugUtilsMessageTypeFlagsEXT messageTypes,const VkDebugUtilsMessengerCallbackDataEXT * pCallbackData,void * pUserData)59 vkr_validation_callback(UNUSED VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
60                         UNUSED VkDebugUtilsMessageTypeFlagsEXT messageTypes,
61                         const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData,
62                         void *pUserData)
63 {
64    struct vkr_context *ctx = pUserData;
65 
66    vkr_log(pCallbackData->pMessage);
67 
68    if (!ctx->validate_fatal)
69       return false;
70 
71    vkr_cs_decoder_set_fatal(&ctx->decoder);
72 
73    /* The spec says we "should" return false, because the meaning of true is
74     * layer-defined and is reserved for layer development.  And we know that,
75     * for VK_LAYER_KHRONOS_validation, the return value indicates whether the
76     * call should be skipped.  Let's do it for now and seek advices.
77     */
78    return true;
79 }
80 
81 static void
vkr_dispatch_vkCreateInstance(struct vn_dispatch_context * dispatch,struct vn_command_vkCreateInstance * args)82 vkr_dispatch_vkCreateInstance(struct vn_dispatch_context *dispatch,
83                               struct vn_command_vkCreateInstance *args)
84 {
85    struct vkr_context *ctx = dispatch->data;
86 
87    if (ctx->instance) {
88       vkr_cs_decoder_set_fatal(&ctx->decoder);
89       return;
90    }
91 
92    if (args->pCreateInfo->enabledLayerCount) {
93       args->ret = VK_ERROR_LAYER_NOT_PRESENT;
94       return;
95    }
96 
97    if (args->pCreateInfo->enabledExtensionCount) {
98       args->ret = VK_ERROR_EXTENSION_NOT_PRESENT;
99       return;
100    }
101 
102    uint32_t instance_version;
103    args->ret = vkEnumerateInstanceVersion(&instance_version);
104    if (args->ret != VK_SUCCESS)
105       return;
106 
107    /* require Vulkan 1.1 */
108    if (instance_version < VK_API_VERSION_1_1) {
109       args->ret = VK_ERROR_INITIALIZATION_FAILED;
110       return;
111    }
112 
113    VkInstanceCreateInfo *create_info = (VkInstanceCreateInfo *)args->pCreateInfo;
114    const char *layer_names[8];
115    const char *ext_names[8];
116    uint32_t layer_count = 0;
117    uint32_t ext_count = 0;
118 
119    /* TODO enable more validation features */
120    const VkValidationFeatureDisableEXT validation_feature_disables_on[] = {
121       VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT,
122       VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT,
123       VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT,
124       VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT,
125       VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT,
126    };
127    /* we are single-threaded */
128    const VkValidationFeatureDisableEXT validation_feature_disables_full[] = {
129       VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT,
130    };
131    VkValidationFeaturesEXT validation_features;
132    VkDebugUtilsMessengerCreateInfoEXT messenger_create_info;
133    if (ctx->validate_level != VKR_CONTEXT_VALIDATE_NONE) {
134       /* let vkCreateInstance return VK_ERROR_LAYER_NOT_PRESENT or
135        * VK_ERROR_EXTENSION_NOT_PRESENT when the layer or extensions are
136        * missing
137        */
138       layer_names[layer_count++] = "VK_LAYER_KHRONOS_validation";
139       ext_names[ext_count++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
140       ext_names[ext_count++] = VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME;
141 
142       validation_features = (const VkValidationFeaturesEXT){
143          .sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
144          .pNext = create_info->pNext,
145       };
146       if (ctx->validate_level == VKR_CONTEXT_VALIDATE_ON) {
147          validation_features.disabledValidationFeatureCount =
148             ARRAY_SIZE(validation_feature_disables_on);
149          validation_features.pDisabledValidationFeatures = validation_feature_disables_on;
150       } else {
151          validation_features.disabledValidationFeatureCount =
152             ARRAY_SIZE(validation_feature_disables_full);
153          validation_features.pDisabledValidationFeatures =
154             validation_feature_disables_full;
155       }
156       messenger_create_info = (VkDebugUtilsMessengerCreateInfoEXT){
157          .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT,
158          .pNext = &validation_features,
159          .messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
160          .messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT,
161          .pfnUserCallback = vkr_validation_callback,
162          .pUserData = ctx,
163       };
164 
165       create_info->pNext = &messenger_create_info;
166    }
167 
168    assert(layer_count <= ARRAY_SIZE(layer_names));
169    create_info->enabledLayerCount = layer_count;
170    create_info->ppEnabledLayerNames = layer_names;
171 
172    assert(ext_count <= ARRAY_SIZE(ext_names));
173    create_info->enabledExtensionCount = ext_count;
174    create_info->ppEnabledExtensionNames = ext_names;
175 
176    /* patch apiVersion */
177    VkApplicationInfo app_info = {
178       .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
179       .apiVersion = VK_API_VERSION_1_1,
180    };
181    if (create_info->pApplicationInfo) {
182       app_info = *create_info->pApplicationInfo;
183       if (app_info.apiVersion < VK_API_VERSION_1_1)
184          app_info.apiVersion = VK_API_VERSION_1_1;
185    }
186    create_info->pApplicationInfo = &app_info;
187 
188    struct vkr_instance *instance = vkr_context_alloc_object(
189       ctx, sizeof(*instance), VK_OBJECT_TYPE_INSTANCE, args->pInstance);
190    if (!instance) {
191       args->ret = VK_ERROR_OUT_OF_HOST_MEMORY;
192       return;
193    }
194 
195    instance->api_version = app_info.apiVersion;
196 
197    vn_replace_vkCreateInstance_args_handle(args);
198    args->ret = vkCreateInstance(create_info, NULL, &instance->base.handle.instance);
199    if (args->ret != VK_SUCCESS) {
200       free(instance);
201       return;
202    }
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