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