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