xref: /aosp_15_r20/external/mesa3d/src/panfrost/vulkan/panvk_instance.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2021 Collabora Ltd.
3  *
4  * Derived from tu_device.c which is:
5  * Copyright © 2016 Red Hat.
6  * Copyright © 2016 Bas Nieuwenhuizen
7  * Copyright © 2015 Intel Corporation
8  *
9  * SPDX-License-Identifier: MIT
10  */
11 
12 #include "util/build_id.h"
13 #include "util/mesa-sha1.h"
14 
15 #include "vk_alloc.h"
16 #include "vk_log.h"
17 
18 #include "panvk_entrypoints.h"
19 #include "panvk_instance.h"
20 #include "panvk_physical_device.h"
21 
22 #ifdef HAVE_VALGRIND
23 #include <memcheck.h>
24 #include <valgrind.h>
25 #define VG(x) x
26 #else
27 #define VG(x)
28 #endif
29 
30 static const struct debug_control panvk_debug_options[] = {
31    {"startup", PANVK_DEBUG_STARTUP},
32    {"nir", PANVK_DEBUG_NIR},
33    {"trace", PANVK_DEBUG_TRACE},
34    {"sync", PANVK_DEBUG_SYNC},
35    {"afbc", PANVK_DEBUG_AFBC},
36    {"linear", PANVK_DEBUG_LINEAR},
37    {"dump", PANVK_DEBUG_DUMP},
38    {"no_known_warn", PANVK_DEBUG_NO_KNOWN_WARN},
39    {"cs", PANVK_DEBUG_CS},
40    {NULL, 0}};
41 
42 VKAPI_ATTR VkResult VKAPI_CALL
panvk_EnumerateInstanceVersion(uint32_t * pApiVersion)43 panvk_EnumerateInstanceVersion(uint32_t *pApiVersion)
44 {
45    *pApiVersion = panvk_get_vk_version();
46    return VK_SUCCESS;
47 }
48 
49 static const struct vk_instance_extension_table panvk_instance_extensions = {
50    .KHR_device_group_creation = true,
51    .KHR_get_physical_device_properties2 = true,
52 #ifdef PANVK_USE_WSI_PLATFORM
53    .KHR_surface = true,
54 #endif
55 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
56    .KHR_wayland_surface = true,
57 #endif
58 #ifdef VK_USE_PLATFORM_XCB_KHR
59    .KHR_xcb_surface = true,
60 #endif
61 #ifdef VK_USE_PLATFORM_XLIB_KHR
62    .KHR_xlib_surface = true,
63 #endif
64 #ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
65    .EXT_acquire_xlib_display = true,
66 #endif
67    .EXT_debug_report = true,
68    .EXT_debug_utils = true,
69 #ifndef VK_USE_PLATFORM_WIN32_KHR
70    .EXT_headless_surface = true,
71 #endif
72 };
73 
74 static VkResult
panvk_physical_device_try_create(struct vk_instance * vk_instance,struct _drmDevice * drm_device,struct vk_physical_device ** out)75 panvk_physical_device_try_create(struct vk_instance *vk_instance,
76                                  struct _drmDevice *drm_device,
77                                  struct vk_physical_device **out)
78 {
79    struct panvk_instance *instance =
80       container_of(vk_instance, struct panvk_instance, vk);
81 
82    if (!(drm_device->available_nodes & (1 << DRM_NODE_RENDER)) ||
83        drm_device->bustype != DRM_BUS_PLATFORM)
84       return VK_ERROR_INCOMPATIBLE_DRIVER;
85 
86    struct panvk_physical_device *device =
87       vk_zalloc(&instance->vk.alloc, sizeof(*device), 8,
88                 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
89    if (!device)
90       return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
91 
92    VkResult result = panvk_physical_device_init(device, instance, drm_device);
93    if (result != VK_SUCCESS) {
94       vk_free(&instance->vk.alloc, device);
95       return result;
96    }
97 
98    *out = &device->vk;
99    return VK_SUCCESS;
100 }
101 
102 static void
panvk_destroy_physical_device(struct vk_physical_device * device)103 panvk_destroy_physical_device(struct vk_physical_device *device)
104 {
105    panvk_physical_device_finish((struct panvk_physical_device *)device);
106    vk_free(&device->instance->alloc, device);
107 }
108 
109 static void *
panvk_kmod_zalloc(const struct pan_kmod_allocator * allocator,size_t size,bool transient)110 panvk_kmod_zalloc(const struct pan_kmod_allocator *allocator, size_t size,
111                   bool transient)
112 {
113    const VkAllocationCallbacks *vkalloc = allocator->priv;
114 
115    void *obj = vk_zalloc(vkalloc, size, 8,
116                          transient ? VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
117                                    : VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
118 
119    /* We force errno to -ENOMEM on host allocation failures so we can properly
120     * report it back as VK_ERROR_OUT_OF_HOST_MEMORY. */
121    errno = obj ? 0 : -ENOMEM;
122 
123    return obj;
124 }
125 
126 static void
panvk_kmod_free(const struct pan_kmod_allocator * allocator,void * data)127 panvk_kmod_free(const struct pan_kmod_allocator *allocator, void *data)
128 {
129    const VkAllocationCallbacks *vkalloc = allocator->priv;
130 
131    return vk_free(vkalloc, data);
132 }
133 
134 VKAPI_ATTR VkResult VKAPI_CALL
panvk_CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)135 panvk_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
136                      const VkAllocationCallbacks *pAllocator,
137                      VkInstance *pInstance)
138 {
139    struct panvk_instance *instance;
140    VkResult result;
141 
142    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
143 
144    const struct build_id_note *note =
145       build_id_find_nhdr_for_addr(panvk_CreateInstance);
146    if (!note) {
147       return vk_errorf(NULL, VK_ERROR_INITIALIZATION_FAILED,
148                        "Failed to find build-id");
149    }
150 
151    unsigned build_id_len = build_id_length(note);
152    if (build_id_len < SHA1_DIGEST_LENGTH) {
153       return vk_errorf(NULL, VK_ERROR_INITIALIZATION_FAILED,
154                        "build-id too short.  It needs to be a SHA");
155    }
156 
157    pAllocator = pAllocator ?: vk_default_allocator();
158    instance = vk_zalloc(pAllocator, sizeof(*instance), 8,
159                         VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
160    if (!instance)
161       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
162 
163    struct vk_instance_dispatch_table dispatch_table;
164 
165    vk_instance_dispatch_table_from_entrypoints(
166       &dispatch_table, &panvk_instance_entrypoints, true);
167    vk_instance_dispatch_table_from_entrypoints(
168       &dispatch_table, &wsi_instance_entrypoints, false);
169    result = vk_instance_init(&instance->vk, &panvk_instance_extensions,
170                              &dispatch_table, pCreateInfo, pAllocator);
171    if (result != VK_SUCCESS) {
172       vk_free(pAllocator, instance);
173       return vk_error(NULL, result);
174    }
175 
176    instance->kmod.allocator = (struct pan_kmod_allocator){
177       .zalloc = panvk_kmod_zalloc,
178       .free = panvk_kmod_free,
179       .priv = &instance->vk.alloc,
180    };
181 
182    instance->vk.physical_devices.try_create_for_drm =
183       panvk_physical_device_try_create;
184    instance->vk.physical_devices.destroy = panvk_destroy_physical_device;
185 
186    instance->debug_flags =
187       parse_debug_string(getenv("PANVK_DEBUG"), panvk_debug_options);
188 
189    if (instance->debug_flags & PANVK_DEBUG_STARTUP)
190       vk_logi(VK_LOG_NO_OBJS(instance), "Created an instance");
191 
192    VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
193 
194    STATIC_ASSERT(sizeof(instance->driver_build_sha) == SHA1_DIGEST_LENGTH);
195    memcpy(instance->driver_build_sha, build_id_data(note), SHA1_DIGEST_LENGTH);
196 
197    *pInstance = panvk_instance_to_handle(instance);
198 
199    return VK_SUCCESS;
200 }
201 
202 VKAPI_ATTR void VKAPI_CALL
panvk_DestroyInstance(VkInstance _instance,const VkAllocationCallbacks * pAllocator)203 panvk_DestroyInstance(VkInstance _instance,
204                       const VkAllocationCallbacks *pAllocator)
205 {
206    VK_FROM_HANDLE(panvk_instance, instance, _instance);
207 
208    if (!instance)
209       return;
210 
211    vk_instance_finish(&instance->vk);
212    vk_free(&instance->vk.alloc, instance);
213 }
214 
215 VKAPI_ATTR VkResult VKAPI_CALL
panvk_EnumerateInstanceLayerProperties(uint32_t * pPropertyCount,VkLayerProperties * pProperties)216 panvk_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
217                                        VkLayerProperties *pProperties)
218 {
219    *pPropertyCount = 0;
220    return VK_SUCCESS;
221 }
222 
223 VKAPI_ATTR VkResult VKAPI_CALL
panvk_EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)224 panvk_EnumerateInstanceExtensionProperties(const char *pLayerName,
225                                            uint32_t *pPropertyCount,
226                                            VkExtensionProperties *pProperties)
227 {
228    if (pLayerName)
229       return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
230 
231    return vk_enumerate_instance_extension_properties(
232       &panvk_instance_extensions, pPropertyCount, pProperties);
233 }
234 
235 PFN_vkVoidFunction
panvk_GetInstanceProcAddr(VkInstance _instance,const char * pName)236 panvk_GetInstanceProcAddr(VkInstance _instance, const char *pName)
237 {
238    VK_FROM_HANDLE(panvk_instance, instance, _instance);
239    return vk_instance_get_proc_addr(&instance->vk, &panvk_instance_entrypoints,
240                                     pName);
241 }
242 
243 /* The loader wants us to expose a second GetInstanceProcAddr function
244  * to work around certain LD_PRELOAD issues seen in apps.
245  */
246 PUBLIC
247 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance,const char * pName)248 vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)
249 {
250    return panvk_GetInstanceProcAddr(instance, pName);
251 }
252