• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2019 Raspberry Pi Ltd
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include <assert.h>
25 #include <fcntl.h>
26 #include <stdbool.h>
27 #include <string.h>
28 #include <sys/mman.h>
29 #include <sys/sysinfo.h>
30 #include <unistd.h>
31 #include <xf86drm.h>
32 
33 #ifdef MAJOR_IN_MKDEV
34 #include <sys/mkdev.h>
35 #endif
36 #ifdef MAJOR_IN_SYSMACROS
37 #include <sys/sysmacros.h>
38 #endif
39 
40 #include "v3dv_private.h"
41 
42 #include "common/v3d_debug.h"
43 
44 #include "compiler/v3d_compiler.h"
45 
46 #include "drm-uapi/v3d_drm.h"
47 #include "format/u_format.h"
48 #include "vk_drm_syncobj.h"
49 #include "vk_util.h"
50 #include "git_sha1.h"
51 
52 #include "util/build_id.h"
53 #include "util/debug.h"
54 
55 #ifdef VK_USE_PLATFORM_XCB_KHR
56 #include <xcb/xcb.h>
57 #include <xcb/dri3.h>
58 #include <X11/Xlib-xcb.h>
59 #endif
60 
61 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
62 #include <wayland-client.h>
63 #include "wayland-drm-client-protocol.h"
64 #endif
65 
66 #ifndef ANDROID
67 #   define V3DV_API_VERSION VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION)
68 #else
69 /* Android CDD require additional extensions for API v1.1+ */
70 #   define V3DV_API_VERSION VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION)
71 #endif
72 
73 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_EnumerateInstanceVersion(uint32_t * pApiVersion)74 v3dv_EnumerateInstanceVersion(uint32_t *pApiVersion)
75 {
76     *pApiVersion = V3DV_API_VERSION;
77     return VK_SUCCESS;
78 }
79 
80 #if defined(VK_USE_PLATFORM_WIN32_KHR) ||   \
81     defined(VK_USE_PLATFORM_WAYLAND_KHR) || \
82     defined(VK_USE_PLATFORM_XCB_KHR) ||     \
83     defined(VK_USE_PLATFORM_XLIB_KHR) ||    \
84     defined(VK_USE_PLATFORM_DISPLAY_KHR)
85 #define V3DV_USE_WSI_PLATFORM
86 #endif
87 
88 static const struct vk_instance_extension_table instance_extensions = {
89    .KHR_device_group_creation           = true,
90 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
91    .KHR_display                         = true,
92    .KHR_get_display_properties2         = true,
93 #endif
94    .KHR_external_fence_capabilities     = true,
95    .KHR_external_memory_capabilities    = true,
96    .KHR_external_semaphore_capabilities = true,
97    .KHR_get_physical_device_properties2 = true,
98 #ifdef V3DV_USE_WSI_PLATFORM
99    .KHR_get_surface_capabilities2       = true,
100    .KHR_surface                         = true,
101    .KHR_surface_protected_capabilities  = true,
102 #endif
103 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
104    .KHR_wayland_surface                 = true,
105 #endif
106 #ifdef VK_USE_PLATFORM_XCB_KHR
107    .KHR_xcb_surface                     = true,
108 #endif
109 #ifdef VK_USE_PLATFORM_XLIB_KHR
110    .KHR_xlib_surface                    = true,
111 #endif
112    .EXT_debug_report                    = true,
113    .EXT_debug_utils                     = true,
114 };
115 
116 static void
get_device_extensions(const struct v3dv_physical_device * device,struct vk_device_extension_table * ext)117 get_device_extensions(const struct v3dv_physical_device *device,
118                       struct vk_device_extension_table *ext)
119 {
120    *ext = (struct vk_device_extension_table) {
121       .KHR_8bit_storage                    = true,
122       .KHR_16bit_storage                   = true,
123       .KHR_bind_memory2                    = true,
124       .KHR_buffer_device_address           = true,
125       .KHR_copy_commands2                  = true,
126       .KHR_create_renderpass2              = true,
127       .KHR_dedicated_allocation            = true,
128       .KHR_device_group                    = true,
129       .KHR_driver_properties               = true,
130       .KHR_descriptor_update_template      = true,
131       .KHR_depth_stencil_resolve           = true,
132       .KHR_external_fence                  = true,
133       .KHR_external_fence_fd               = true,
134       .KHR_external_memory                 = true,
135       .KHR_external_memory_fd              = true,
136       .KHR_external_semaphore              = true,
137       .KHR_external_semaphore_fd           = true,
138       .KHR_format_feature_flags2           = true,
139       .KHR_get_memory_requirements2        = true,
140       .KHR_image_format_list               = true,
141       .KHR_imageless_framebuffer           = true,
142       .KHR_performance_query               = device->caps.perfmon,
143       .KHR_relaxed_block_layout            = true,
144       .KHR_maintenance1                    = true,
145       .KHR_maintenance2                    = true,
146       .KHR_maintenance3                    = true,
147       .KHR_multiview                       = true,
148       .KHR_pipeline_executable_properties  = true,
149       .KHR_separate_depth_stencil_layouts  = true,
150       .KHR_shader_float_controls           = true,
151       .KHR_shader_non_semantic_info        = true,
152       .KHR_sampler_mirror_clamp_to_edge    = true,
153       .KHR_spirv_1_4                       = true,
154       .KHR_storage_buffer_storage_class    = true,
155       .KHR_timeline_semaphore              = true,
156       .KHR_uniform_buffer_standard_layout  = true,
157 #ifdef V3DV_USE_WSI_PLATFORM
158       .KHR_swapchain                       = true,
159       .KHR_swapchain_mutable_format        = true,
160       .KHR_incremental_present             = true,
161 #endif
162       .KHR_variable_pointers               = true,
163       .KHR_vulkan_memory_model             = true,
164       .EXT_4444_formats                    = true,
165       .EXT_color_write_enable              = true,
166       .EXT_custom_border_color             = true,
167       .EXT_inline_uniform_block            = true,
168       .EXT_external_memory_dma_buf         = true,
169       .EXT_host_query_reset                = true,
170       .EXT_image_drm_format_modifier       = true,
171       .EXT_index_type_uint8                = true,
172       .EXT_line_rasterization              = true,
173       .EXT_physical_device_drm             = true,
174       .EXT_pipeline_creation_cache_control = true,
175       .EXT_pipeline_creation_feedback      = true,
176       .EXT_private_data                    = true,
177       .EXT_provoking_vertex                = true,
178       .EXT_separate_stencil_usage          = true,
179       .EXT_vertex_attribute_divisor        = true,
180 #ifdef ANDROID
181       .ANDROID_native_buffer               = true,
182 #endif
183    };
184 }
185 
186 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)187 v3dv_EnumerateInstanceExtensionProperties(const char *pLayerName,
188                                           uint32_t *pPropertyCount,
189                                           VkExtensionProperties *pProperties)
190 {
191    /* We don't support any layers  */
192    if (pLayerName)
193       return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
194 
195    return vk_enumerate_instance_extension_properties(
196       &instance_extensions, pPropertyCount, pProperties);
197 }
198 
199 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)200 v3dv_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
201                     const VkAllocationCallbacks *pAllocator,
202                     VkInstance *pInstance)
203 {
204    struct v3dv_instance *instance;
205    VkResult result;
206 
207    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
208 
209    if (pAllocator == NULL)
210       pAllocator = vk_default_allocator();
211 
212    instance = vk_alloc(pAllocator, sizeof(*instance), 8,
213                        VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
214    if (!instance)
215       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
216 
217    struct vk_instance_dispatch_table dispatch_table;
218    vk_instance_dispatch_table_from_entrypoints(
219       &dispatch_table, &v3dv_instance_entrypoints, true);
220    vk_instance_dispatch_table_from_entrypoints(
221       &dispatch_table, &wsi_instance_entrypoints, false);
222 
223    result = vk_instance_init(&instance->vk,
224                              &instance_extensions,
225                              &dispatch_table,
226                              pCreateInfo, pAllocator);
227 
228    if (result != VK_SUCCESS) {
229       vk_free(pAllocator, instance);
230       return vk_error(NULL, result);
231    }
232 
233    v3d_process_debug_variable();
234 
235    instance->physicalDeviceCount = -1;
236 
237    /* We start with the default values for the pipeline_cache envvars */
238    instance->pipeline_cache_enabled = true;
239    instance->default_pipeline_cache_enabled = true;
240    const char *pipeline_cache_str = getenv("V3DV_ENABLE_PIPELINE_CACHE");
241    if (pipeline_cache_str != NULL) {
242       if (strncmp(pipeline_cache_str, "full", 4) == 0) {
243          /* nothing to do, just to filter correct values */
244       } else if (strncmp(pipeline_cache_str, "no-default-cache", 16) == 0) {
245          instance->default_pipeline_cache_enabled = false;
246       } else if (strncmp(pipeline_cache_str, "off", 3) == 0) {
247          instance->pipeline_cache_enabled = false;
248          instance->default_pipeline_cache_enabled = false;
249       } else {
250          fprintf(stderr, "Wrong value for envvar V3DV_ENABLE_PIPELINE_CACHE. "
251                  "Allowed values are: full, no-default-cache, off\n");
252       }
253    }
254 
255    if (instance->pipeline_cache_enabled == false) {
256       fprintf(stderr, "WARNING: v3dv pipeline cache is disabled. Performance "
257               "can be affected negatively\n");
258    } else {
259       if (instance->default_pipeline_cache_enabled == false) {
260         fprintf(stderr, "WARNING: default v3dv pipeline cache is disabled. "
261                 "Performance can be affected negatively\n");
262       }
263    }
264 
265    VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
266 
267    *pInstance = v3dv_instance_to_handle(instance);
268 
269    return VK_SUCCESS;
270 }
271 
272 static void
v3dv_physical_device_free_disk_cache(struct v3dv_physical_device * device)273 v3dv_physical_device_free_disk_cache(struct v3dv_physical_device *device)
274 {
275 #ifdef ENABLE_SHADER_CACHE
276    if (device->disk_cache)
277       disk_cache_destroy(device->disk_cache);
278 #else
279    assert(device->disk_cache == NULL);
280 #endif
281 }
282 
283 static void
physical_device_finish(struct v3dv_physical_device * device)284 physical_device_finish(struct v3dv_physical_device *device)
285 {
286    v3dv_wsi_finish(device);
287    v3dv_physical_device_free_disk_cache(device);
288    v3d_compiler_free(device->compiler);
289 
290    util_sparse_array_finish(&device->bo_map);
291 
292    close(device->render_fd);
293    if (device->display_fd >= 0)
294       close(device->display_fd);
295    if (device->master_fd >= 0)
296       close(device->master_fd);
297 
298    free(device->name);
299 
300 #if using_v3d_simulator
301    v3d_simulator_destroy(device->sim_file);
302 #endif
303 
304    vk_physical_device_finish(&device->vk);
305    mtx_destroy(&device->mutex);
306 }
307 
308 VKAPI_ATTR void VKAPI_CALL
v3dv_DestroyInstance(VkInstance _instance,const VkAllocationCallbacks * pAllocator)309 v3dv_DestroyInstance(VkInstance _instance,
310                      const VkAllocationCallbacks *pAllocator)
311 {
312    V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
313 
314    if (!instance)
315       return;
316 
317    if (instance->physicalDeviceCount > 0) {
318       /* We support at most one physical device. */
319       assert(instance->physicalDeviceCount == 1);
320       physical_device_finish(&instance->physicalDevice);
321    }
322 
323    VG(VALGRIND_DESTROY_MEMPOOL(instance));
324 
325    vk_instance_finish(&instance->vk);
326    vk_free(&instance->vk.alloc, instance);
327 }
328 
329 static uint64_t
compute_heap_size()330 compute_heap_size()
331 {
332 #if !using_v3d_simulator
333    /* Query the total ram from the system */
334    struct sysinfo info;
335    sysinfo(&info);
336 
337    uint64_t total_ram = (uint64_t)info.totalram * (uint64_t)info.mem_unit;
338 #else
339    uint64_t total_ram = (uint64_t) v3d_simulator_get_mem_size();
340 #endif
341 
342    /* We don't want to burn too much ram with the GPU.  If the user has 4GiB
343     * or less, we use at most half.  If they have more than 4GiB, we use 3/4.
344     */
345    uint64_t available_ram;
346    if (total_ram <= 4ull * 1024ull * 1024ull * 1024ull)
347       available_ram = total_ram / 2;
348    else
349       available_ram = total_ram * 3 / 4;
350 
351    return available_ram;
352 }
353 
354 #if !using_v3d_simulator
355 #ifdef VK_USE_PLATFORM_XCB_KHR
356 static int
create_display_fd_xcb(VkIcdSurfaceBase * surface)357 create_display_fd_xcb(VkIcdSurfaceBase *surface)
358 {
359    int fd = -1;
360 
361    xcb_connection_t *conn;
362    xcb_dri3_open_reply_t *reply = NULL;
363    if (surface) {
364       if (surface->platform == VK_ICD_WSI_PLATFORM_XLIB)
365          conn = XGetXCBConnection(((VkIcdSurfaceXlib *)surface)->dpy);
366       else
367          conn = ((VkIcdSurfaceXcb *)surface)->connection;
368    } else {
369       conn = xcb_connect(NULL, NULL);
370    }
371 
372    if (xcb_connection_has_error(conn))
373       goto finish;
374 
375    const xcb_setup_t *setup = xcb_get_setup(conn);
376    xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
377    xcb_screen_t *screen = iter.data;
378 
379    xcb_dri3_open_cookie_t cookie;
380    cookie = xcb_dri3_open(conn, screen->root, None);
381    reply = xcb_dri3_open_reply(conn, cookie, NULL);
382    if (!reply)
383       goto finish;
384 
385    if (reply->nfd != 1)
386       goto finish;
387 
388    fd = xcb_dri3_open_reply_fds(conn, reply)[0];
389    fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
390 
391 finish:
392    if (!surface)
393       xcb_disconnect(conn);
394    if (reply)
395       free(reply);
396 
397    return fd;
398 }
399 #endif
400 
401 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
402 struct v3dv_wayland_info {
403    struct wl_drm *wl_drm;
404    int fd;
405    bool is_set;
406    bool authenticated;
407 };
408 
409 static void
v3dv_drm_handle_device(void * data,struct wl_drm * drm,const char * device)410 v3dv_drm_handle_device(void *data, struct wl_drm *drm, const char *device)
411 {
412    struct v3dv_wayland_info *info = data;
413    info->fd = open(device, O_RDWR | O_CLOEXEC);
414    info->is_set = info->fd != -1;
415    if (!info->is_set) {
416       fprintf(stderr, "v3dv_drm_handle_device: could not open %s (%s)\n",
417               device, strerror(errno));
418       return;
419    }
420 
421    drm_magic_t magic;
422    if (drmGetMagic(info->fd, &magic)) {
423       fprintf(stderr, "v3dv_drm_handle_device: drmGetMagic failed\n");
424       close(info->fd);
425       info->fd = -1;
426       info->is_set = false;
427       return;
428    }
429    wl_drm_authenticate(info->wl_drm, magic);
430 }
431 
432 static void
v3dv_drm_handle_format(void * data,struct wl_drm * drm,uint32_t format)433 v3dv_drm_handle_format(void *data, struct wl_drm *drm, uint32_t format)
434 {
435 }
436 
437 static void
v3dv_drm_handle_authenticated(void * data,struct wl_drm * drm)438 v3dv_drm_handle_authenticated(void *data, struct wl_drm *drm)
439 {
440    struct v3dv_wayland_info *info = data;
441    info->authenticated = true;
442 }
443 
444 static void
v3dv_drm_handle_capabilities(void * data,struct wl_drm * drm,uint32_t value)445 v3dv_drm_handle_capabilities(void *data, struct wl_drm *drm, uint32_t value)
446 {
447 }
448 
449 struct wl_drm_listener v3dv_drm_listener = {
450    .device = v3dv_drm_handle_device,
451    .format = v3dv_drm_handle_format,
452    .authenticated = v3dv_drm_handle_authenticated,
453    .capabilities = v3dv_drm_handle_capabilities
454 };
455 
456 static void
v3dv_registry_global(void * data,struct wl_registry * registry,uint32_t name,const char * interface,uint32_t version)457 v3dv_registry_global(void *data,
458                      struct wl_registry *registry,
459                      uint32_t name,
460                      const char *interface,
461                      uint32_t version)
462 {
463    struct v3dv_wayland_info *info = data;
464    if (strcmp(interface, "wl_drm") == 0) {
465       info->wl_drm = wl_registry_bind(registry, name, &wl_drm_interface,
466                                       MIN2(version, 2));
467       wl_drm_add_listener(info->wl_drm, &v3dv_drm_listener, data);
468    };
469 }
470 
471 static void
v3dv_registry_global_remove_cb(void * data,struct wl_registry * registry,uint32_t name)472 v3dv_registry_global_remove_cb(void *data,
473                                struct wl_registry *registry,
474                                uint32_t name)
475 {
476 }
477 
478 static int
create_display_fd_wayland(VkIcdSurfaceBase * surface)479 create_display_fd_wayland(VkIcdSurfaceBase *surface)
480 {
481    struct wl_display *display;
482    struct wl_registry *registry = NULL;
483 
484    struct v3dv_wayland_info info = {
485       .wl_drm = NULL,
486       .fd = -1,
487       .is_set = false,
488       .authenticated = false
489    };
490 
491    if (surface)
492       display = ((VkIcdSurfaceWayland *) surface)->display;
493    else
494       display = wl_display_connect(NULL);
495 
496    if (!display)
497       return -1;
498 
499    registry = wl_display_get_registry(display);
500    if (!registry) {
501       if (!surface)
502          wl_display_disconnect(display);
503       return -1;
504    }
505 
506    static const struct wl_registry_listener registry_listener = {
507       v3dv_registry_global,
508       v3dv_registry_global_remove_cb
509    };
510    wl_registry_add_listener(registry, &registry_listener, &info);
511 
512    wl_display_roundtrip(display); /* For the registry advertisement */
513    wl_display_roundtrip(display); /* For the DRM device event */
514    wl_display_roundtrip(display); /* For the authentication event */
515 
516    wl_drm_destroy(info.wl_drm);
517    wl_registry_destroy(registry);
518 
519    if (!surface)
520       wl_display_disconnect(display);
521 
522    if (!info.is_set)
523       return -1;
524 
525    if (!info.authenticated)
526       return -1;
527 
528    return info.fd;
529 }
530 #endif
531 
532 /* Acquire an authenticated display fd without a surface reference. This is the
533  * case where the application is making WSI allocations outside the Vulkan
534  * swapchain context (only Zink, for now). Since we lack information about the
535  * underlying surface we just try our best to figure out the correct display
536  * and platform to use. It should work in most cases.
537  */
538 static void
acquire_display_device_no_surface(struct v3dv_instance * instance,struct v3dv_physical_device * pdevice)539 acquire_display_device_no_surface(struct v3dv_instance *instance,
540                                   struct v3dv_physical_device *pdevice)
541 {
542 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
543    pdevice->display_fd = create_display_fd_wayland(NULL);
544 #endif
545 
546 #ifdef VK_USE_PLATFORM_XCB_KHR
547    if (pdevice->display_fd == -1)
548       pdevice->display_fd = create_display_fd_xcb(NULL);
549 #endif
550 
551 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
552    if (pdevice->display_fd == - 1 && pdevice->master_fd >= 0)
553       pdevice->display_fd = dup(pdevice->master_fd);
554 #endif
555 }
556 
557 /* Acquire an authenticated display fd from the surface. This is the regular
558  * case where the application is using swapchains to create WSI allocations.
559  * In this case we use the surface information to figure out the correct
560  * display and platform combination.
561  */
562 static void
acquire_display_device_surface(struct v3dv_instance * instance,struct v3dv_physical_device * pdevice,VkIcdSurfaceBase * surface)563 acquire_display_device_surface(struct v3dv_instance *instance,
564                                struct v3dv_physical_device *pdevice,
565                                VkIcdSurfaceBase *surface)
566 {
567    /* Mesa will set both of VK_USE_PLATFORM_{XCB,XLIB} when building with
568     * platform X11, so only check for XCB and rely on XCB to get an
569     * authenticated device also for Xlib.
570     */
571 #ifdef VK_USE_PLATFORM_XCB_KHR
572    if (surface->platform == VK_ICD_WSI_PLATFORM_XCB ||
573        surface->platform == VK_ICD_WSI_PLATFORM_XLIB) {
574       pdevice->display_fd = create_display_fd_xcb(surface);
575    }
576 #endif
577 
578 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
579    if (surface->platform == VK_ICD_WSI_PLATFORM_WAYLAND)
580       pdevice->display_fd = create_display_fd_wayland(surface);
581 #endif
582 
583 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
584    if (surface->platform == VK_ICD_WSI_PLATFORM_DISPLAY &&
585        pdevice->master_fd >= 0) {
586       pdevice->display_fd = dup(pdevice->master_fd);
587    }
588 #endif
589 }
590 #endif /* !using_v3d_simulator */
591 
592 /* Attempts to get an authenticated display fd from the display server that
593  * we can use to allocate BOs for presentable images.
594  */
595 VkResult
v3dv_physical_device_acquire_display(struct v3dv_instance * instance,struct v3dv_physical_device * pdevice,VkIcdSurfaceBase * surface)596 v3dv_physical_device_acquire_display(struct v3dv_instance *instance,
597                                      struct v3dv_physical_device *pdevice,
598                                      VkIcdSurfaceBase *surface)
599 {
600    VkResult result = VK_SUCCESS;
601    mtx_lock(&pdevice->mutex);
602 
603    if (pdevice->display_fd != -1)
604       goto done;
605 
606    /* When running on the simulator we do everything on a single render node so
607     * we don't need to get an authenticated display fd from the display server.
608     */
609 #if !using_v3d_simulator
610    if (surface)
611       acquire_display_device_surface(instance, pdevice, surface);
612    else
613       acquire_display_device_no_surface(instance, pdevice);
614 
615    if (pdevice->display_fd == -1)
616       result = VK_ERROR_INITIALIZATION_FAILED;
617 #endif
618 
619 done:
620    mtx_unlock(&pdevice->mutex);
621    return result;
622 }
623 
624 static bool
v3d_has_feature(struct v3dv_physical_device * device,enum drm_v3d_param feature)625 v3d_has_feature(struct v3dv_physical_device *device, enum drm_v3d_param feature)
626 {
627    struct drm_v3d_get_param p = {
628       .param = feature,
629    };
630    if (v3dv_ioctl(device->render_fd, DRM_IOCTL_V3D_GET_PARAM, &p) != 0)
631       return false;
632    return p.value;
633 }
634 
635 static bool
device_has_expected_features(struct v3dv_physical_device * device)636 device_has_expected_features(struct v3dv_physical_device *device)
637 {
638    return v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_TFU) &&
639           v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_CSD) &&
640           v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_CACHE_FLUSH);
641 }
642 
643 
644 static VkResult
init_uuids(struct v3dv_physical_device * device)645 init_uuids(struct v3dv_physical_device *device)
646 {
647    const struct build_id_note *note =
648       build_id_find_nhdr_for_addr(init_uuids);
649    if (!note) {
650       return vk_errorf(device->vk.instance,
651                        VK_ERROR_INITIALIZATION_FAILED,
652                        "Failed to find build-id");
653    }
654 
655    unsigned build_id_len = build_id_length(note);
656    if (build_id_len < 20) {
657       return vk_errorf(device->vk.instance,
658                        VK_ERROR_INITIALIZATION_FAILED,
659                        "build-id too short.  It needs to be a SHA");
660    }
661 
662    memcpy(device->driver_build_sha1, build_id_data(note), 20);
663 
664    uint32_t vendor_id = v3dv_physical_device_vendor_id(device);
665    uint32_t device_id = v3dv_physical_device_device_id(device);
666 
667    struct mesa_sha1 sha1_ctx;
668    uint8_t sha1[20];
669    STATIC_ASSERT(VK_UUID_SIZE <= sizeof(sha1));
670 
671    /* The pipeline cache UUID is used for determining when a pipeline cache is
672     * invalid.  It needs both a driver build and the PCI ID of the device.
673     */
674    _mesa_sha1_init(&sha1_ctx);
675    _mesa_sha1_update(&sha1_ctx, build_id_data(note), build_id_len);
676    _mesa_sha1_update(&sha1_ctx, &device_id, sizeof(device_id));
677    _mesa_sha1_final(&sha1_ctx, sha1);
678    memcpy(device->pipeline_cache_uuid, sha1, VK_UUID_SIZE);
679 
680    /* The driver UUID is used for determining sharability of images and memory
681     * between two Vulkan instances in separate processes.  People who want to
682     * share memory need to also check the device UUID (below) so all this
683     * needs to be is the build-id.
684     */
685    memcpy(device->driver_uuid, build_id_data(note), VK_UUID_SIZE);
686 
687    /* The device UUID uniquely identifies the given device within the machine.
688     * Since we never have more than one device, this doesn't need to be a real
689     * UUID.
690     */
691    _mesa_sha1_init(&sha1_ctx);
692    _mesa_sha1_update(&sha1_ctx, &vendor_id, sizeof(vendor_id));
693    _mesa_sha1_update(&sha1_ctx, &device_id, sizeof(device_id));
694    _mesa_sha1_final(&sha1_ctx, sha1);
695    memcpy(device->device_uuid, sha1, VK_UUID_SIZE);
696 
697    return VK_SUCCESS;
698 }
699 
700 static void
v3dv_physical_device_init_disk_cache(struct v3dv_physical_device * device)701 v3dv_physical_device_init_disk_cache(struct v3dv_physical_device *device)
702 {
703 #ifdef ENABLE_SHADER_CACHE
704    char timestamp[41];
705    _mesa_sha1_format(timestamp, device->driver_build_sha1);
706 
707    assert(device->name);
708    device->disk_cache = disk_cache_create(device->name, timestamp, 0);
709 #else
710    device->disk_cache = NULL;
711 #endif
712 }
713 
714 static VkResult
physical_device_init(struct v3dv_physical_device * device,struct v3dv_instance * instance,drmDevicePtr drm_render_device,drmDevicePtr drm_primary_device)715 physical_device_init(struct v3dv_physical_device *device,
716                      struct v3dv_instance *instance,
717                      drmDevicePtr drm_render_device,
718                      drmDevicePtr drm_primary_device)
719 {
720    VkResult result = VK_SUCCESS;
721    int32_t master_fd = -1;
722    int32_t render_fd = -1;
723 
724    struct vk_physical_device_dispatch_table dispatch_table;
725    vk_physical_device_dispatch_table_from_entrypoints
726       (&dispatch_table, &v3dv_physical_device_entrypoints, true);
727    vk_physical_device_dispatch_table_from_entrypoints(
728       &dispatch_table, &wsi_physical_device_entrypoints, false);
729 
730    result = vk_physical_device_init(&device->vk, &instance->vk, NULL,
731                                     &dispatch_table);
732 
733    if (result != VK_SUCCESS)
734       goto fail;
735 
736    assert(drm_render_device);
737    const char *path = drm_render_device->nodes[DRM_NODE_RENDER];
738    render_fd = open(path, O_RDWR | O_CLOEXEC);
739    if (render_fd < 0) {
740       fprintf(stderr, "Opening %s failed: %s\n", path, strerror(errno));
741       result = VK_ERROR_INCOMPATIBLE_DRIVER;
742       goto fail;
743    }
744 
745    /* If we are running on VK_KHR_display we need to acquire the master
746     * display device now for the v3dv_wsi_init() call below. For anything else
747     * we postpone that until a swapchain is created.
748     */
749 
750    const char *primary_path;
751 #if !using_v3d_simulator
752    if (drm_primary_device)
753       primary_path = drm_primary_device->nodes[DRM_NODE_PRIMARY];
754    else
755       primary_path = NULL;
756 #else
757    primary_path = drm_render_device->nodes[DRM_NODE_PRIMARY];
758 #endif
759 
760    struct stat primary_stat = {0}, render_stat = {0};
761 
762    device->has_primary = primary_path;
763    if (device->has_primary) {
764       if (stat(primary_path, &primary_stat) != 0) {
765          result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
766                             "failed to stat DRM primary node %s",
767                             primary_path);
768          goto fail;
769       }
770 
771       device->primary_devid = primary_stat.st_rdev;
772    }
773 
774    if (fstat(render_fd, &render_stat) != 0) {
775       result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
776                          "failed to stat DRM render node %s",
777                          path);
778       goto fail;
779    }
780    device->has_render = true;
781    device->render_devid = render_stat.st_rdev;
782 
783 #if using_v3d_simulator
784    device->device_id = drm_render_device->deviceinfo.pci->device_id;
785 #endif
786 
787    if (instance->vk.enabled_extensions.KHR_display) {
788 #if !using_v3d_simulator
789       /* Open the primary node on the vc4 display device */
790       assert(drm_primary_device);
791       master_fd = open(primary_path, O_RDWR | O_CLOEXEC);
792 #else
793       /* There is only one device with primary and render nodes.
794        * Open its primary node.
795        */
796       master_fd = open(primary_path, O_RDWR | O_CLOEXEC);
797 #endif
798    }
799 
800 #if using_v3d_simulator
801    device->sim_file = v3d_simulator_init(render_fd);
802 #endif
803 
804    device->render_fd = render_fd;    /* The v3d render node  */
805    device->display_fd = -1;          /* Authenticated vc4 primary node */
806    device->master_fd = master_fd;    /* Master vc4 primary node */
807 
808    if (!v3d_get_device_info(device->render_fd, &device->devinfo, &v3dv_ioctl)) {
809       result = VK_ERROR_INCOMPATIBLE_DRIVER;
810       goto fail;
811    }
812 
813    if (device->devinfo.ver < 42) {
814       result = VK_ERROR_INCOMPATIBLE_DRIVER;
815       goto fail;
816    }
817 
818    if (!device_has_expected_features(device)) {
819       result = VK_ERROR_INCOMPATIBLE_DRIVER;
820       goto fail;
821    }
822 
823    device->caps.multisync =
824       v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_MULTISYNC_EXT);
825 
826    device->caps.perfmon =
827       v3d_has_feature(device, DRM_V3D_PARAM_SUPPORTS_PERFMON);
828 
829    result = init_uuids(device);
830    if (result != VK_SUCCESS)
831       goto fail;
832 
833    device->compiler = v3d_compiler_init(&device->devinfo,
834                                         MAX_INLINE_UNIFORM_BUFFERS);
835    device->next_program_id = 0;
836 
837    ASSERTED int len =
838       asprintf(&device->name, "V3D %d.%d",
839                device->devinfo.ver / 10, device->devinfo.ver % 10);
840    assert(len != -1);
841 
842    v3dv_physical_device_init_disk_cache(device);
843 
844    /* Setup available memory heaps and types */
845    VkPhysicalDeviceMemoryProperties *mem = &device->memory;
846    mem->memoryHeapCount = 1;
847    mem->memoryHeaps[0].size = compute_heap_size();
848    mem->memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
849 
850    /* This is the only combination required by the spec */
851    mem->memoryTypeCount = 1;
852    mem->memoryTypes[0].propertyFlags =
853       VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
854       VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
855       VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
856    mem->memoryTypes[0].heapIndex = 0;
857 
858    /* Initialize sparse array for refcounting imported BOs */
859    util_sparse_array_init(&device->bo_map, sizeof(struct v3dv_bo), 512);
860 
861    device->options.merge_jobs = !(V3D_DEBUG & V3D_DEBUG_NO_MERGE_JOBS);
862 
863    device->drm_syncobj_type = vk_drm_syncobj_get_type(device->render_fd);
864 
865    /* We don't support timelines in the uAPI yet and we don't want it getting
866     * suddenly turned on by vk_drm_syncobj_get_type() without us adding v3dv
867     * code for it first.
868     */
869    device->drm_syncobj_type.features &= ~VK_SYNC_FEATURE_TIMELINE;
870 
871 #ifndef ANDROID
872    /* Sync file export is incompatible with the current model of execution
873     * where some jobs may run on the CPU.  There are CTS tests which do the
874     * following:
875     *
876     *  1. Create a command buffer with a vkCmdWaitEvents()
877     *  2. Submit the command buffer
878     *  3. vkGetSemaphoreFdKHR() to try to get a sync_file
879     *  4. vkSetEvent()
880     *
881     * This deadlocks because we have to wait for the syncobj to get a real
882     * fence in vkGetSemaphoreFdKHR() which only happens after all the work
883     * from the command buffer is complete which only happens after
884     * vkSetEvent().  No amount of CPU threading in userspace will ever fix
885     * this.  Sadly, this is pretty explicitly allowed by the Vulkan spec:
886     *
887     *    VUID-vkCmdWaitEvents-pEvents-01163
888     *
889     *    "If pEvents includes one or more events that will be signaled by
890     *    vkSetEvent after commandBuffer has been submitted to a queue, then
891     *    vkCmdWaitEvents must not be called inside a render pass instance"
892     *
893     * Disable sync file support for now.
894     */
895    device->drm_syncobj_type.import_sync_file = NULL;
896    device->drm_syncobj_type.export_sync_file = NULL;
897 #endif
898 
899    /* Multiwait is required for emulated timeline semaphores and is supported
900     * by the v3d kernel interface.
901     */
902    device->drm_syncobj_type.features |= VK_SYNC_FEATURE_GPU_MULTI_WAIT;
903 
904    device->sync_timeline_type =
905       vk_sync_timeline_get_type(&device->drm_syncobj_type);
906 
907    device->sync_types[0] = &device->drm_syncobj_type;
908    device->sync_types[1] = &device->sync_timeline_type.sync;
909    device->sync_types[2] = NULL;
910    device->vk.supported_sync_types = device->sync_types;
911 
912    result = v3dv_wsi_init(device);
913    if (result != VK_SUCCESS) {
914       vk_error(instance, result);
915       goto fail;
916    }
917 
918    get_device_extensions(device, &device->vk.supported_extensions);
919 
920    mtx_init(&device->mutex, mtx_plain);
921 
922    return VK_SUCCESS;
923 
924 fail:
925    vk_physical_device_finish(&device->vk);
926 
927    if (render_fd >= 0)
928       close(render_fd);
929    if (master_fd >= 0)
930       close(master_fd);
931 
932    return result;
933 }
934 
935 static VkResult
enumerate_devices(struct v3dv_instance * instance)936 enumerate_devices(struct v3dv_instance *instance)
937 {
938    /* TODO: Check for more devices? */
939    drmDevicePtr devices[8];
940    VkResult result = VK_ERROR_INCOMPATIBLE_DRIVER;
941    int max_devices;
942 
943    instance->physicalDeviceCount = 0;
944 
945    max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
946    if (max_devices < 1)
947       return VK_ERROR_INCOMPATIBLE_DRIVER;
948 
949 #if !using_v3d_simulator
950    int32_t v3d_idx = -1;
951    int32_t vc4_idx = -1;
952 #endif
953    for (unsigned i = 0; i < (unsigned)max_devices; i++) {
954 #if using_v3d_simulator
955       /* In the simulator, we look for an Intel/AMD render node */
956       const int required_nodes = (1 << DRM_NODE_RENDER) | (1 << DRM_NODE_PRIMARY);
957       if ((devices[i]->available_nodes & required_nodes) == required_nodes &&
958            devices[i]->bustype == DRM_BUS_PCI &&
959           (devices[i]->deviceinfo.pci->vendor_id == 0x8086 ||
960            devices[i]->deviceinfo.pci->vendor_id == 0x1002)) {
961          result = physical_device_init(&instance->physicalDevice, instance,
962                                        devices[i], NULL);
963          if (result != VK_ERROR_INCOMPATIBLE_DRIVER)
964             break;
965       }
966 #else
967       /* On actual hardware, we should have a render node (v3d)
968        * and a primary node (vc4). We will need to use the primary
969        * to allocate WSI buffers and share them with the render node
970        * via prime, but that is a privileged operation so we need the
971        * primary node to be authenticated, and for that we need the
972        * display server to provide the device fd (with DRI3), so we
973        * here we only check that the device is present but we don't
974        * try to open it.
975        */
976       if (devices[i]->bustype != DRM_BUS_PLATFORM)
977          continue;
978 
979       if (devices[i]->available_nodes & 1 << DRM_NODE_RENDER) {
980          char **compat = devices[i]->deviceinfo.platform->compatible;
981          while (*compat) {
982             if (strncmp(*compat, "brcm,2711-v3d", 13) == 0) {
983                v3d_idx = i;
984                break;
985             }
986             compat++;
987          }
988       } else if (devices[i]->available_nodes & 1 << DRM_NODE_PRIMARY) {
989          char **compat = devices[i]->deviceinfo.platform->compatible;
990          while (*compat) {
991             if (strncmp(*compat, "brcm,bcm2711-vc5", 16) == 0 ||
992                 strncmp(*compat, "brcm,bcm2835-vc4", 16) == 0 ) {
993                vc4_idx = i;
994                break;
995             }
996             compat++;
997          }
998       }
999 #endif
1000    }
1001 
1002 #if !using_v3d_simulator
1003    if (v3d_idx == -1 || vc4_idx == -1)
1004       result = VK_ERROR_INCOMPATIBLE_DRIVER;
1005    else
1006       result = physical_device_init(&instance->physicalDevice, instance,
1007                                     devices[v3d_idx], devices[vc4_idx]);
1008 #endif
1009 
1010    drmFreeDevices(devices, max_devices);
1011 
1012    if (result == VK_SUCCESS)
1013       instance->physicalDeviceCount = 1;
1014 
1015    return result;
1016 }
1017 
1018 static VkResult
instance_ensure_physical_device(struct v3dv_instance * instance)1019 instance_ensure_physical_device(struct v3dv_instance *instance)
1020 {
1021    if (instance->physicalDeviceCount < 0) {
1022       VkResult result = enumerate_devices(instance);
1023       if (result != VK_SUCCESS &&
1024           result != VK_ERROR_INCOMPATIBLE_DRIVER)
1025          return result;
1026    }
1027 
1028    return VK_SUCCESS;
1029 }
1030 
1031 VKAPI_ATTR VkResult  VKAPI_CALL
v3dv_EnumeratePhysicalDevices(VkInstance _instance,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices)1032 v3dv_EnumeratePhysicalDevices(VkInstance _instance,
1033                               uint32_t *pPhysicalDeviceCount,
1034                               VkPhysicalDevice *pPhysicalDevices)
1035 {
1036    V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
1037    VK_OUTARRAY_MAKE_TYPED(VkPhysicalDevice, out,
1038                           pPhysicalDevices, pPhysicalDeviceCount);
1039 
1040    VkResult result = instance_ensure_physical_device(instance);
1041    if (result != VK_SUCCESS)
1042       return result;
1043 
1044    if (instance->physicalDeviceCount == 0)
1045       return VK_SUCCESS;
1046 
1047    assert(instance->physicalDeviceCount == 1);
1048    vk_outarray_append_typed(VkPhysicalDevice, &out, i) {
1049       *i = v3dv_physical_device_to_handle(&instance->physicalDevice);
1050    }
1051 
1052    return vk_outarray_status(&out);
1053 }
1054 
1055 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_EnumeratePhysicalDeviceGroups(VkInstance _instance,uint32_t * pPhysicalDeviceGroupCount,VkPhysicalDeviceGroupProperties * pPhysicalDeviceGroupProperties)1056 v3dv_EnumeratePhysicalDeviceGroups(
1057     VkInstance _instance,
1058     uint32_t *pPhysicalDeviceGroupCount,
1059     VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties)
1060 {
1061    V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
1062    VK_OUTARRAY_MAKE_TYPED(VkPhysicalDeviceGroupProperties, out,
1063                           pPhysicalDeviceGroupProperties,
1064                           pPhysicalDeviceGroupCount);
1065 
1066    VkResult result = instance_ensure_physical_device(instance);
1067    if (result != VK_SUCCESS)
1068       return result;
1069 
1070    assert(instance->physicalDeviceCount == 1);
1071 
1072    vk_outarray_append_typed(VkPhysicalDeviceGroupProperties, &out, p) {
1073       p->physicalDeviceCount = 1;
1074       memset(p->physicalDevices, 0, sizeof(p->physicalDevices));
1075       p->physicalDevices[0] =
1076          v3dv_physical_device_to_handle(&instance->physicalDevice);
1077       p->subsetAllocation = false;
1078 
1079       vk_foreach_struct(ext, p->pNext)
1080          v3dv_debug_ignored_stype(ext->sType);
1081    }
1082 
1083    return vk_outarray_status(&out);
1084 }
1085 
1086 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,VkPhysicalDeviceFeatures * pFeatures)1087 v3dv_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
1088                                VkPhysicalDeviceFeatures *pFeatures)
1089 {
1090    memset(pFeatures, 0, sizeof(*pFeatures));
1091 
1092    *pFeatures = (VkPhysicalDeviceFeatures) {
1093       .robustBufferAccess = true, /* This feature is mandatory */
1094       .fullDrawIndexUint32 = false, /* Only available since V3D 4.4.9.1 */
1095       .imageCubeArray = true,
1096       .independentBlend = true,
1097       .geometryShader = true,
1098       .tessellationShader = false,
1099       .sampleRateShading = true,
1100       .dualSrcBlend = false,
1101       .logicOp = true,
1102       .multiDrawIndirect = false,
1103       .drawIndirectFirstInstance = true,
1104       .depthClamp = false, /* Only available since V3D 4.5.1.1 */
1105       .depthBiasClamp = true,
1106       .fillModeNonSolid = true,
1107       .depthBounds = false, /* Only available since V3D 4.3.16.2 */
1108       .wideLines = true,
1109       .largePoints = true,
1110       .alphaToOne = true,
1111       .multiViewport = false,
1112       .samplerAnisotropy = true,
1113       .textureCompressionETC2 = true,
1114       .textureCompressionASTC_LDR = true,
1115       /* Note that textureCompressionBC requires that the driver support all
1116        * the BC formats. V3D 4.2 only support the BC1-3, so we can't claim
1117        * that we support it.
1118        */
1119       .textureCompressionBC = false,
1120       .occlusionQueryPrecise = true,
1121       .pipelineStatisticsQuery = false,
1122       .vertexPipelineStoresAndAtomics = true,
1123       .fragmentStoresAndAtomics = true,
1124       .shaderTessellationAndGeometryPointSize = true,
1125       .shaderImageGatherExtended = false,
1126       .shaderStorageImageExtendedFormats = true,
1127       .shaderStorageImageMultisample = false,
1128       .shaderStorageImageReadWithoutFormat = false,
1129       .shaderStorageImageWriteWithoutFormat = false,
1130       .shaderUniformBufferArrayDynamicIndexing = false,
1131       .shaderSampledImageArrayDynamicIndexing = false,
1132       .shaderStorageBufferArrayDynamicIndexing = false,
1133       .shaderStorageImageArrayDynamicIndexing = false,
1134       .shaderClipDistance = true,
1135       .shaderCullDistance = false,
1136       .shaderFloat64 = false,
1137       .shaderInt64 = false,
1138       .shaderInt16 = false,
1139       .shaderResourceResidency = false,
1140       .shaderResourceMinLod = false,
1141       .sparseBinding = false,
1142       .sparseResidencyBuffer = false,
1143       .sparseResidencyImage2D = false,
1144       .sparseResidencyImage3D = false,
1145       .sparseResidency2Samples = false,
1146       .sparseResidency4Samples = false,
1147       .sparseResidency8Samples = false,
1148       .sparseResidency16Samples = false,
1149       .sparseResidencyAliased = false,
1150       .variableMultisampleRate = false,
1151       .inheritedQueries = true,
1152    };
1153 }
1154 
1155 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceFeatures2 * pFeatures)1156 v3dv_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
1157                                 VkPhysicalDeviceFeatures2 *pFeatures)
1158 {
1159    V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
1160    v3dv_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
1161 
1162    VkPhysicalDeviceVulkan13Features vk13 = {
1163       .inlineUniformBlock  = true,
1164       /* Inline buffers work like push constants, so after their are bound
1165        * some of their contents may be copied into the uniform stream as soon
1166        * as the next draw/dispatch is recorded in the command buffer. This means
1167        * that if the client updates the buffer contents after binding it to
1168        * a command buffer, the next queue submit of that command buffer may
1169        * not use the latest update to the buffer contents, but the data that
1170        * was present in the buffer at the time it was bound to the command
1171        * buffer.
1172        */
1173       .descriptorBindingInlineUniformBlockUpdateAfterBind = false,
1174       .pipelineCreationCacheControl = true,
1175       .privateData = true,
1176    };
1177 
1178    VkPhysicalDeviceVulkan12Features vk12 = {
1179       .hostQueryReset = true,
1180       .uniformAndStorageBuffer8BitAccess = true,
1181       .uniformBufferStandardLayout = true,
1182       /* V3D 4.2 wraps TMU vector accesses to 16-byte boundaries, so loads and
1183        * stores of vectors that cross these boundaries would not work correcly
1184        * with scalarBlockLayout and would need to be split into smaller vectors
1185        * (and/or scalars) that don't cross these boundaries. For load/stores
1186        * with dynamic offsets where we can't identify if the offset is
1187        * problematic, we would always have to scalarize. Overall, this would
1188        * not lead to best performance so let's just not support it.
1189        */
1190       .scalarBlockLayout = false,
1191       /* This tells applications 2 things:
1192        *
1193        * 1. If they can select just one aspect for barriers. For us barriers
1194        *    decide if we need to split a job and we don't care if it is only
1195        *    for one of the aspects of the image or both, so we don't really
1196        *    benefit from seeing barriers that select just one aspect.
1197        *
1198        * 2. If they can program different layouts for each aspect. We
1199        *    generally don't care about layouts, so again, we don't get any
1200        *    benefits from this to limit the scope of image layout transitions.
1201        *
1202        * Still, Vulkan 1.2 requires this feature to be supported so we
1203        * advertise it even though we don't really take advantage of it.
1204        */
1205       .separateDepthStencilLayouts = true,
1206       .storageBuffer8BitAccess = true,
1207       .storagePushConstant8 = true,
1208       .imagelessFramebuffer = true,
1209       .timelineSemaphore = true,
1210 
1211       .samplerMirrorClampToEdge = true,
1212 
1213       /* These are mandatory by Vulkan 1.2, however, we don't support any of
1214        * the optional features affected by them (non 32-bit types for
1215        * shaderSubgroupExtendedTypes and additional subgroup ballot for
1216        * subgroupBroadcastDynamicId), so in practice setting them to true
1217        * doesn't have any implications for us until we implement any of these
1218        * optional features.
1219        */
1220       .shaderSubgroupExtendedTypes = true,
1221       .subgroupBroadcastDynamicId = true,
1222 
1223       .vulkanMemoryModel = true,
1224       .vulkanMemoryModelDeviceScope = true,
1225       .vulkanMemoryModelAvailabilityVisibilityChains = true,
1226 
1227       .bufferDeviceAddress = true,
1228       .bufferDeviceAddressCaptureReplay = false,
1229       .bufferDeviceAddressMultiDevice = false,
1230    };
1231 
1232    VkPhysicalDeviceVulkan11Features vk11 = {
1233       .storageBuffer16BitAccess = true,
1234       .uniformAndStorageBuffer16BitAccess = true,
1235       .storagePushConstant16 = true,
1236       .storageInputOutput16 = false,
1237       .multiview = true,
1238       .multiviewGeometryShader = false,
1239       .multiviewTessellationShader = false,
1240       .variablePointersStorageBuffer = true,
1241       /* FIXME: this needs support for non-constant index on UBO/SSBO */
1242       .variablePointers = false,
1243       .protectedMemory = false,
1244       .samplerYcbcrConversion = false,
1245       .shaderDrawParameters = false,
1246    };
1247 
1248    vk_foreach_struct(ext, pFeatures->pNext) {
1249       if (vk_get_physical_device_core_1_1_feature_ext(ext, &vk11))
1250          continue;
1251       if (vk_get_physical_device_core_1_2_feature_ext(ext, &vk12))
1252          continue;
1253       if (vk_get_physical_device_core_1_3_feature_ext(ext, &vk13))
1254          continue;
1255 
1256       switch (ext->sType) {
1257       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {
1258          VkPhysicalDevice4444FormatsFeaturesEXT *features =
1259             (VkPhysicalDevice4444FormatsFeaturesEXT *)ext;
1260          features->formatA4R4G4B4 = true;
1261          features->formatA4B4G4R4 = true;
1262          break;
1263       }
1264 
1265       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {
1266          VkPhysicalDeviceCustomBorderColorFeaturesEXT *features =
1267             (VkPhysicalDeviceCustomBorderColorFeaturesEXT *)ext;
1268          features->customBorderColors = true;
1269          features->customBorderColorWithoutFormat = false;
1270          break;
1271       }
1272 
1273       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {
1274          VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features =
1275             (VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext;
1276          features->indexTypeUint8 = true;
1277          break;
1278       }
1279 
1280       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: {
1281          VkPhysicalDeviceLineRasterizationFeaturesEXT *features =
1282             (VkPhysicalDeviceLineRasterizationFeaturesEXT *)ext;
1283          features->rectangularLines = true;
1284          features->bresenhamLines = true;
1285          features->smoothLines = false;
1286          features->stippledRectangularLines = false;
1287          features->stippledBresenhamLines = false;
1288          features->stippledSmoothLines = false;
1289          break;
1290       }
1291 
1292       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT: {
1293           VkPhysicalDeviceColorWriteEnableFeaturesEXT *features = (void *) ext;
1294           features->colorWriteEnable = true;
1295           break;
1296       }
1297 
1298       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR: {
1299          VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *features =
1300             (VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *) ext;
1301          features->pipelineExecutableInfo = true;
1302          break;
1303       }
1304 
1305       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: {
1306          VkPhysicalDeviceProvokingVertexFeaturesEXT *features = (void *) ext;
1307          features->provokingVertexLast = true;
1308          /* FIXME: update when supporting EXT_transform_feedback */
1309          features->transformFeedbackPreservesProvokingVertex = false;
1310          break;
1311       }
1312 
1313       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
1314          VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features =
1315             (void *) ext;
1316          features->vertexAttributeInstanceRateDivisor = true;
1317          features->vertexAttributeInstanceRateZeroDivisor = false;
1318          break;
1319       }
1320 
1321       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: {
1322          VkPhysicalDevicePerformanceQueryFeaturesKHR *features =
1323             (void *) ext;
1324 
1325          features->performanceCounterQueryPools =
1326             physical_device->caps.perfmon;
1327          features->performanceCounterMultipleQueryPools = false;
1328          break;
1329       }
1330 
1331       default:
1332          v3dv_debug_ignored_stype(ext->sType);
1333          break;
1334       }
1335    }
1336 }
1337 
1338 VKAPI_ATTR void VKAPI_CALL
v3dv_GetDeviceGroupPeerMemoryFeatures(VkDevice device,uint32_t heapIndex,uint32_t localDeviceIndex,uint32_t remoteDeviceIndex,VkPeerMemoryFeatureFlags * pPeerMemoryFeatures)1339 v3dv_GetDeviceGroupPeerMemoryFeatures(VkDevice device,
1340                                       uint32_t heapIndex,
1341                                       uint32_t localDeviceIndex,
1342                                       uint32_t remoteDeviceIndex,
1343                                       VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)
1344 {
1345    assert(localDeviceIndex == 0 && remoteDeviceIndex == 0);
1346    *pPeerMemoryFeatures = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT |
1347                           VK_PEER_MEMORY_FEATURE_COPY_DST_BIT |
1348                           VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT |
1349                           VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT;
1350 }
1351 
1352 uint32_t
v3dv_physical_device_vendor_id(struct v3dv_physical_device * dev)1353 v3dv_physical_device_vendor_id(struct v3dv_physical_device *dev)
1354 {
1355    return 0x14E4; /* Broadcom */
1356 }
1357 
1358 uint32_t
v3dv_physical_device_device_id(struct v3dv_physical_device * dev)1359 v3dv_physical_device_device_id(struct v3dv_physical_device *dev)
1360 {
1361 #if using_v3d_simulator
1362    return dev->device_id;
1363 #else
1364    switch (dev->devinfo.ver) {
1365    case 42:
1366       return 0xBE485FD3; /* Broadcom deviceID for 2711 */
1367    default:
1368       unreachable("Unsupported V3D version");
1369    }
1370 #endif
1371 }
1372 
1373 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,VkPhysicalDeviceProperties * pProperties)1374 v3dv_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
1375                                  VkPhysicalDeviceProperties *pProperties)
1376 {
1377    V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice);
1378 
1379    STATIC_ASSERT(MAX_SAMPLED_IMAGES + MAX_STORAGE_IMAGES + MAX_INPUT_ATTACHMENTS
1380                  <= V3D_MAX_TEXTURE_SAMPLERS);
1381    STATIC_ASSERT(MAX_UNIFORM_BUFFERS >= MAX_DYNAMIC_UNIFORM_BUFFERS);
1382    STATIC_ASSERT(MAX_STORAGE_BUFFERS >= MAX_DYNAMIC_STORAGE_BUFFERS);
1383 
1384    const uint32_t page_size = 4096;
1385    const uint32_t mem_size = compute_heap_size();
1386 
1387    const uint32_t max_varying_components = 16 * 4;
1388 
1389    const float v3d_point_line_granularity = 2.0f / (1 << V3D_COORD_SHIFT);
1390    const uint32_t max_fb_size = V3D_MAX_IMAGE_DIMENSION;
1391 
1392    const VkSampleCountFlags supported_sample_counts =
1393       VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT;
1394 
1395    struct timespec clock_res;
1396    clock_getres(CLOCK_MONOTONIC, &clock_res);
1397    const float timestamp_period =
1398       clock_res.tv_sec * 1000000000.0f + clock_res.tv_nsec;
1399 
1400    /* FIXME: this will probably require an in-depth review */
1401    VkPhysicalDeviceLimits limits = {
1402       .maxImageDimension1D                      = V3D_MAX_IMAGE_DIMENSION,
1403       .maxImageDimension2D                      = V3D_MAX_IMAGE_DIMENSION,
1404       .maxImageDimension3D                      = V3D_MAX_IMAGE_DIMENSION,
1405       .maxImageDimensionCube                    = V3D_MAX_IMAGE_DIMENSION,
1406       .maxImageArrayLayers                      = V3D_MAX_ARRAY_LAYERS,
1407       .maxTexelBufferElements                   = (1ul << 28),
1408       .maxUniformBufferRange                    = V3D_MAX_BUFFER_RANGE,
1409       .maxStorageBufferRange                    = V3D_MAX_BUFFER_RANGE,
1410       .maxPushConstantsSize                     = MAX_PUSH_CONSTANTS_SIZE,
1411       .maxMemoryAllocationCount                 = mem_size / page_size,
1412       .maxSamplerAllocationCount                = 64 * 1024,
1413       .bufferImageGranularity                   = V3D_NON_COHERENT_ATOM_SIZE,
1414       .sparseAddressSpaceSize                   = 0,
1415       .maxBoundDescriptorSets                   = MAX_SETS,
1416       .maxPerStageDescriptorSamplers            = V3D_MAX_TEXTURE_SAMPLERS,
1417       .maxPerStageDescriptorUniformBuffers      = MAX_UNIFORM_BUFFERS,
1418       .maxPerStageDescriptorStorageBuffers      = MAX_STORAGE_BUFFERS,
1419       .maxPerStageDescriptorSampledImages       = MAX_SAMPLED_IMAGES,
1420       .maxPerStageDescriptorStorageImages       = MAX_STORAGE_IMAGES,
1421       .maxPerStageDescriptorInputAttachments    = MAX_INPUT_ATTACHMENTS,
1422       .maxPerStageResources                     = 128,
1423 
1424       /* Some of these limits are multiplied by 6 because they need to
1425        * include all possible shader stages (even if not supported). See
1426        * 'Required Limits' table in the Vulkan spec.
1427        */
1428       .maxDescriptorSetSamplers                 = 6 * V3D_MAX_TEXTURE_SAMPLERS,
1429       .maxDescriptorSetUniformBuffers           = 6 * MAX_UNIFORM_BUFFERS,
1430       .maxDescriptorSetUniformBuffersDynamic    = MAX_DYNAMIC_UNIFORM_BUFFERS,
1431       .maxDescriptorSetStorageBuffers           = 6 * MAX_STORAGE_BUFFERS,
1432       .maxDescriptorSetStorageBuffersDynamic    = MAX_DYNAMIC_STORAGE_BUFFERS,
1433       .maxDescriptorSetSampledImages            = 6 * MAX_SAMPLED_IMAGES,
1434       .maxDescriptorSetStorageImages            = 6 * MAX_STORAGE_IMAGES,
1435       .maxDescriptorSetInputAttachments         = MAX_INPUT_ATTACHMENTS,
1436 
1437       /* Vertex limits */
1438       .maxVertexInputAttributes                 = MAX_VERTEX_ATTRIBS,
1439       .maxVertexInputBindings                   = MAX_VBS,
1440       .maxVertexInputAttributeOffset            = 0xffffffff,
1441       .maxVertexInputBindingStride              = 0xffffffff,
1442       .maxVertexOutputComponents                = max_varying_components,
1443 
1444       /* Tessellation limits */
1445       .maxTessellationGenerationLevel           = 0,
1446       .maxTessellationPatchSize                 = 0,
1447       .maxTessellationControlPerVertexInputComponents = 0,
1448       .maxTessellationControlPerVertexOutputComponents = 0,
1449       .maxTessellationControlPerPatchOutputComponents = 0,
1450       .maxTessellationControlTotalOutputComponents = 0,
1451       .maxTessellationEvaluationInputComponents = 0,
1452       .maxTessellationEvaluationOutputComponents = 0,
1453 
1454       /* Geometry limits */
1455       .maxGeometryShaderInvocations             = 32,
1456       .maxGeometryInputComponents               = 64,
1457       .maxGeometryOutputComponents              = 64,
1458       .maxGeometryOutputVertices                = 256,
1459       .maxGeometryTotalOutputComponents         = 1024,
1460 
1461       /* Fragment limits */
1462       .maxFragmentInputComponents               = max_varying_components,
1463       .maxFragmentOutputAttachments             = 4,
1464       .maxFragmentDualSrcAttachments            = 0,
1465       .maxFragmentCombinedOutputResources       = MAX_RENDER_TARGETS +
1466                                                   MAX_STORAGE_BUFFERS +
1467                                                   MAX_STORAGE_IMAGES,
1468 
1469       /* Compute limits */
1470       .maxComputeSharedMemorySize               = 16384,
1471       .maxComputeWorkGroupCount                 = { 65535, 65535, 65535 },
1472       .maxComputeWorkGroupInvocations           = 256,
1473       .maxComputeWorkGroupSize                  = { 256, 256, 256 },
1474 
1475       .subPixelPrecisionBits                    = V3D_COORD_SHIFT,
1476       .subTexelPrecisionBits                    = 8,
1477       .mipmapPrecisionBits                      = 8,
1478       .maxDrawIndexedIndexValue                 = 0x00ffffff,
1479       .maxDrawIndirectCount                     = 0x7fffffff,
1480       .maxSamplerLodBias                        = 14.0f,
1481       .maxSamplerAnisotropy                     = 16.0f,
1482       .maxViewports                             = MAX_VIEWPORTS,
1483       .maxViewportDimensions                    = { max_fb_size, max_fb_size },
1484       .viewportBoundsRange                      = { -2.0 * max_fb_size,
1485                                                     2.0 * max_fb_size - 1 },
1486       .viewportSubPixelBits                     = 0,
1487       .minMemoryMapAlignment                    = page_size,
1488       .minTexelBufferOffsetAlignment            = V3D_UIFBLOCK_SIZE,
1489       .minUniformBufferOffsetAlignment          = 32,
1490       .minStorageBufferOffsetAlignment          = 32,
1491       .minTexelOffset                           = -8,
1492       .maxTexelOffset                           = 7,
1493       .minTexelGatherOffset                     = -8,
1494       .maxTexelGatherOffset                     = 7,
1495       .minInterpolationOffset                   = -0.5,
1496       .maxInterpolationOffset                   = 0.5,
1497       .subPixelInterpolationOffsetBits          = V3D_COORD_SHIFT,
1498       .maxFramebufferWidth                      = max_fb_size,
1499       .maxFramebufferHeight                     = max_fb_size,
1500       .maxFramebufferLayers                     = 256,
1501       .framebufferColorSampleCounts             = supported_sample_counts,
1502       .framebufferDepthSampleCounts             = supported_sample_counts,
1503       .framebufferStencilSampleCounts           = supported_sample_counts,
1504       .framebufferNoAttachmentsSampleCounts     = supported_sample_counts,
1505       .maxColorAttachments                      = MAX_RENDER_TARGETS,
1506       .sampledImageColorSampleCounts            = supported_sample_counts,
1507       .sampledImageIntegerSampleCounts          = supported_sample_counts,
1508       .sampledImageDepthSampleCounts            = supported_sample_counts,
1509       .sampledImageStencilSampleCounts          = supported_sample_counts,
1510       .storageImageSampleCounts                 = VK_SAMPLE_COUNT_1_BIT,
1511       .maxSampleMaskWords                       = 1,
1512       .timestampComputeAndGraphics              = true,
1513       .timestampPeriod                          = timestamp_period,
1514       .maxClipDistances                         = 8,
1515       .maxCullDistances                         = 0,
1516       .maxCombinedClipAndCullDistances          = 8,
1517       .discreteQueuePriorities                  = 2,
1518       .pointSizeRange                           = { v3d_point_line_granularity,
1519                                                     V3D_MAX_POINT_SIZE },
1520       .lineWidthRange                           = { 1.0f, V3D_MAX_LINE_WIDTH },
1521       .pointSizeGranularity                     = v3d_point_line_granularity,
1522       .lineWidthGranularity                     = v3d_point_line_granularity,
1523       .strictLines                              = true,
1524       .standardSampleLocations                  = false,
1525       .optimalBufferCopyOffsetAlignment         = 32,
1526       .optimalBufferCopyRowPitchAlignment       = 32,
1527       .nonCoherentAtomSize                      = V3D_NON_COHERENT_ATOM_SIZE,
1528    };
1529 
1530    *pProperties = (VkPhysicalDeviceProperties) {
1531       .apiVersion = V3DV_API_VERSION,
1532       .driverVersion = vk_get_driver_version(),
1533       .vendorID = v3dv_physical_device_vendor_id(pdevice),
1534       .deviceID = v3dv_physical_device_device_id(pdevice),
1535       .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
1536       .limits = limits,
1537       .sparseProperties = { 0 },
1538    };
1539 
1540    snprintf(pProperties->deviceName, sizeof(pProperties->deviceName),
1541             "%s", pdevice->name);
1542    memcpy(pProperties->pipelineCacheUUID,
1543           pdevice->pipeline_cache_uuid, VK_UUID_SIZE);
1544 }
1545 
1546 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceProperties2 * pProperties)1547 v3dv_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
1548                                   VkPhysicalDeviceProperties2 *pProperties)
1549 {
1550    V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice);
1551 
1552    v3dv_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
1553 
1554    /* We don't really have special restrictions for the maximum
1555     * descriptors per set, other than maybe not exceeding the limits
1556     * of addressable memory in a single allocation on either the host
1557     * or the GPU. This will be a much larger limit than any of the
1558     * per-stage limits already available in Vulkan though, so in practice,
1559     * it is not expected to limit anything beyond what is already
1560     * constrained through per-stage limits.
1561     */
1562    const uint32_t max_host_descriptors =
1563       (UINT32_MAX - sizeof(struct v3dv_descriptor_set)) /
1564       sizeof(struct v3dv_descriptor);
1565    const uint32_t max_gpu_descriptors =
1566       (UINT32_MAX / v3dv_X(pdevice, max_descriptor_bo_size)());
1567 
1568    VkPhysicalDeviceVulkan13Properties vk13 = {
1569       .maxInlineUniformBlockSize = 4096,
1570       .maxPerStageDescriptorInlineUniformBlocks = MAX_INLINE_UNIFORM_BUFFERS,
1571       .maxDescriptorSetInlineUniformBlocks = MAX_INLINE_UNIFORM_BUFFERS,
1572       .maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks =
1573          MAX_INLINE_UNIFORM_BUFFERS,
1574       .maxDescriptorSetUpdateAfterBindInlineUniformBlocks =
1575          MAX_INLINE_UNIFORM_BUFFERS,
1576    };
1577 
1578    VkPhysicalDeviceVulkan12Properties vk12 = {
1579       .driverID = VK_DRIVER_ID_MESA_V3DV,
1580       .conformanceVersion = {
1581          .major = 1,
1582          .minor = 2,
1583          .subminor = 7,
1584          .patch = 1,
1585       },
1586       .supportedDepthResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
1587       .supportedStencilResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT,
1588       /* FIXME: if we want to support independentResolveNone then we would
1589        * need to honor attachment load operations on resolve attachments,
1590        * which we currently ignore because the resolve makes them irrelevant,
1591        * as it unconditionally writes all pixels in the render area. However,
1592        * with independentResolveNone, it is possible to have one aspect of a
1593        * D/S resolve attachment stay unresolved, in which case the attachment
1594        * load operation is relevant.
1595        *
1596        * NOTE: implementing attachment load for resolve attachments isn't
1597        * immediately trivial because these attachments are not part of the
1598        * framebuffer and therefore we can't use the same mechanism we use
1599        * for framebuffer attachments. Instead, we should probably have to
1600        * emit a meta operation for that right at the start of the render
1601        * pass (or subpass).
1602        */
1603       .independentResolveNone = false,
1604       .independentResolve = false,
1605       .maxTimelineSemaphoreValueDifference = UINT64_MAX,
1606 
1607       .denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL,
1608       .roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL,
1609       .shaderSignedZeroInfNanPreserveFloat16 = true,
1610       .shaderSignedZeroInfNanPreserveFloat32 = true,
1611       .shaderSignedZeroInfNanPreserveFloat64 = false,
1612       .shaderDenormPreserveFloat16 = true,
1613       .shaderDenormPreserveFloat32 = true,
1614       .shaderDenormPreserveFloat64 = false,
1615       .shaderDenormFlushToZeroFloat16 = false,
1616       .shaderDenormFlushToZeroFloat32 = false,
1617       .shaderDenormFlushToZeroFloat64 = false,
1618       .shaderRoundingModeRTEFloat16 = true,
1619       .shaderRoundingModeRTEFloat32 = true,
1620       .shaderRoundingModeRTEFloat64 = false,
1621       .shaderRoundingModeRTZFloat16 = false,
1622       .shaderRoundingModeRTZFloat32 = false,
1623       .shaderRoundingModeRTZFloat64 = false,
1624 
1625       /* V3D doesn't support min/max filtering */
1626       .filterMinmaxSingleComponentFormats = false,
1627       .filterMinmaxImageComponentMapping = false,
1628 
1629       .framebufferIntegerColorSampleCounts =
1630          VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT,
1631    };
1632    memset(vk12.driverName, 0, VK_MAX_DRIVER_NAME_SIZE);
1633    snprintf(vk12.driverName, VK_MAX_DRIVER_NAME_SIZE, "V3DV Mesa");
1634    memset(vk12.driverInfo, 0, VK_MAX_DRIVER_INFO_SIZE);
1635    snprintf(vk12.driverInfo, VK_MAX_DRIVER_INFO_SIZE,
1636             "Mesa " PACKAGE_VERSION MESA_GIT_SHA1);
1637 
1638    VkPhysicalDeviceVulkan11Properties vk11 = {
1639       .deviceLUIDValid = false,
1640       .subgroupSize = V3D_CHANNELS,
1641       .subgroupSupportedStages = VK_SHADER_STAGE_COMPUTE_BIT,
1642       .subgroupSupportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT,
1643       .subgroupQuadOperationsInAllStages = false,
1644       .pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES,
1645       .maxMultiviewViewCount = MAX_MULTIVIEW_VIEW_COUNT,
1646       .maxMultiviewInstanceIndex = UINT32_MAX - 1,
1647       .protectedNoFault = false,
1648       .maxPerSetDescriptors = MIN2(max_host_descriptors, max_gpu_descriptors),
1649       /* Minimum required by the spec */
1650       .maxMemoryAllocationSize = MAX_MEMORY_ALLOCATION_SIZE,
1651    };
1652    memcpy(vk11.deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
1653    memcpy(vk11.driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
1654 
1655 
1656    vk_foreach_struct(ext, pProperties->pNext) {
1657       if (vk_get_physical_device_core_1_1_property_ext(ext, &vk11))
1658          continue;
1659       if (vk_get_physical_device_core_1_2_property_ext(ext, &vk12))
1660          continue;
1661       if (vk_get_physical_device_core_1_3_property_ext(ext, &vk13))
1662          continue;
1663 
1664       switch (ext->sType) {
1665       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: {
1666          VkPhysicalDeviceCustomBorderColorPropertiesEXT *props =
1667             (VkPhysicalDeviceCustomBorderColorPropertiesEXT *)ext;
1668          props->maxCustomBorderColorSamplers = V3D_MAX_TEXTURE_SAMPLERS;
1669          break;
1670       }
1671       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT: {
1672          VkPhysicalDeviceProvokingVertexPropertiesEXT *props =
1673             (VkPhysicalDeviceProvokingVertexPropertiesEXT *)ext;
1674          props->provokingVertexModePerPipeline = true;
1675          /* FIXME: update when supporting EXT_transform_feedback */
1676          props->transformFeedbackPreservesTriangleFanProvokingVertex = false;
1677          break;
1678       }
1679       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
1680          VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *props =
1681             (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext;
1682          props->maxVertexAttribDivisor = 0xffff;
1683          break;
1684       }
1685       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR : {
1686          VkPhysicalDevicePerformanceQueryPropertiesKHR *props =
1687             (VkPhysicalDevicePerformanceQueryPropertiesKHR *)ext;
1688 
1689          props->allowCommandBufferQueryCopies = true;
1690          break;
1691       }
1692       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT: {
1693          VkPhysicalDeviceDrmPropertiesEXT *props =
1694             (VkPhysicalDeviceDrmPropertiesEXT *)ext;
1695          props->hasPrimary = pdevice->has_primary;
1696          if (props->hasPrimary) {
1697             props->primaryMajor = (int64_t) major(pdevice->primary_devid);
1698             props->primaryMinor = (int64_t) minor(pdevice->primary_devid);
1699          }
1700          props->hasRender = pdevice->has_render;
1701          if (props->hasRender) {
1702             props->renderMajor = (int64_t) major(pdevice->render_devid);
1703             props->renderMinor = (int64_t) minor(pdevice->render_devid);
1704          }
1705          break;
1706       }
1707       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: {
1708          VkPhysicalDeviceLineRasterizationPropertiesEXT *props =
1709             (VkPhysicalDeviceLineRasterizationPropertiesEXT *)ext;
1710          props->lineSubPixelPrecisionBits = V3D_COORD_SHIFT;
1711          break;
1712       }
1713       case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT:
1714          /* Do nothing, not even logging. This is a non-PCI device, so we will
1715           * never provide this extension.
1716           */
1717          break;
1718       default:
1719          v3dv_debug_ignored_stype(ext->sType);
1720          break;
1721       }
1722    }
1723 }
1724 
1725 /* We support exactly one queue family. */
1726 static const VkQueueFamilyProperties
1727 v3dv_queue_family_properties = {
1728    .queueFlags = VK_QUEUE_GRAPHICS_BIT |
1729                  VK_QUEUE_COMPUTE_BIT |
1730                  VK_QUEUE_TRANSFER_BIT,
1731    .queueCount = 1,
1732    .timestampValidBits = 64,
1733    .minImageTransferGranularity = { 1, 1, 1 },
1734 };
1735 
1736 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties2 * pQueueFamilyProperties)1737 v3dv_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
1738                                              uint32_t *pQueueFamilyPropertyCount,
1739                                              VkQueueFamilyProperties2 *pQueueFamilyProperties)
1740 {
1741    VK_OUTARRAY_MAKE_TYPED(VkQueueFamilyProperties2, out,
1742                           pQueueFamilyProperties, pQueueFamilyPropertyCount);
1743 
1744    vk_outarray_append_typed(VkQueueFamilyProperties2, &out, p) {
1745       p->queueFamilyProperties = v3dv_queue_family_properties;
1746 
1747       vk_foreach_struct(s, p->pNext) {
1748          v3dv_debug_ignored_stype(s->sType);
1749       }
1750    }
1751 }
1752 
1753 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,VkPhysicalDeviceMemoryProperties * pMemoryProperties)1754 v3dv_GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice,
1755                                        VkPhysicalDeviceMemoryProperties *pMemoryProperties)
1756 {
1757    V3DV_FROM_HANDLE(v3dv_physical_device, device, physicalDevice);
1758    *pMemoryProperties = device->memory;
1759 }
1760 
1761 VKAPI_ATTR void VKAPI_CALL
v3dv_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceMemoryProperties2 * pMemoryProperties)1762 v3dv_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,
1763                                         VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
1764 {
1765    v3dv_GetPhysicalDeviceMemoryProperties(physicalDevice,
1766                                           &pMemoryProperties->memoryProperties);
1767 
1768    vk_foreach_struct(ext, pMemoryProperties->pNext) {
1769       switch (ext->sType) {
1770       default:
1771          v3dv_debug_ignored_stype(ext->sType);
1772          break;
1773       }
1774    }
1775 }
1776 
1777 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
v3dv_GetInstanceProcAddr(VkInstance _instance,const char * pName)1778 v3dv_GetInstanceProcAddr(VkInstance _instance,
1779                          const char *pName)
1780 {
1781    V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
1782    return vk_instance_get_proc_addr(&instance->vk,
1783                                     &v3dv_instance_entrypoints,
1784                                     pName);
1785 }
1786 
1787 /* With version 1+ of the loader interface the ICD should expose
1788  * vk_icdGetInstanceProcAddr to work around certain LD_PRELOAD issues seen in apps.
1789  */
1790 PUBLIC
1791 VKAPI_ATTR PFN_vkVoidFunction
1792 VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance,
1793                                      const char *pName);
1794 
1795 PUBLIC
1796 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance,const char * pName)1797 vk_icdGetInstanceProcAddr(VkInstance instance,
1798                           const char*                                 pName)
1799 {
1800    return v3dv_GetInstanceProcAddr(instance, pName);
1801 }
1802 
1803 /* With version 4+ of the loader interface the ICD should expose
1804  * vk_icdGetPhysicalDeviceProcAddr()
1805  */
1806 PUBLIC
1807 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1808 vk_icdGetPhysicalDeviceProcAddr(VkInstance  _instance,
1809                                 const char* pName);
1810 
1811 PFN_vkVoidFunction
vk_icdGetPhysicalDeviceProcAddr(VkInstance _instance,const char * pName)1812 vk_icdGetPhysicalDeviceProcAddr(VkInstance  _instance,
1813                                 const char* pName)
1814 {
1815    V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
1816 
1817    return vk_instance_get_physical_device_proc_addr(&instance->vk, pName);
1818 }
1819 
1820 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_EnumerateInstanceLayerProperties(uint32_t * pPropertyCount,VkLayerProperties * pProperties)1821 v3dv_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
1822                                       VkLayerProperties *pProperties)
1823 {
1824    if (pProperties == NULL) {
1825       *pPropertyCount = 0;
1826       return VK_SUCCESS;
1827    }
1828 
1829    return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1830 }
1831 
1832 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,uint32_t * pPropertyCount,VkLayerProperties * pProperties)1833 v3dv_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
1834                                     uint32_t *pPropertyCount,
1835                                     VkLayerProperties *pProperties)
1836 {
1837    V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
1838 
1839    if (pProperties == NULL) {
1840       *pPropertyCount = 0;
1841       return VK_SUCCESS;
1842    }
1843 
1844    return vk_error(physical_device, VK_ERROR_LAYER_NOT_PRESENT);
1845 }
1846 
1847 static void
destroy_queue_syncs(struct v3dv_queue * queue)1848 destroy_queue_syncs(struct v3dv_queue *queue)
1849 {
1850    for (int i = 0; i < V3DV_QUEUE_COUNT; i++) {
1851       if (queue->last_job_syncs.syncs[i]) {
1852          drmSyncobjDestroy(queue->device->pdevice->render_fd,
1853                            queue->last_job_syncs.syncs[i]);
1854       }
1855    }
1856 }
1857 
1858 static VkResult
queue_init(struct v3dv_device * device,struct v3dv_queue * queue,const VkDeviceQueueCreateInfo * create_info,uint32_t index_in_family)1859 queue_init(struct v3dv_device *device, struct v3dv_queue *queue,
1860            const VkDeviceQueueCreateInfo *create_info,
1861            uint32_t index_in_family)
1862 {
1863    VkResult result = vk_queue_init(&queue->vk, &device->vk, create_info,
1864                                    index_in_family);
1865    if (result != VK_SUCCESS)
1866       return result;
1867 
1868    result = vk_queue_enable_submit_thread(&queue->vk);
1869    if (result != VK_SUCCESS)
1870       goto fail_submit_thread;
1871 
1872    queue->device = device;
1873    queue->vk.driver_submit = v3dv_queue_driver_submit;
1874 
1875    for (int i = 0; i < V3DV_QUEUE_COUNT; i++) {
1876       queue->last_job_syncs.first[i] = true;
1877       int ret = drmSyncobjCreate(device->pdevice->render_fd,
1878                                  DRM_SYNCOBJ_CREATE_SIGNALED,
1879                                  &queue->last_job_syncs.syncs[i]);
1880       if (ret) {
1881          result = vk_errorf(device, VK_ERROR_INITIALIZATION_FAILED,
1882                             "syncobj create failed: %m");
1883          goto fail_last_job_syncs;
1884       }
1885    }
1886 
1887    queue->noop_job = NULL;
1888    return VK_SUCCESS;
1889 
1890 fail_last_job_syncs:
1891    destroy_queue_syncs(queue);
1892 fail_submit_thread:
1893    vk_queue_finish(&queue->vk);
1894    return result;
1895 }
1896 
1897 static void
queue_finish(struct v3dv_queue * queue)1898 queue_finish(struct v3dv_queue *queue)
1899 {
1900    if (queue->noop_job)
1901       v3dv_job_destroy(queue->noop_job);
1902    destroy_queue_syncs(queue);
1903    vk_queue_finish(&queue->vk);
1904 }
1905 
1906 static void
init_device_meta(struct v3dv_device * device)1907 init_device_meta(struct v3dv_device *device)
1908 {
1909    mtx_init(&device->meta.mtx, mtx_plain);
1910    v3dv_meta_clear_init(device);
1911    v3dv_meta_blit_init(device);
1912    v3dv_meta_texel_buffer_copy_init(device);
1913 }
1914 
1915 static void
destroy_device_meta(struct v3dv_device * device)1916 destroy_device_meta(struct v3dv_device *device)
1917 {
1918    mtx_destroy(&device->meta.mtx);
1919    v3dv_meta_clear_finish(device);
1920    v3dv_meta_blit_finish(device);
1921    v3dv_meta_texel_buffer_copy_finish(device);
1922 }
1923 
1924 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_CreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)1925 v3dv_CreateDevice(VkPhysicalDevice physicalDevice,
1926                   const VkDeviceCreateInfo *pCreateInfo,
1927                   const VkAllocationCallbacks *pAllocator,
1928                   VkDevice *pDevice)
1929 {
1930    V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
1931    struct v3dv_instance *instance = (struct v3dv_instance*) physical_device->vk.instance;
1932    VkResult result;
1933    struct v3dv_device *device;
1934 
1935    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
1936 
1937    /* Check requested queues (we only expose one queue ) */
1938    assert(pCreateInfo->queueCreateInfoCount == 1);
1939    for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
1940       assert(pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex == 0);
1941       assert(pCreateInfo->pQueueCreateInfos[i].queueCount == 1);
1942       if (pCreateInfo->pQueueCreateInfos[i].flags != 0)
1943          return vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
1944    }
1945 
1946    device = vk_zalloc2(&physical_device->vk.instance->alloc, pAllocator,
1947                        sizeof(*device), 8,
1948                        VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1949    if (!device)
1950       return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1951 
1952    struct vk_device_dispatch_table dispatch_table;
1953    vk_device_dispatch_table_from_entrypoints(&dispatch_table,
1954                                              &v3dv_device_entrypoints, true);
1955    vk_device_dispatch_table_from_entrypoints(&dispatch_table,
1956                                              &wsi_device_entrypoints, false);
1957    result = vk_device_init(&device->vk, &physical_device->vk,
1958                            &dispatch_table, pCreateInfo, pAllocator);
1959    if (result != VK_SUCCESS) {
1960       vk_free(&device->vk.alloc, device);
1961       return vk_error(NULL, result);
1962    }
1963 
1964    device->instance = instance;
1965    device->pdevice = physical_device;
1966 
1967    mtx_init(&device->query_mutex, mtx_plain);
1968    cnd_init(&device->query_ended);
1969 
1970    vk_device_set_drm_fd(&device->vk, physical_device->render_fd);
1971    vk_device_enable_threaded_submit(&device->vk);
1972 
1973    result = queue_init(device, &device->queue,
1974                        pCreateInfo->pQueueCreateInfos, 0);
1975    if (result != VK_SUCCESS)
1976       goto fail;
1977 
1978    device->devinfo = physical_device->devinfo;
1979 
1980    /* Vulkan 1.1 and VK_KHR_get_physical_device_properties2 added
1981     * VkPhysicalDeviceFeatures2 which can be used in the pNext chain of
1982     * vkDeviceCreateInfo, in which case it should be used instead of
1983     * pEnabledFeatures.
1984     */
1985    const VkPhysicalDeviceFeatures2 *features2 =
1986       vk_find_struct_const(pCreateInfo->pNext, PHYSICAL_DEVICE_FEATURES_2);
1987    if (features2) {
1988       memcpy(&device->features, &features2->features,
1989              sizeof(device->features));
1990    } else  if (pCreateInfo->pEnabledFeatures) {
1991       memcpy(&device->features, pCreateInfo->pEnabledFeatures,
1992              sizeof(device->features));
1993    }
1994 
1995    if (device->features.robustBufferAccess)
1996       perf_debug("Device created with Robust Buffer Access enabled.\n");
1997 
1998 #ifdef DEBUG
1999    v3dv_X(device, device_check_prepacked_sizes)();
2000 #endif
2001    init_device_meta(device);
2002    v3dv_bo_cache_init(device);
2003    v3dv_pipeline_cache_init(&device->default_pipeline_cache, device, 0,
2004                             device->instance->default_pipeline_cache_enabled);
2005    device->default_attribute_float =
2006       v3dv_pipeline_create_default_attribute_values(device, NULL);
2007 
2008    device->device_address_mem_ctx = ralloc_context(NULL);
2009    util_dynarray_init(&device->device_address_bo_list,
2010                       device->device_address_mem_ctx);
2011 
2012    *pDevice = v3dv_device_to_handle(device);
2013 
2014    return VK_SUCCESS;
2015 
2016 fail:
2017    cnd_destroy(&device->query_ended);
2018    mtx_destroy(&device->query_mutex);
2019    queue_finish(&device->queue);
2020    destroy_device_meta(device);
2021    v3dv_pipeline_cache_finish(&device->default_pipeline_cache);
2022    vk_device_finish(&device->vk);
2023    vk_free(&device->vk.alloc, device);
2024 
2025    return result;
2026 }
2027 
2028 VKAPI_ATTR void VKAPI_CALL
v3dv_DestroyDevice(VkDevice _device,const VkAllocationCallbacks * pAllocator)2029 v3dv_DestroyDevice(VkDevice _device,
2030                    const VkAllocationCallbacks *pAllocator)
2031 {
2032    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2033 
2034    device->vk.dispatch_table.DeviceWaitIdle(_device);
2035    queue_finish(&device->queue);
2036    destroy_device_meta(device);
2037    v3dv_pipeline_cache_finish(&device->default_pipeline_cache);
2038 
2039    if (device->default_attribute_float) {
2040       v3dv_bo_free(device, device->default_attribute_float);
2041       device->default_attribute_float = NULL;
2042    }
2043 
2044    ralloc_free(device->device_address_mem_ctx);
2045 
2046    /* Bo cache should be removed the last, as any other object could be
2047     * freeing their private bos
2048     */
2049    v3dv_bo_cache_destroy(device);
2050 
2051    cnd_destroy(&device->query_ended);
2052    mtx_destroy(&device->query_mutex);
2053 
2054    vk_device_finish(&device->vk);
2055    vk_free2(&device->vk.alloc, pAllocator, device);
2056 }
2057 
2058 static VkResult
device_alloc(struct v3dv_device * device,struct v3dv_device_memory * mem,VkDeviceSize size)2059 device_alloc(struct v3dv_device *device,
2060              struct v3dv_device_memory *mem,
2061              VkDeviceSize size)
2062 {
2063    /* Our kernel interface is 32-bit */
2064    assert(size <= UINT32_MAX);
2065 
2066    mem->bo = v3dv_bo_alloc(device, size, "device_alloc", false);
2067    if (!mem->bo)
2068       return VK_ERROR_OUT_OF_DEVICE_MEMORY;
2069 
2070    return VK_SUCCESS;
2071 }
2072 
2073 static void
device_free_wsi_dumb(int32_t display_fd,int32_t dumb_handle)2074 device_free_wsi_dumb(int32_t display_fd, int32_t dumb_handle)
2075 {
2076    assert(display_fd != -1);
2077    if (dumb_handle < 0)
2078       return;
2079 
2080    struct drm_mode_destroy_dumb destroy_dumb = {
2081       .handle = dumb_handle,
2082    };
2083    if (v3dv_ioctl(display_fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb)) {
2084       fprintf(stderr, "destroy dumb object %d: %s\n", dumb_handle, strerror(errno));
2085    }
2086 }
2087 
2088 static void
device_free(struct v3dv_device * device,struct v3dv_device_memory * mem)2089 device_free(struct v3dv_device *device, struct v3dv_device_memory *mem)
2090 {
2091    /* If this memory allocation was for WSI, then we need to use the
2092     * display device to free the allocated dumb BO.
2093     */
2094    if (mem->is_for_wsi) {
2095       device_free_wsi_dumb(device->instance->physicalDevice.display_fd,
2096                            mem->bo->dumb_handle);
2097    }
2098 
2099    v3dv_bo_free(device, mem->bo);
2100 }
2101 
2102 static void
device_unmap(struct v3dv_device * device,struct v3dv_device_memory * mem)2103 device_unmap(struct v3dv_device *device, struct v3dv_device_memory *mem)
2104 {
2105    assert(mem && mem->bo->map && mem->bo->map_size > 0);
2106    v3dv_bo_unmap(device, mem->bo);
2107 }
2108 
2109 static VkResult
device_map(struct v3dv_device * device,struct v3dv_device_memory * mem)2110 device_map(struct v3dv_device *device, struct v3dv_device_memory *mem)
2111 {
2112    assert(mem && mem->bo);
2113 
2114    /* From the spec:
2115     *
2116     *   "After a successful call to vkMapMemory the memory object memory is
2117     *   considered to be currently host mapped. It is an application error to
2118     *   call vkMapMemory on a memory object that is already host mapped."
2119     *
2120     * We are not concerned with this ourselves (validation layers should
2121     * catch these errors and warn users), however, the driver may internally
2122     * map things (for example for debug CLIF dumps or some CPU-side operations)
2123     * so by the time the user calls here the buffer might already been mapped
2124     * internally by the driver.
2125     */
2126    if (mem->bo->map) {
2127       assert(mem->bo->map_size == mem->bo->size);
2128       return VK_SUCCESS;
2129    }
2130 
2131    bool ok = v3dv_bo_map(device, mem->bo, mem->bo->size);
2132    if (!ok)
2133       return VK_ERROR_MEMORY_MAP_FAILED;
2134 
2135    return VK_SUCCESS;
2136 }
2137 
2138 static VkResult
device_import_bo(struct v3dv_device * device,const VkAllocationCallbacks * pAllocator,int fd,uint64_t size,struct v3dv_bo ** bo)2139 device_import_bo(struct v3dv_device *device,
2140                  const VkAllocationCallbacks *pAllocator,
2141                  int fd, uint64_t size,
2142                  struct v3dv_bo **bo)
2143 {
2144    *bo = NULL;
2145 
2146    off_t real_size = lseek(fd, 0, SEEK_END);
2147    lseek(fd, 0, SEEK_SET);
2148    if (real_size < 0 || (uint64_t) real_size < size)
2149       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
2150 
2151    int render_fd = device->pdevice->render_fd;
2152    assert(render_fd >= 0);
2153 
2154    int ret;
2155    uint32_t handle;
2156    ret = drmPrimeFDToHandle(render_fd, fd, &handle);
2157    if (ret)
2158       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
2159 
2160    struct drm_v3d_get_bo_offset get_offset = {
2161       .handle = handle,
2162    };
2163    ret = v3dv_ioctl(render_fd, DRM_IOCTL_V3D_GET_BO_OFFSET, &get_offset);
2164    if (ret)
2165       return VK_ERROR_INVALID_EXTERNAL_HANDLE;
2166    assert(get_offset.offset != 0);
2167 
2168    *bo = v3dv_device_lookup_bo(device->pdevice, handle);
2169    assert(*bo);
2170 
2171    if ((*bo)->refcnt == 0)
2172       v3dv_bo_init(*bo, handle, size, get_offset.offset, "import", false);
2173    else
2174       p_atomic_inc(&(*bo)->refcnt);
2175 
2176    return VK_SUCCESS;
2177 }
2178 
2179 static VkResult
device_alloc_for_wsi(struct v3dv_device * device,const VkAllocationCallbacks * pAllocator,struct v3dv_device_memory * mem,VkDeviceSize size)2180 device_alloc_for_wsi(struct v3dv_device *device,
2181                      const VkAllocationCallbacks *pAllocator,
2182                      struct v3dv_device_memory *mem,
2183                      VkDeviceSize size)
2184 {
2185    /* In the simulator we can get away with a regular allocation since both
2186     * allocation and rendering happen in the same DRM render node. On actual
2187     * hardware we need to allocate our winsys BOs on the vc4 display device
2188     * and import them into v3d.
2189     */
2190 #if using_v3d_simulator
2191       return device_alloc(device, mem, size);
2192 #else
2193    /* If we are allocating for WSI we should have a swapchain and thus,
2194     * we should've initialized the display device. However, Zink doesn't
2195     * use swapchains, so in that case we can get here without acquiring the
2196     * display device and we need to do it now.
2197     */
2198    VkResult result;
2199    struct v3dv_instance *instance = device->instance;
2200    struct v3dv_physical_device *pdevice = &device->instance->physicalDevice;
2201    if (unlikely(pdevice->display_fd < 0)) {
2202       result = v3dv_physical_device_acquire_display(instance, pdevice, NULL);
2203       if (result != VK_SUCCESS)
2204          return result;
2205    }
2206    assert(pdevice->display_fd != -1);
2207 
2208    mem->is_for_wsi = true;
2209 
2210    int display_fd = pdevice->display_fd;
2211    struct drm_mode_create_dumb create_dumb = {
2212       .width = 1024, /* one page */
2213       .height = align(size, 4096) / 4096,
2214       .bpp = util_format_get_blocksizebits(PIPE_FORMAT_RGBA8888_UNORM),
2215    };
2216 
2217    int err;
2218    err = v3dv_ioctl(display_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
2219    if (err < 0)
2220       goto fail_create;
2221 
2222    int fd;
2223    err =
2224       drmPrimeHandleToFD(display_fd, create_dumb.handle, O_CLOEXEC, &fd);
2225    if (err < 0)
2226       goto fail_export;
2227 
2228    result = device_import_bo(device, pAllocator, fd, size, &mem->bo);
2229    close(fd);
2230    if (result != VK_SUCCESS)
2231       goto fail_import;
2232 
2233    mem->bo->dumb_handle = create_dumb.handle;
2234    return VK_SUCCESS;
2235 
2236 fail_import:
2237 fail_export:
2238    device_free_wsi_dumb(display_fd, create_dumb.handle);
2239 
2240 fail_create:
2241    return VK_ERROR_OUT_OF_DEVICE_MEMORY;
2242 #endif
2243 }
2244 
2245 static void
device_add_device_address_bo(struct v3dv_device * device,struct v3dv_bo * bo)2246 device_add_device_address_bo(struct v3dv_device *device,
2247                                   struct v3dv_bo *bo)
2248 {
2249    util_dynarray_append(&device->device_address_bo_list,
2250                         struct v3dv_bo *,
2251                         bo);
2252 }
2253 
2254 static void
device_remove_device_address_bo(struct v3dv_device * device,struct v3dv_bo * bo)2255 device_remove_device_address_bo(struct v3dv_device *device,
2256                                 struct v3dv_bo *bo)
2257 {
2258    util_dynarray_delete_unordered(&device->device_address_bo_list,
2259                                   struct v3dv_bo *,
2260                                   bo);
2261 }
2262 
2263 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_AllocateMemory(VkDevice _device,const VkMemoryAllocateInfo * pAllocateInfo,const VkAllocationCallbacks * pAllocator,VkDeviceMemory * pMem)2264 v3dv_AllocateMemory(VkDevice _device,
2265                     const VkMemoryAllocateInfo *pAllocateInfo,
2266                     const VkAllocationCallbacks *pAllocator,
2267                     VkDeviceMemory *pMem)
2268 {
2269    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2270    struct v3dv_device_memory *mem;
2271    struct v3dv_physical_device *pdevice = &device->instance->physicalDevice;
2272 
2273    assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
2274 
2275    /* The Vulkan 1.0.33 spec says "allocationSize must be greater than 0". */
2276    assert(pAllocateInfo->allocationSize > 0);
2277 
2278    mem = vk_object_zalloc(&device->vk, pAllocator, sizeof(*mem),
2279                           VK_OBJECT_TYPE_DEVICE_MEMORY);
2280    if (mem == NULL)
2281       return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
2282 
2283    assert(pAllocateInfo->memoryTypeIndex < pdevice->memory.memoryTypeCount);
2284    mem->type = &pdevice->memory.memoryTypes[pAllocateInfo->memoryTypeIndex];
2285    mem->is_for_wsi = false;
2286 
2287    const struct wsi_memory_allocate_info *wsi_info = NULL;
2288    const VkImportMemoryFdInfoKHR *fd_info = NULL;
2289    const VkMemoryAllocateFlagsInfo *flags_info = NULL;
2290    vk_foreach_struct_const(ext, pAllocateInfo->pNext) {
2291       switch ((unsigned)ext->sType) {
2292       case VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA:
2293          wsi_info = (void *)ext;
2294          break;
2295       case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR:
2296          fd_info = (void *)ext;
2297          break;
2298       case VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO:
2299          flags_info = (void *)ext;
2300          break;
2301       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO:
2302          /* We don't have particular optimizations associated with memory
2303           * allocations that won't be suballocated to multiple resources.
2304           */
2305          break;
2306       case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO:
2307          /* The mask of handle types specified here must be supported
2308           * according to VkExternalImageFormatProperties, so it must be
2309           * fd or dmabuf, which don't have special requirements for us.
2310           */
2311          break;
2312       default:
2313          v3dv_debug_ignored_stype(ext->sType);
2314          break;
2315       }
2316    }
2317 
2318    VkResult result = VK_SUCCESS;
2319 
2320    /* We always allocate device memory in multiples of a page, so round up
2321     * requested size to that.
2322     */
2323    VkDeviceSize alloc_size = ALIGN(pAllocateInfo->allocationSize, 4096);
2324 
2325    if (unlikely(alloc_size > MAX_MEMORY_ALLOCATION_SIZE)) {
2326       result = VK_ERROR_OUT_OF_DEVICE_MEMORY;
2327    } else {
2328       if (wsi_info) {
2329          result = device_alloc_for_wsi(device, pAllocator, mem, alloc_size);
2330       } else if (fd_info && fd_info->handleType) {
2331          assert(fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
2332                 fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
2333          result = device_import_bo(device, pAllocator,
2334                                    fd_info->fd, alloc_size, &mem->bo);
2335          if (result == VK_SUCCESS)
2336             close(fd_info->fd);
2337       } else {
2338          result = device_alloc(device, mem, alloc_size);
2339       }
2340    }
2341 
2342    if (result != VK_SUCCESS) {
2343       vk_object_free(&device->vk, pAllocator, mem);
2344       return vk_error(device, result);
2345    }
2346 
2347    /* If this memory can be used via VK_KHR_buffer_device_address then we
2348     * will need to manually add the BO to any job submit that makes use of
2349     * VK_KHR_buffer_device_address, since such jobs may produde buffer
2350     * load/store operations that may access any buffer memory allocated with
2351     * this flag and we don't have any means to tell which buffers will be
2352     * accessed through this mechanism since they don't even have to be bound
2353     * through descriptor state.
2354     */
2355    if (flags_info &&
2356        (flags_info->flags & VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR)) {
2357       mem->is_for_device_address = true;
2358       device_add_device_address_bo(device, mem->bo);
2359    }
2360 
2361    *pMem = v3dv_device_memory_to_handle(mem);
2362    return result;
2363 }
2364 
2365 VKAPI_ATTR void VKAPI_CALL
v3dv_FreeMemory(VkDevice _device,VkDeviceMemory _mem,const VkAllocationCallbacks * pAllocator)2366 v3dv_FreeMemory(VkDevice _device,
2367                 VkDeviceMemory _mem,
2368                 const VkAllocationCallbacks *pAllocator)
2369 {
2370    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2371    V3DV_FROM_HANDLE(v3dv_device_memory, mem, _mem);
2372 
2373    if (mem == NULL)
2374       return;
2375 
2376    if (mem->bo->map)
2377       v3dv_UnmapMemory(_device, _mem);
2378 
2379    if (mem->is_for_device_address)
2380       device_remove_device_address_bo(device, mem->bo);
2381 
2382    device_free(device, mem);
2383 
2384    vk_object_free(&device->vk, pAllocator, mem);
2385 }
2386 
2387 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_MapMemory(VkDevice _device,VkDeviceMemory _memory,VkDeviceSize offset,VkDeviceSize size,VkMemoryMapFlags flags,void ** ppData)2388 v3dv_MapMemory(VkDevice _device,
2389                VkDeviceMemory _memory,
2390                VkDeviceSize offset,
2391                VkDeviceSize size,
2392                VkMemoryMapFlags flags,
2393                void **ppData)
2394 {
2395    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2396    V3DV_FROM_HANDLE(v3dv_device_memory, mem, _memory);
2397 
2398    if (mem == NULL) {
2399       *ppData = NULL;
2400       return VK_SUCCESS;
2401    }
2402 
2403    assert(offset < mem->bo->size);
2404 
2405    /* Since the driver can map BOs internally as well and the mapped range
2406     * required by the user or the driver might not be the same, we always map
2407     * the entire BO and then add the requested offset to the start address
2408     * of the mapped region.
2409     */
2410    VkResult result = device_map(device, mem);
2411    if (result != VK_SUCCESS)
2412       return vk_error(device, result);
2413 
2414    *ppData = ((uint8_t *) mem->bo->map) + offset;
2415    return VK_SUCCESS;
2416 }
2417 
2418 VKAPI_ATTR void VKAPI_CALL
v3dv_UnmapMemory(VkDevice _device,VkDeviceMemory _memory)2419 v3dv_UnmapMemory(VkDevice _device,
2420                  VkDeviceMemory _memory)
2421 {
2422    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2423    V3DV_FROM_HANDLE(v3dv_device_memory, mem, _memory);
2424 
2425    if (mem == NULL)
2426       return;
2427 
2428    device_unmap(device, mem);
2429 }
2430 
2431 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_FlushMappedMemoryRanges(VkDevice _device,uint32_t memoryRangeCount,const VkMappedMemoryRange * pMemoryRanges)2432 v3dv_FlushMappedMemoryRanges(VkDevice _device,
2433                              uint32_t memoryRangeCount,
2434                              const VkMappedMemoryRange *pMemoryRanges)
2435 {
2436    return VK_SUCCESS;
2437 }
2438 
2439 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_InvalidateMappedMemoryRanges(VkDevice _device,uint32_t memoryRangeCount,const VkMappedMemoryRange * pMemoryRanges)2440 v3dv_InvalidateMappedMemoryRanges(VkDevice _device,
2441                                   uint32_t memoryRangeCount,
2442                                   const VkMappedMemoryRange *pMemoryRanges)
2443 {
2444    return VK_SUCCESS;
2445 }
2446 
2447 VKAPI_ATTR void VKAPI_CALL
v3dv_GetImageMemoryRequirements2(VkDevice device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)2448 v3dv_GetImageMemoryRequirements2(VkDevice device,
2449                                  const VkImageMemoryRequirementsInfo2 *pInfo,
2450                                  VkMemoryRequirements2 *pMemoryRequirements)
2451 {
2452    V3DV_FROM_HANDLE(v3dv_image, image, pInfo->image);
2453 
2454    pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
2455       .memoryTypeBits = 0x1,
2456       .alignment = image->alignment,
2457       .size = image->size
2458    };
2459 
2460    vk_foreach_struct(ext, pMemoryRequirements->pNext) {
2461       switch (ext->sType) {
2462       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
2463          VkMemoryDedicatedRequirements *req =
2464             (VkMemoryDedicatedRequirements *) ext;
2465          req->requiresDedicatedAllocation = image->vk.external_handle_types != 0;
2466          req->prefersDedicatedAllocation = image->vk.external_handle_types != 0;
2467          break;
2468       }
2469       default:
2470          v3dv_debug_ignored_stype(ext->sType);
2471          break;
2472       }
2473    }
2474 }
2475 
2476 static void
bind_image_memory(const VkBindImageMemoryInfo * info)2477 bind_image_memory(const VkBindImageMemoryInfo *info)
2478 {
2479    V3DV_FROM_HANDLE(v3dv_image, image, info->image);
2480    V3DV_FROM_HANDLE(v3dv_device_memory, mem, info->memory);
2481 
2482    /* Valid usage:
2483     *
2484     *   "memoryOffset must be an integer multiple of the alignment member of
2485     *    the VkMemoryRequirements structure returned from a call to
2486     *    vkGetImageMemoryRequirements with image"
2487     */
2488    assert(info->memoryOffset % image->alignment == 0);
2489    assert(info->memoryOffset < mem->bo->size);
2490 
2491    image->mem = mem;
2492    image->mem_offset = info->memoryOffset;
2493 }
2494 
2495 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_BindImageMemory2(VkDevice _device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)2496 v3dv_BindImageMemory2(VkDevice _device,
2497                       uint32_t bindInfoCount,
2498                       const VkBindImageMemoryInfo *pBindInfos)
2499 {
2500    for (uint32_t i = 0; i < bindInfoCount; i++) {
2501       const VkBindImageMemorySwapchainInfoKHR *swapchain_info =
2502          vk_find_struct_const(pBindInfos->pNext,
2503                               BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR);
2504       if (swapchain_info && swapchain_info->swapchain) {
2505          struct v3dv_image *swapchain_image =
2506             v3dv_wsi_get_image_from_swapchain(swapchain_info->swapchain,
2507                                               swapchain_info->imageIndex);
2508          VkBindImageMemoryInfo swapchain_bind = {
2509             .sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
2510             .image = pBindInfos[i].image,
2511             .memory = v3dv_device_memory_to_handle(swapchain_image->mem),
2512             .memoryOffset = swapchain_image->mem_offset,
2513          };
2514          bind_image_memory(&swapchain_bind);
2515       } else {
2516          bind_image_memory(&pBindInfos[i]);
2517       }
2518    }
2519 
2520    return VK_SUCCESS;
2521 }
2522 
2523 VKAPI_ATTR void VKAPI_CALL
v3dv_GetBufferMemoryRequirements2(VkDevice device,const VkBufferMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)2524 v3dv_GetBufferMemoryRequirements2(VkDevice device,
2525                                   const VkBufferMemoryRequirementsInfo2 *pInfo,
2526                                   VkMemoryRequirements2 *pMemoryRequirements)
2527 {
2528    V3DV_FROM_HANDLE(v3dv_buffer, buffer, pInfo->buffer);
2529 
2530    pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
2531       .memoryTypeBits = 0x1,
2532       .alignment = buffer->alignment,
2533       .size = align64(buffer->size, buffer->alignment),
2534    };
2535 
2536    vk_foreach_struct(ext, pMemoryRequirements->pNext) {
2537       switch (ext->sType) {
2538       case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
2539          VkMemoryDedicatedRequirements *req =
2540             (VkMemoryDedicatedRequirements *) ext;
2541          req->requiresDedicatedAllocation = false;
2542          req->prefersDedicatedAllocation = false;
2543          break;
2544       }
2545       default:
2546          v3dv_debug_ignored_stype(ext->sType);
2547          break;
2548       }
2549    }
2550 }
2551 
2552 static void
bind_buffer_memory(const VkBindBufferMemoryInfo * info)2553 bind_buffer_memory(const VkBindBufferMemoryInfo *info)
2554 {
2555    V3DV_FROM_HANDLE(v3dv_buffer, buffer, info->buffer);
2556    V3DV_FROM_HANDLE(v3dv_device_memory, mem, info->memory);
2557 
2558    /* Valid usage:
2559     *
2560     *   "memoryOffset must be an integer multiple of the alignment member of
2561     *    the VkMemoryRequirements structure returned from a call to
2562     *    vkGetBufferMemoryRequirements with buffer"
2563     */
2564    assert(info->memoryOffset % buffer->alignment == 0);
2565    assert(info->memoryOffset < mem->bo->size);
2566 
2567    buffer->mem = mem;
2568    buffer->mem_offset = info->memoryOffset;
2569 }
2570 
2571 
2572 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_BindBufferMemory2(VkDevice device,uint32_t bindInfoCount,const VkBindBufferMemoryInfo * pBindInfos)2573 v3dv_BindBufferMemory2(VkDevice device,
2574                        uint32_t bindInfoCount,
2575                        const VkBindBufferMemoryInfo *pBindInfos)
2576 {
2577    for (uint32_t i = 0; i < bindInfoCount; i++)
2578       bind_buffer_memory(&pBindInfos[i]);
2579 
2580    return VK_SUCCESS;
2581 }
2582 
2583 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_CreateBuffer(VkDevice _device,const VkBufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBuffer * pBuffer)2584 v3dv_CreateBuffer(VkDevice  _device,
2585                   const VkBufferCreateInfo *pCreateInfo,
2586                   const VkAllocationCallbacks *pAllocator,
2587                   VkBuffer *pBuffer)
2588 {
2589    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2590    struct v3dv_buffer *buffer;
2591 
2592    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
2593    assert(pCreateInfo->usage != 0);
2594 
2595    /* We don't support any flags for now */
2596    assert(pCreateInfo->flags == 0);
2597 
2598    buffer = vk_object_zalloc(&device->vk, pAllocator, sizeof(*buffer),
2599                              VK_OBJECT_TYPE_BUFFER);
2600    if (buffer == NULL)
2601       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2602 
2603    buffer->size = pCreateInfo->size;
2604    buffer->usage = pCreateInfo->usage;
2605    buffer->alignment = V3D_NON_COHERENT_ATOM_SIZE;
2606 
2607    /* Limit allocations to 32-bit */
2608    const VkDeviceSize aligned_size = align64(buffer->size, buffer->alignment);
2609    if (aligned_size > UINT32_MAX || aligned_size < buffer->size) {
2610       vk_free(&device->vk.alloc, buffer);
2611       return VK_ERROR_OUT_OF_DEVICE_MEMORY;
2612    }
2613 
2614    *pBuffer = v3dv_buffer_to_handle(buffer);
2615 
2616    return VK_SUCCESS;
2617 }
2618 
2619 VKAPI_ATTR void VKAPI_CALL
v3dv_DestroyBuffer(VkDevice _device,VkBuffer _buffer,const VkAllocationCallbacks * pAllocator)2620 v3dv_DestroyBuffer(VkDevice _device,
2621                    VkBuffer _buffer,
2622                    const VkAllocationCallbacks *pAllocator)
2623 {
2624    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2625    V3DV_FROM_HANDLE(v3dv_buffer, buffer, _buffer);
2626 
2627    if (!buffer)
2628       return;
2629 
2630    vk_object_free(&device->vk, pAllocator, buffer);
2631 }
2632 
2633 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_CreateFramebuffer(VkDevice _device,const VkFramebufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkFramebuffer * pFramebuffer)2634 v3dv_CreateFramebuffer(VkDevice _device,
2635                        const VkFramebufferCreateInfo *pCreateInfo,
2636                        const VkAllocationCallbacks *pAllocator,
2637                        VkFramebuffer *pFramebuffer)
2638 {
2639    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2640    struct v3dv_framebuffer *framebuffer;
2641 
2642    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
2643 
2644    size_t size = sizeof(*framebuffer) +
2645                  sizeof(struct v3dv_image_view *) * pCreateInfo->attachmentCount;
2646    framebuffer = vk_object_zalloc(&device->vk, pAllocator, size,
2647                                   VK_OBJECT_TYPE_FRAMEBUFFER);
2648    if (framebuffer == NULL)
2649       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2650 
2651    framebuffer->width = pCreateInfo->width;
2652    framebuffer->height = pCreateInfo->height;
2653    framebuffer->layers = pCreateInfo->layers;
2654    framebuffer->has_edge_padding = true;
2655 
2656    const VkFramebufferAttachmentsCreateInfo *imageless =
2657       vk_find_struct_const(pCreateInfo->pNext,
2658       FRAMEBUFFER_ATTACHMENTS_CREATE_INFO);
2659 
2660    framebuffer->attachment_count = pCreateInfo->attachmentCount;
2661    framebuffer->color_attachment_count = 0;
2662    for (uint32_t i = 0; i < framebuffer->attachment_count; i++) {
2663       if (!imageless) {
2664          framebuffer->attachments[i] =
2665             v3dv_image_view_from_handle(pCreateInfo->pAttachments[i]);
2666          if (framebuffer->attachments[i]->vk.aspects & VK_IMAGE_ASPECT_COLOR_BIT)
2667             framebuffer->color_attachment_count++;
2668       } else {
2669          assert(i < imageless->attachmentImageInfoCount);
2670          if (imageless->pAttachmentImageInfos[i].usage &
2671              VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
2672             framebuffer->color_attachment_count++;
2673          }
2674       }
2675    }
2676 
2677    *pFramebuffer = v3dv_framebuffer_to_handle(framebuffer);
2678 
2679    return VK_SUCCESS;
2680 }
2681 
2682 VKAPI_ATTR void VKAPI_CALL
v3dv_DestroyFramebuffer(VkDevice _device,VkFramebuffer _fb,const VkAllocationCallbacks * pAllocator)2683 v3dv_DestroyFramebuffer(VkDevice _device,
2684                         VkFramebuffer _fb,
2685                         const VkAllocationCallbacks *pAllocator)
2686 {
2687    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2688    V3DV_FROM_HANDLE(v3dv_framebuffer, fb, _fb);
2689 
2690    if (!fb)
2691       return;
2692 
2693    vk_object_free(&device->vk, pAllocator, fb);
2694 }
2695 
2696 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetMemoryFdPropertiesKHR(VkDevice _device,VkExternalMemoryHandleTypeFlagBits handleType,int fd,VkMemoryFdPropertiesKHR * pMemoryFdProperties)2697 v3dv_GetMemoryFdPropertiesKHR(VkDevice _device,
2698                               VkExternalMemoryHandleTypeFlagBits handleType,
2699                               int fd,
2700                               VkMemoryFdPropertiesKHR *pMemoryFdProperties)
2701 {
2702    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2703    struct v3dv_physical_device *pdevice = &device->instance->physicalDevice;
2704 
2705    switch (handleType) {
2706    case VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT:
2707       pMemoryFdProperties->memoryTypeBits =
2708          (1 << pdevice->memory.memoryTypeCount) - 1;
2709       return VK_SUCCESS;
2710    default:
2711       return vk_error(device, VK_ERROR_INVALID_EXTERNAL_HANDLE);
2712    }
2713 }
2714 
2715 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetMemoryFdKHR(VkDevice _device,const VkMemoryGetFdInfoKHR * pGetFdInfo,int * pFd)2716 v3dv_GetMemoryFdKHR(VkDevice _device,
2717                     const VkMemoryGetFdInfoKHR *pGetFdInfo,
2718                     int *pFd)
2719 {
2720    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2721    V3DV_FROM_HANDLE(v3dv_device_memory, mem, pGetFdInfo->memory);
2722 
2723    assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
2724    assert(pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
2725           pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
2726 
2727    int fd, ret;
2728    ret = drmPrimeHandleToFD(device->pdevice->render_fd,
2729                             mem->bo->handle,
2730                             DRM_CLOEXEC, &fd);
2731    if (ret)
2732       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2733 
2734    *pFd = fd;
2735 
2736    return VK_SUCCESS;
2737 }
2738 
2739 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_CreateEvent(VkDevice _device,const VkEventCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkEvent * pEvent)2740 v3dv_CreateEvent(VkDevice _device,
2741                  const VkEventCreateInfo *pCreateInfo,
2742                  const VkAllocationCallbacks *pAllocator,
2743                  VkEvent *pEvent)
2744 {
2745    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2746    struct v3dv_event *event =
2747       vk_object_zalloc(&device->vk, pAllocator, sizeof(*event),
2748                        VK_OBJECT_TYPE_EVENT);
2749    if (!event)
2750       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2751 
2752    /* Events are created in the unsignaled state */
2753    event->state = false;
2754    *pEvent = v3dv_event_to_handle(event);
2755 
2756    return VK_SUCCESS;
2757 }
2758 
2759 VKAPI_ATTR void VKAPI_CALL
v3dv_DestroyEvent(VkDevice _device,VkEvent _event,const VkAllocationCallbacks * pAllocator)2760 v3dv_DestroyEvent(VkDevice _device,
2761                   VkEvent _event,
2762                   const VkAllocationCallbacks *pAllocator)
2763 {
2764    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2765    V3DV_FROM_HANDLE(v3dv_event, event, _event);
2766 
2767    if (!event)
2768       return;
2769 
2770    vk_object_free(&device->vk, pAllocator, event);
2771 }
2772 
2773 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_GetEventStatus(VkDevice _device,VkEvent _event)2774 v3dv_GetEventStatus(VkDevice _device, VkEvent _event)
2775 {
2776    V3DV_FROM_HANDLE(v3dv_event, event, _event);
2777    return p_atomic_read(&event->state) ? VK_EVENT_SET : VK_EVENT_RESET;
2778 }
2779 
2780 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_SetEvent(VkDevice _device,VkEvent _event)2781 v3dv_SetEvent(VkDevice _device, VkEvent _event)
2782 {
2783    V3DV_FROM_HANDLE(v3dv_event, event, _event);
2784    p_atomic_set(&event->state, 1);
2785    return VK_SUCCESS;
2786 }
2787 
2788 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_ResetEvent(VkDevice _device,VkEvent _event)2789 v3dv_ResetEvent(VkDevice _device, VkEvent _event)
2790 {
2791    V3DV_FROM_HANDLE(v3dv_event, event, _event);
2792    p_atomic_set(&event->state, 0);
2793    return VK_SUCCESS;
2794 }
2795 
2796 VKAPI_ATTR VkResult VKAPI_CALL
v3dv_CreateSampler(VkDevice _device,const VkSamplerCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSampler * pSampler)2797 v3dv_CreateSampler(VkDevice _device,
2798                  const VkSamplerCreateInfo *pCreateInfo,
2799                  const VkAllocationCallbacks *pAllocator,
2800                  VkSampler *pSampler)
2801 {
2802    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2803    struct v3dv_sampler *sampler;
2804 
2805    assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
2806 
2807    sampler = vk_object_zalloc(&device->vk, pAllocator, sizeof(*sampler),
2808                               VK_OBJECT_TYPE_SAMPLER);
2809    if (!sampler)
2810       return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2811 
2812    sampler->compare_enable = pCreateInfo->compareEnable;
2813    sampler->unnormalized_coordinates = pCreateInfo->unnormalizedCoordinates;
2814 
2815    const VkSamplerCustomBorderColorCreateInfoEXT *bc_info =
2816       vk_find_struct_const(pCreateInfo->pNext,
2817                            SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT);
2818 
2819    v3dv_X(device, pack_sampler_state)(sampler, pCreateInfo, bc_info);
2820 
2821    *pSampler = v3dv_sampler_to_handle(sampler);
2822 
2823    return VK_SUCCESS;
2824 }
2825 
2826 VKAPI_ATTR void VKAPI_CALL
v3dv_DestroySampler(VkDevice _device,VkSampler _sampler,const VkAllocationCallbacks * pAllocator)2827 v3dv_DestroySampler(VkDevice _device,
2828                   VkSampler _sampler,
2829                   const VkAllocationCallbacks *pAllocator)
2830 {
2831    V3DV_FROM_HANDLE(v3dv_device, device, _device);
2832    V3DV_FROM_HANDLE(v3dv_sampler, sampler, _sampler);
2833 
2834    if (!sampler)
2835       return;
2836 
2837    vk_object_free(&device->vk, pAllocator, sampler);
2838 }
2839 
2840 VKAPI_ATTR void VKAPI_CALL
v3dv_GetDeviceMemoryCommitment(VkDevice device,VkDeviceMemory memory,VkDeviceSize * pCommittedMemoryInBytes)2841 v3dv_GetDeviceMemoryCommitment(VkDevice device,
2842                                VkDeviceMemory memory,
2843                                VkDeviceSize *pCommittedMemoryInBytes)
2844 {
2845    *pCommittedMemoryInBytes = 0;
2846 }
2847 
2848 VKAPI_ATTR void VKAPI_CALL
v3dv_GetImageSparseMemoryRequirements(VkDevice device,VkImage image,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements * pSparseMemoryRequirements)2849 v3dv_GetImageSparseMemoryRequirements(
2850     VkDevice device,
2851     VkImage image,
2852     uint32_t *pSparseMemoryRequirementCount,
2853     VkSparseImageMemoryRequirements *pSparseMemoryRequirements)
2854 {
2855    *pSparseMemoryRequirementCount = 0;
2856 }
2857 
2858 VKAPI_ATTR void VKAPI_CALL
v3dv_GetImageSparseMemoryRequirements2(VkDevice device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)2859 v3dv_GetImageSparseMemoryRequirements2(
2860    VkDevice device,
2861    const VkImageSparseMemoryRequirementsInfo2 *pInfo,
2862    uint32_t *pSparseMemoryRequirementCount,
2863    VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
2864 {
2865    *pSparseMemoryRequirementCount = 0;
2866 }
2867 
2868 /* vk_icd.h does not declare this function, so we declare it here to
2869  * suppress Wmissing-prototypes.
2870  */
2871 PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
2872 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion);
2873 
2874 PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t * pSupportedVersion)2875 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion)
2876 {
2877    /* For the full details on loader interface versioning, see
2878     * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
2879     * What follows is a condensed summary, to help you navigate the large and
2880     * confusing official doc.
2881     *
2882     *   - Loader interface v0 is incompatible with later versions. We don't
2883     *     support it.
2884     *
2885     *   - In loader interface v1:
2886     *       - The first ICD entrypoint called by the loader is
2887     *         vk_icdGetInstanceProcAddr(). The ICD must statically expose this
2888     *         entrypoint.
2889     *       - The ICD must statically expose no other Vulkan symbol unless it is
2890     *         linked with -Bsymbolic.
2891     *       - Each dispatchable Vulkan handle created by the ICD must be
2892     *         a pointer to a struct whose first member is VK_LOADER_DATA. The
2893     *         ICD must initialize VK_LOADER_DATA.loadMagic to ICD_LOADER_MAGIC.
2894     *       - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
2895     *         vkDestroySurfaceKHR(). The ICD must be capable of working with
2896     *         such loader-managed surfaces.
2897     *
2898     *    - Loader interface v2 differs from v1 in:
2899     *       - The first ICD entrypoint called by the loader is
2900     *         vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
2901     *         statically expose this entrypoint.
2902     *
2903     *    - Loader interface v3 differs from v2 in:
2904     *        - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
2905     *          vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
2906     *          because the loader no longer does so.
2907     *
2908     *    - Loader interface v4 differs from v3 in:
2909     *        - The ICD must implement vk_icdGetPhysicalDeviceProcAddr().
2910     *
2911     *    - Loader interface v5 differs from v4 in:
2912     *        - The ICD must support Vulkan API version 1.1 and must not return
2913     *          VK_ERROR_INCOMPATIBLE_DRIVER from vkCreateInstance() unless a
2914     *          Vulkan Loader with interface v4 or smaller is being used and the
2915     *          application provides an API version that is greater than 1.0.
2916     */
2917    *pSupportedVersion = MIN2(*pSupportedVersion, 5u);
2918    return VK_SUCCESS;
2919 }
2920 
2921 VkDeviceAddress
v3dv_GetBufferDeviceAddress(VkDevice device,const VkBufferDeviceAddressInfoKHR * pInfo)2922 v3dv_GetBufferDeviceAddress(VkDevice device,
2923                             const VkBufferDeviceAddressInfoKHR *pInfo)
2924 {
2925    V3DV_FROM_HANDLE(v3dv_buffer, buffer, pInfo->buffer);
2926    return buffer->mem_offset + buffer->mem->bo->offset;
2927 }
2928 
2929 uint64_t
v3dv_GetBufferOpaqueCaptureAddress(VkDevice device,const VkBufferDeviceAddressInfoKHR * pInfo)2930 v3dv_GetBufferOpaqueCaptureAddress(VkDevice device,
2931                                    const VkBufferDeviceAddressInfoKHR *pInfo)
2932 {
2933    /* Not implemented */
2934    return 0;
2935 }
2936 
2937 uint64_t
v3dv_GetDeviceMemoryOpaqueCaptureAddress(VkDevice device,const VkDeviceMemoryOpaqueCaptureAddressInfoKHR * pInfo)2938 v3dv_GetDeviceMemoryOpaqueCaptureAddress(
2939     VkDevice device,
2940     const VkDeviceMemoryOpaqueCaptureAddressInfoKHR *pInfo)
2941 {
2942    /* Not implemented */
2943    return 0;
2944 }
2945