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