1 /*
2 * Copyright © 2021 Collabora Ltd.
3 *
4 * Derived from tu_device.c which is:
5 * Copyright © 2016 Red Hat.
6 * Copyright © 2016 Bas Nieuwenhuizen
7 * Copyright © 2015 Intel Corporation
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 */
28
29 #include "panvk_private.h"
30
31 #include "decode.h"
32
33 #include "pan_encoder.h"
34 #include "pan_util.h"
35 #include "pan_props.h"
36 #include "pan_samples.h"
37
38 #include "vk_cmd_enqueue_entrypoints.h"
39 #include "vk_common_entrypoints.h"
40
41 #include <fcntl.h>
42 #include <libsync.h>
43 #include <stdbool.h>
44 #include <string.h>
45 #include <unistd.h>
46 #include <xf86drm.h>
47 #include <sys/mman.h>
48 #include <sys/sysinfo.h>
49
50 #include "drm-uapi/panfrost_drm.h"
51
52 #include "util/disk_cache.h"
53 #include "util/strtod.h"
54 #include "util/u_debug.h"
55 #include "vk_drm_syncobj.h"
56 #include "vk_format.h"
57 #include "vk_util.h"
58
59 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
60 #include "wayland-drm-client-protocol.h"
61 #include <wayland-client.h>
62 #endif
63
64 #include "panvk_cs.h"
65
66 VkResult
_panvk_device_set_lost(struct panvk_device * device,const char * file,int line,const char * msg,...)67 _panvk_device_set_lost(struct panvk_device *device, const char *file, int line,
68 const char *msg, ...)
69 {
70 /* Set the flag indicating that waits should return in finite time even
71 * after device loss.
72 */
73 p_atomic_inc(&device->_lost);
74
75 /* TODO: Report the log message through VkDebugReportCallbackEXT instead */
76 fprintf(stderr, "%s:%d: ", file, line);
77 va_list ap;
78 va_start(ap, msg);
79 vfprintf(stderr, msg, ap);
80 va_end(ap);
81
82 if (debug_get_bool_option("PANVK_ABORT_ON_DEVICE_LOSS", false))
83 abort();
84
85 return VK_ERROR_DEVICE_LOST;
86 }
87
88 static int
panvk_device_get_cache_uuid(uint16_t family,void * uuid)89 panvk_device_get_cache_uuid(uint16_t family, void *uuid)
90 {
91 uint32_t mesa_timestamp;
92 uint16_t f = family;
93
94 if (!disk_cache_get_function_timestamp(panvk_device_get_cache_uuid,
95 &mesa_timestamp))
96 return -1;
97
98 memset(uuid, 0, VK_UUID_SIZE);
99 memcpy(uuid, &mesa_timestamp, 4);
100 memcpy((char *)uuid + 4, &f, 2);
101 snprintf((char *)uuid + 6, VK_UUID_SIZE - 10, "pan");
102 return 0;
103 }
104
105 static void
panvk_get_driver_uuid(void * uuid)106 panvk_get_driver_uuid(void *uuid)
107 {
108 memset(uuid, 0, VK_UUID_SIZE);
109 snprintf(uuid, VK_UUID_SIZE, "panfrost");
110 }
111
112 static void
panvk_get_device_uuid(void * uuid)113 panvk_get_device_uuid(void *uuid)
114 {
115 memset(uuid, 0, VK_UUID_SIZE);
116 }
117
118 static const struct debug_control panvk_debug_options[] = {
119 {"startup", PANVK_DEBUG_STARTUP},
120 {"nir", PANVK_DEBUG_NIR},
121 {"trace", PANVK_DEBUG_TRACE},
122 {"sync", PANVK_DEBUG_SYNC},
123 {"afbc", PANVK_DEBUG_AFBC},
124 {"linear", PANVK_DEBUG_LINEAR},
125 {"dump", PANVK_DEBUG_DUMP},
126 {"no_known_warn", PANVK_DEBUG_NO_KNOWN_WARN},
127 {NULL, 0}};
128
129 #if defined(VK_USE_PLATFORM_WAYLAND_KHR)
130 #define PANVK_USE_WSI_PLATFORM
131 #endif
132
133 #define PANVK_API_VERSION VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION)
134
135 VkResult
panvk_EnumerateInstanceVersion(uint32_t * pApiVersion)136 panvk_EnumerateInstanceVersion(uint32_t *pApiVersion)
137 {
138 *pApiVersion = PANVK_API_VERSION;
139 return VK_SUCCESS;
140 }
141
142 static const struct vk_instance_extension_table panvk_instance_extensions = {
143 .KHR_get_physical_device_properties2 = true,
144 .EXT_debug_report = true,
145 .EXT_debug_utils = true,
146
147 #ifdef PANVK_USE_WSI_PLATFORM
148 .KHR_surface = true,
149 #endif
150 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
151 .KHR_wayland_surface = true,
152 #endif
153 #ifndef VK_USE_PLATFORM_WIN32_KHR
154 .EXT_headless_surface = true,
155 #endif
156 };
157
158 static void
panvk_get_device_extensions(const struct panvk_physical_device * device,struct vk_device_extension_table * ext)159 panvk_get_device_extensions(const struct panvk_physical_device *device,
160 struct vk_device_extension_table *ext)
161 {
162 *ext = (struct vk_device_extension_table){
163 .KHR_copy_commands2 = true,
164 .KHR_shader_expect_assume = true,
165 .KHR_storage_buffer_storage_class = true,
166 .KHR_descriptor_update_template = true,
167 #ifdef PANVK_USE_WSI_PLATFORM
168 .KHR_swapchain = true,
169 #endif
170 .KHR_synchronization2 = true,
171 .KHR_variable_pointers = true,
172 .EXT_custom_border_color = true,
173 .EXT_index_type_uint8 = true,
174 .EXT_vertex_attribute_divisor = true,
175 };
176 }
177
178 static void
panvk_get_features(const struct panvk_physical_device * device,struct vk_features * features)179 panvk_get_features(const struct panvk_physical_device *device,
180 struct vk_features *features)
181 {
182 *features = (struct vk_features){
183 /* Vulkan 1.0 */
184 .robustBufferAccess = true,
185 .fullDrawIndexUint32 = true,
186 .independentBlend = true,
187 .logicOp = true,
188 .wideLines = true,
189 .largePoints = true,
190 .textureCompressionETC2 = true,
191 .textureCompressionASTC_LDR = true,
192 .shaderUniformBufferArrayDynamicIndexing = true,
193 .shaderSampledImageArrayDynamicIndexing = true,
194 .shaderStorageBufferArrayDynamicIndexing = true,
195 .shaderStorageImageArrayDynamicIndexing = true,
196
197 /* Vulkan 1.1 */
198 .storageBuffer16BitAccess = false,
199 .uniformAndStorageBuffer16BitAccess = false,
200 .storagePushConstant16 = false,
201 .storageInputOutput16 = false,
202 .multiview = false,
203 .multiviewGeometryShader = false,
204 .multiviewTessellationShader = false,
205 .variablePointersStorageBuffer = true,
206 .variablePointers = true,
207 .protectedMemory = false,
208 .samplerYcbcrConversion = false,
209 .shaderDrawParameters = false,
210
211 /* Vulkan 1.2 */
212 .samplerMirrorClampToEdge = false,
213 .drawIndirectCount = false,
214 .storageBuffer8BitAccess = false,
215 .uniformAndStorageBuffer8BitAccess = false,
216 .storagePushConstant8 = false,
217 .shaderBufferInt64Atomics = false,
218 .shaderSharedInt64Atomics = false,
219 .shaderFloat16 = false,
220 .shaderInt8 = false,
221
222 .descriptorIndexing = false,
223 .shaderInputAttachmentArrayDynamicIndexing = false,
224 .shaderUniformTexelBufferArrayDynamicIndexing = false,
225 .shaderStorageTexelBufferArrayDynamicIndexing = false,
226 .shaderUniformBufferArrayNonUniformIndexing = false,
227 .shaderSampledImageArrayNonUniformIndexing = false,
228 .shaderStorageBufferArrayNonUniformIndexing = false,
229 .shaderStorageImageArrayNonUniformIndexing = false,
230 .shaderInputAttachmentArrayNonUniformIndexing = false,
231 .shaderUniformTexelBufferArrayNonUniformIndexing = false,
232 .shaderStorageTexelBufferArrayNonUniformIndexing = false,
233 .descriptorBindingUniformBufferUpdateAfterBind = false,
234 .descriptorBindingSampledImageUpdateAfterBind = false,
235 .descriptorBindingStorageImageUpdateAfterBind = false,
236 .descriptorBindingStorageBufferUpdateAfterBind = false,
237 .descriptorBindingUniformTexelBufferUpdateAfterBind = false,
238 .descriptorBindingStorageTexelBufferUpdateAfterBind = false,
239 .descriptorBindingUpdateUnusedWhilePending = false,
240 .descriptorBindingPartiallyBound = false,
241 .descriptorBindingVariableDescriptorCount = false,
242 .runtimeDescriptorArray = false,
243
244 .samplerFilterMinmax = false,
245 .scalarBlockLayout = false,
246 .imagelessFramebuffer = false,
247 .uniformBufferStandardLayout = false,
248 .shaderSubgroupExtendedTypes = false,
249 .separateDepthStencilLayouts = false,
250 .hostQueryReset = false,
251 .timelineSemaphore = false,
252 .bufferDeviceAddress = true,
253 .bufferDeviceAddressCaptureReplay = false,
254 .bufferDeviceAddressMultiDevice = false,
255 .vulkanMemoryModel = false,
256 .vulkanMemoryModelDeviceScope = false,
257 .vulkanMemoryModelAvailabilityVisibilityChains = false,
258 .shaderOutputViewportIndex = false,
259 .shaderOutputLayer = false,
260 .subgroupBroadcastDynamicId = false,
261
262 /* Vulkan 1.3 */
263 .robustImageAccess = false,
264 .inlineUniformBlock = false,
265 .descriptorBindingInlineUniformBlockUpdateAfterBind = false,
266 .pipelineCreationCacheControl = false,
267 .privateData = true,
268 .shaderDemoteToHelperInvocation = false,
269 .shaderTerminateInvocation = false,
270 .subgroupSizeControl = false,
271 .computeFullSubgroups = false,
272 .synchronization2 = true,
273 .textureCompressionASTC_HDR = false,
274 .shaderZeroInitializeWorkgroupMemory = false,
275 .dynamicRendering = false,
276 .shaderIntegerDotProduct = false,
277 .maintenance4 = false,
278
279 /* VK_EXT_index_type_uint8 */
280 .indexTypeUint8 = true,
281
282 /* VK_EXT_vertex_attribute_divisor */
283 .vertexAttributeInstanceRateDivisor = true,
284 .vertexAttributeInstanceRateZeroDivisor = true,
285
286 /* VK_EXT_depth_clip_enable */
287 .depthClipEnable = true,
288
289 /* VK_EXT_4444_formats */
290 .formatA4R4G4B4 = true,
291 .formatA4B4G4R4 = true,
292
293 /* VK_EXT_custom_border_color */
294 .customBorderColors = true,
295 .customBorderColorWithoutFormat = true,
296
297 /* VK_KHR_shader_expect_assume */
298 .shaderExpectAssume = true,
299 };
300 }
301
302 VkResult panvk_physical_device_try_create(struct vk_instance *vk_instance,
303 struct _drmDevice *drm_device,
304 struct vk_physical_device **out);
305
306 static void
panvk_physical_device_finish(struct panvk_physical_device * device)307 panvk_physical_device_finish(struct panvk_physical_device *device)
308 {
309 panvk_wsi_finish(device);
310
311 pan_kmod_dev_destroy(device->kmod.dev);
312 if (device->master_fd != -1)
313 close(device->master_fd);
314
315 vk_physical_device_finish(&device->vk);
316 }
317
318 static void
panvk_destroy_physical_device(struct vk_physical_device * device)319 panvk_destroy_physical_device(struct vk_physical_device *device)
320 {
321 panvk_physical_device_finish((struct panvk_physical_device *)device);
322 vk_free(&device->instance->alloc, device);
323 }
324
325 static void *
panvk_kmod_zalloc(const struct pan_kmod_allocator * allocator,size_t size,bool transient)326 panvk_kmod_zalloc(const struct pan_kmod_allocator *allocator,
327 size_t size, bool transient)
328 {
329 const VkAllocationCallbacks *vkalloc = allocator->priv;
330
331 return vk_zalloc(vkalloc, size, 8,
332 transient ? VK_SYSTEM_ALLOCATION_SCOPE_COMMAND
333 : VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
334 }
335
336 static void
panvk_kmod_free(const struct pan_kmod_allocator * allocator,void * data)337 panvk_kmod_free(const struct pan_kmod_allocator *allocator, void *data)
338 {
339 const VkAllocationCallbacks *vkalloc = allocator->priv;
340
341 return vk_free(vkalloc, data);
342 }
343
344 VkResult
panvk_CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)345 panvk_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
346 const VkAllocationCallbacks *pAllocator,
347 VkInstance *pInstance)
348 {
349 struct panvk_instance *instance;
350 VkResult result;
351
352 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
353
354 pAllocator = pAllocator ?: vk_default_allocator();
355 instance = vk_zalloc(pAllocator, sizeof(*instance), 8,
356 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
357 if (!instance)
358 return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
359
360 struct vk_instance_dispatch_table dispatch_table;
361
362 vk_instance_dispatch_table_from_entrypoints(
363 &dispatch_table, &panvk_instance_entrypoints, true);
364 vk_instance_dispatch_table_from_entrypoints(
365 &dispatch_table, &wsi_instance_entrypoints, false);
366 result = vk_instance_init(&instance->vk, &panvk_instance_extensions,
367 &dispatch_table, pCreateInfo, pAllocator);
368 if (result != VK_SUCCESS) {
369 vk_free(pAllocator, instance);
370 return vk_error(NULL, result);
371 }
372
373 instance->kmod.allocator = (struct pan_kmod_allocator){
374 .zalloc = panvk_kmod_zalloc,
375 .free = panvk_kmod_free,
376 .priv = &instance->vk.alloc,
377 };
378
379 instance->vk.physical_devices.try_create_for_drm =
380 panvk_physical_device_try_create;
381 instance->vk.physical_devices.destroy = panvk_destroy_physical_device;
382
383 instance->debug_flags =
384 parse_debug_string(getenv("PANVK_DEBUG"), panvk_debug_options);
385
386 if (instance->debug_flags & PANVK_DEBUG_STARTUP)
387 vk_logi(VK_LOG_NO_OBJS(instance), "Created an instance");
388
389 VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
390
391 *pInstance = panvk_instance_to_handle(instance);
392
393 return VK_SUCCESS;
394 }
395
396 void
panvk_DestroyInstance(VkInstance _instance,const VkAllocationCallbacks * pAllocator)397 panvk_DestroyInstance(VkInstance _instance,
398 const VkAllocationCallbacks *pAllocator)
399 {
400 VK_FROM_HANDLE(panvk_instance, instance, _instance);
401
402 if (!instance)
403 return;
404
405 vk_instance_finish(&instance->vk);
406 vk_free(&instance->vk.alloc, instance);
407 }
408
409 static VkResult
panvk_physical_device_init(struct panvk_physical_device * device,struct panvk_instance * instance,drmDevicePtr drm_device)410 panvk_physical_device_init(struct panvk_physical_device *device,
411 struct panvk_instance *instance,
412 drmDevicePtr drm_device)
413 {
414 const char *path = drm_device->nodes[DRM_NODE_RENDER];
415 VkResult result = VK_SUCCESS;
416 drmVersionPtr version;
417 int fd;
418 int master_fd = -1;
419
420 if (!getenv("PAN_I_WANT_A_BROKEN_VULKAN_DRIVER")) {
421 return vk_errorf(
422 instance, VK_ERROR_INCOMPATIBLE_DRIVER,
423 "WARNING: panvk is not a conformant vulkan implementation, "
424 "pass PAN_I_WANT_A_BROKEN_VULKAN_DRIVER=1 if you know what you're doing.");
425 }
426
427 fd = open(path, O_RDWR | O_CLOEXEC);
428 if (fd < 0) {
429 return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
430 "failed to open device %s", path);
431 }
432
433 version = drmGetVersion(fd);
434 if (!version) {
435 close(fd);
436 return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
437 "failed to query kernel driver version for device %s",
438 path);
439 }
440
441 if (strcmp(version->name, "panfrost")) {
442 drmFreeVersion(version);
443 close(fd);
444 return vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
445 "device %s does not use the panfrost kernel driver",
446 path);
447 }
448
449 drmFreeVersion(version);
450
451 if (instance->debug_flags & PANVK_DEBUG_STARTUP)
452 vk_logi(VK_LOG_NO_OBJS(instance), "Found compatible device '%s'.", path);
453
454 struct vk_device_extension_table supported_extensions;
455 panvk_get_device_extensions(device, &supported_extensions);
456
457 struct vk_features supported_features;
458 panvk_get_features(device, &supported_features);
459
460 struct vk_physical_device_dispatch_table dispatch_table;
461 vk_physical_device_dispatch_table_from_entrypoints(
462 &dispatch_table, &panvk_physical_device_entrypoints, true);
463 vk_physical_device_dispatch_table_from_entrypoints(
464 &dispatch_table, &wsi_physical_device_entrypoints, false);
465
466 result =
467 vk_physical_device_init(&device->vk, &instance->vk, &supported_extensions,
468 &supported_features, NULL, &dispatch_table);
469
470 if (result != VK_SUCCESS) {
471 vk_error(instance, result);
472 goto fail;
473 }
474
475 device->instance = instance;
476
477 if (instance->vk.enabled_extensions.KHR_display) {
478 master_fd = open(drm_device->nodes[DRM_NODE_PRIMARY], O_RDWR | O_CLOEXEC);
479 if (master_fd >= 0) {
480 /* TODO: free master_fd is accel is not working? */
481 }
482 }
483
484 device->master_fd = master_fd;
485
486 device->kmod.dev = pan_kmod_dev_create(fd, PAN_KMOD_DEV_FLAG_OWNS_FD,
487 &instance->kmod.allocator);
488 pan_kmod_dev_query_props(device->kmod.dev, &device->kmod.props);
489
490 unsigned arch = pan_arch(device->kmod.props.gpu_prod_id);
491
492 device->model = panfrost_get_model(device->kmod.props.gpu_prod_id);
493 device->formats.all = panfrost_format_table(arch);
494 device->formats.blendable = panfrost_blendable_format_table(arch);
495
496 if (arch <= 5 || arch >= 8) {
497 result = vk_errorf(instance, VK_ERROR_INCOMPATIBLE_DRIVER,
498 "%s not supported", device->model->name);
499 goto fail;
500 }
501
502 memset(device->name, 0, sizeof(device->name));
503 sprintf(device->name, "%s", device->model->name);
504
505 if (panvk_device_get_cache_uuid(device->kmod.props.gpu_prod_id,
506 device->cache_uuid)) {
507 result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
508 "cannot generate UUID");
509 goto fail_close_device;
510 }
511
512 vk_warn_non_conformant_implementation("panvk");
513
514 panvk_get_driver_uuid(&device->device_uuid);
515 panvk_get_device_uuid(&device->device_uuid);
516
517 device->drm_syncobj_type =
518 vk_drm_syncobj_get_type(device->kmod.dev->fd);
519 /* We don't support timelines in the uAPI yet and we don't want it getting
520 * suddenly turned on by vk_drm_syncobj_get_type() without us adding panvk
521 * code for it first.
522 */
523 device->drm_syncobj_type.features &= ~VK_SYNC_FEATURE_TIMELINE;
524
525 device->sync_types[0] = &device->drm_syncobj_type;
526 device->sync_types[1] = NULL;
527 device->vk.supported_sync_types = device->sync_types;
528
529 result = panvk_wsi_init(device);
530 if (result != VK_SUCCESS) {
531 vk_error(instance, result);
532 goto fail_close_device;
533 }
534
535 return VK_SUCCESS;
536
537 fail_close_device:
538 pan_kmod_dev_destroy(device->kmod.dev);
539 fail:
540 if (fd != -1)
541 close(fd);
542 if (master_fd != -1)
543 close(master_fd);
544 return result;
545 }
546
547 VkResult
panvk_physical_device_try_create(struct vk_instance * vk_instance,struct _drmDevice * drm_device,struct vk_physical_device ** out)548 panvk_physical_device_try_create(struct vk_instance *vk_instance,
549 struct _drmDevice *drm_device,
550 struct vk_physical_device **out)
551 {
552 struct panvk_instance *instance =
553 container_of(vk_instance, struct panvk_instance, vk);
554
555 if (!(drm_device->available_nodes & (1 << DRM_NODE_RENDER)) ||
556 drm_device->bustype != DRM_BUS_PLATFORM)
557 return VK_ERROR_INCOMPATIBLE_DRIVER;
558
559 struct panvk_physical_device *device =
560 vk_zalloc(&instance->vk.alloc, sizeof(*device), 8,
561 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
562 if (!device)
563 return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
564
565 VkResult result = panvk_physical_device_init(device, instance, drm_device);
566 if (result != VK_SUCCESS) {
567 vk_free(&instance->vk.alloc, device);
568 return result;
569 }
570
571 *out = &device->vk;
572 return VK_SUCCESS;
573 }
574
575 void
panvk_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceProperties2 * pProperties)576 panvk_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
577 VkPhysicalDeviceProperties2 *pProperties)
578 {
579 VK_FROM_HANDLE(panvk_physical_device, pdevice, physicalDevice);
580
581 VkSampleCountFlags sample_counts =
582 VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT;
583
584 /* make sure that the entire descriptor set is addressable with a signed
585 * 32-bit int. So the sum of all limits scaled by descriptor size has to
586 * be at most 2 GiB. the combined image & samples object count as one of
587 * both. This limit is for the pipeline layout, not for the set layout, but
588 * there is no set limit, so we just set a pipeline limit. I don't think
589 * any app is going to hit this soon. */
590 size_t max_descriptor_set_size =
591 ((1ull << 31) - 16 * MAX_DYNAMIC_BUFFERS) /
592 (32 /* uniform buffer, 32 due to potential space wasted on alignment */ +
593 32 /* storage buffer, 32 due to potential space wasted on alignment */ +
594 32 /* sampler, largest when combined with image */ +
595 64 /* sampled image */ + 64 /* storage image */);
596
597 const VkPhysicalDeviceLimits limits = {
598 .maxImageDimension1D = (1 << 14),
599 .maxImageDimension2D = (1 << 14),
600 .maxImageDimension3D = (1 << 11),
601 .maxImageDimensionCube = (1 << 14),
602 .maxImageArrayLayers = (1 << 11),
603 .maxTexelBufferElements = 128 * 1024 * 1024,
604 .maxUniformBufferRange = UINT32_MAX,
605 .maxStorageBufferRange = UINT32_MAX,
606 .maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,
607 .maxMemoryAllocationCount = UINT32_MAX,
608 .maxSamplerAllocationCount = 64 * 1024,
609 .bufferImageGranularity = 64, /* A cache line */
610 .sparseAddressSpaceSize = 0xffffffffu, /* buffer max size */
611 .maxBoundDescriptorSets = MAX_SETS,
612 .maxPerStageDescriptorSamplers = max_descriptor_set_size,
613 .maxPerStageDescriptorUniformBuffers = max_descriptor_set_size,
614 .maxPerStageDescriptorStorageBuffers = max_descriptor_set_size,
615 .maxPerStageDescriptorSampledImages = max_descriptor_set_size,
616 .maxPerStageDescriptorStorageImages = max_descriptor_set_size,
617 .maxPerStageDescriptorInputAttachments = max_descriptor_set_size,
618 .maxPerStageResources = max_descriptor_set_size,
619 .maxDescriptorSetSamplers = max_descriptor_set_size,
620 .maxDescriptorSetUniformBuffers = max_descriptor_set_size,
621 .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS,
622 .maxDescriptorSetStorageBuffers = max_descriptor_set_size,
623 .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS,
624 .maxDescriptorSetSampledImages = max_descriptor_set_size,
625 .maxDescriptorSetStorageImages = max_descriptor_set_size,
626 .maxDescriptorSetInputAttachments = max_descriptor_set_size,
627 .maxVertexInputAttributes = 32,
628 .maxVertexInputBindings = 32,
629 .maxVertexInputAttributeOffset = 2047,
630 .maxVertexInputBindingStride = 2048,
631 .maxVertexOutputComponents = 128,
632 .maxTessellationGenerationLevel = 64,
633 .maxTessellationPatchSize = 32,
634 .maxTessellationControlPerVertexInputComponents = 128,
635 .maxTessellationControlPerVertexOutputComponents = 128,
636 .maxTessellationControlPerPatchOutputComponents = 120,
637 .maxTessellationControlTotalOutputComponents = 4096,
638 .maxTessellationEvaluationInputComponents = 128,
639 .maxTessellationEvaluationOutputComponents = 128,
640 .maxGeometryShaderInvocations = 127,
641 .maxGeometryInputComponents = 64,
642 .maxGeometryOutputComponents = 128,
643 .maxGeometryOutputVertices = 256,
644 .maxGeometryTotalOutputComponents = 1024,
645 .maxFragmentInputComponents = 128,
646 .maxFragmentOutputAttachments = 8,
647 .maxFragmentDualSrcAttachments = 1,
648 .maxFragmentCombinedOutputResources =
649 MAX_RTS + max_descriptor_set_size * 2,
650 .maxComputeSharedMemorySize = 32768,
651 .maxComputeWorkGroupCount = {65535, 65535, 65535},
652 .maxComputeWorkGroupInvocations = 2048,
653 .maxComputeWorkGroupSize = {2048, 2048, 2048},
654 .subPixelPrecisionBits = 4 /* FIXME */,
655 .subTexelPrecisionBits = 4 /* FIXME */,
656 .mipmapPrecisionBits = 4 /* FIXME */,
657 .maxDrawIndexedIndexValue = UINT32_MAX,
658 .maxDrawIndirectCount = UINT32_MAX,
659 .maxSamplerLodBias = 16,
660 .maxSamplerAnisotropy = 16,
661 .maxViewports = MAX_VIEWPORTS,
662 .maxViewportDimensions = {(1 << 14), (1 << 14)},
663 .viewportBoundsRange = {INT16_MIN, INT16_MAX},
664 .viewportSubPixelBits = 8,
665 .minMemoryMapAlignment = 4096, /* A page */
666 .minTexelBufferOffsetAlignment = 64,
667 .minUniformBufferOffsetAlignment = 16,
668 .minStorageBufferOffsetAlignment = 4,
669 .minTexelOffset = -32,
670 .maxTexelOffset = 31,
671 .minTexelGatherOffset = -32,
672 .maxTexelGatherOffset = 31,
673 .minInterpolationOffset = -2,
674 .maxInterpolationOffset = 2,
675 .subPixelInterpolationOffsetBits = 8,
676 .maxFramebufferWidth = (1 << 14),
677 .maxFramebufferHeight = (1 << 14),
678 .maxFramebufferLayers = (1 << 10),
679 .framebufferColorSampleCounts = sample_counts,
680 .framebufferDepthSampleCounts = sample_counts,
681 .framebufferStencilSampleCounts = sample_counts,
682 .framebufferNoAttachmentsSampleCounts = sample_counts,
683 .maxColorAttachments = MAX_RTS,
684 .sampledImageColorSampleCounts = sample_counts,
685 .sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT,
686 .sampledImageDepthSampleCounts = sample_counts,
687 .sampledImageStencilSampleCounts = sample_counts,
688 .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT,
689 .maxSampleMaskWords = 1,
690 .timestampComputeAndGraphics = true,
691 .timestampPeriod = 1,
692 .maxClipDistances = 8,
693 .maxCullDistances = 8,
694 .maxCombinedClipAndCullDistances = 8,
695 .discreteQueuePriorities = 1,
696 .pointSizeRange = {0.125, 4095.9375},
697 .lineWidthRange = {0.0, 7.9921875},
698 .pointSizeGranularity = (1.0 / 16.0),
699 .lineWidthGranularity = (1.0 / 128.0),
700 .strictLines = false, /* FINISHME */
701 .standardSampleLocations = true,
702 .optimalBufferCopyOffsetAlignment = 128,
703 .optimalBufferCopyRowPitchAlignment = 128,
704 .nonCoherentAtomSize = 64,
705 };
706
707 pProperties->properties = (VkPhysicalDeviceProperties){
708 .apiVersion = PANVK_API_VERSION,
709 .driverVersion = vk_get_driver_version(),
710 .vendorID = 0, /* TODO */
711 .deviceID = 0,
712 .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
713 .limits = limits,
714 .sparseProperties = {0},
715 };
716
717 strcpy(pProperties->properties.deviceName, pdevice->name);
718 memcpy(pProperties->properties.pipelineCacheUUID, pdevice->cache_uuid,
719 VK_UUID_SIZE);
720
721 VkPhysicalDeviceVulkan11Properties core_1_1 = {
722 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES,
723 .deviceLUIDValid = false,
724 .pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES,
725 .maxMultiviewViewCount = 0,
726 .maxMultiviewInstanceIndex = 0,
727 .protectedNoFault = false,
728 /* Make sure everything is addressable by a signed 32-bit int, and
729 * our largest descriptors are 96 bytes. */
730 .maxPerSetDescriptors = (1ull << 31) / 96,
731 /* Our buffer size fields allow only this much */
732 .maxMemoryAllocationSize = 0xFFFFFFFFull,
733 };
734 memcpy(core_1_1.driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
735 memcpy(core_1_1.deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
736
737 const VkPhysicalDeviceVulkan12Properties core_1_2 = {
738 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES,
739 };
740
741 const VkPhysicalDeviceVulkan13Properties core_1_3 = {
742 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES,
743 };
744
745 vk_foreach_struct(ext, pProperties->pNext) {
746 if (vk_get_physical_device_core_1_1_property_ext(ext, &core_1_1))
747 continue;
748 if (vk_get_physical_device_core_1_2_property_ext(ext, &core_1_2))
749 continue;
750 if (vk_get_physical_device_core_1_3_property_ext(ext, &core_1_3))
751 continue;
752
753 switch (ext->sType) {
754 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
755 VkPhysicalDevicePushDescriptorPropertiesKHR *properties =
756 (VkPhysicalDevicePushDescriptorPropertiesKHR *)ext;
757 properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
758 break;
759 }
760 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
761 VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *properties =
762 (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext;
763 /* We have to restrict this a bit for multiview */
764 properties->maxVertexAttribDivisor = UINT32_MAX / (16 * 2048);
765 break;
766 }
767 default:
768 break;
769 }
770 }
771 }
772
773 static const VkQueueFamilyProperties panvk_queue_family_properties = {
774 .queueFlags =
775 VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT,
776 .queueCount = 1,
777 .timestampValidBits = 64,
778 .minImageTransferGranularity = {1, 1, 1},
779 };
780
781 void
panvk_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties2 * pQueueFamilyProperties)782 panvk_GetPhysicalDeviceQueueFamilyProperties2(
783 VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
784 VkQueueFamilyProperties2 *pQueueFamilyProperties)
785 {
786 VK_OUTARRAY_MAKE_TYPED(VkQueueFamilyProperties2, out, pQueueFamilyProperties,
787 pQueueFamilyPropertyCount);
788
789 vk_outarray_append_typed(VkQueueFamilyProperties2, &out, p)
790 {
791 p->queueFamilyProperties = panvk_queue_family_properties;
792 }
793 }
794
795 static uint64_t
panvk_get_system_heap_size()796 panvk_get_system_heap_size()
797 {
798 struct sysinfo info;
799 sysinfo(&info);
800
801 uint64_t total_ram = (uint64_t)info.totalram * info.mem_unit;
802
803 /* We don't want to burn too much ram with the GPU. If the user has 4GiB
804 * or less, we use at most half. If they have more than 4GiB, we use 3/4.
805 */
806 uint64_t available_ram;
807 if (total_ram <= 4ull * 1024 * 1024 * 1024)
808 available_ram = total_ram / 2;
809 else
810 available_ram = total_ram * 3 / 4;
811
812 return available_ram;
813 }
814
815 void
panvk_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceMemoryProperties2 * pMemoryProperties)816 panvk_GetPhysicalDeviceMemoryProperties2(
817 VkPhysicalDevice physicalDevice,
818 VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
819 {
820 pMemoryProperties->memoryProperties = (VkPhysicalDeviceMemoryProperties){
821 .memoryHeapCount = 1,
822 .memoryHeaps[0].size = panvk_get_system_heap_size(),
823 .memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
824 .memoryTypeCount = 1,
825 .memoryTypes[0].propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
826 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
827 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
828 .memoryTypes[0].heapIndex = 0,
829 };
830 }
831
832 static VkResult
panvk_queue_init(struct panvk_device * device,struct panvk_queue * queue,int idx,const VkDeviceQueueCreateInfo * create_info)833 panvk_queue_init(struct panvk_device *device, struct panvk_queue *queue,
834 int idx, const VkDeviceQueueCreateInfo *create_info)
835 {
836 VkResult result = vk_queue_init(&queue->vk, &device->vk, create_info, idx);
837 if (result != VK_SUCCESS)
838 return result;
839 queue->device = device;
840
841 struct drm_syncobj_create create = {
842 .flags = DRM_SYNCOBJ_CREATE_SIGNALED,
843 };
844
845 int ret = drmIoctl(device->vk.drm_fd, DRM_IOCTL_SYNCOBJ_CREATE, &create);
846 if (ret) {
847 vk_queue_finish(&queue->vk);
848 return VK_ERROR_OUT_OF_HOST_MEMORY;
849 }
850
851 unsigned arch = pan_arch(device->physical_device->kmod.props.gpu_prod_id);
852
853 switch (arch) {
854 case 6:
855 queue->vk.driver_submit = panvk_v6_queue_submit;
856 break;
857 case 7:
858 queue->vk.driver_submit = panvk_v7_queue_submit;
859 break;
860 default:
861 unreachable("Unsupported architecture");
862 }
863
864 queue->sync = create.handle;
865 return VK_SUCCESS;
866 }
867
868 static void
panvk_queue_finish(struct panvk_queue * queue)869 panvk_queue_finish(struct panvk_queue *queue)
870 {
871 vk_queue_finish(&queue->vk);
872 }
873
panvk_priv_bo_create(struct panvk_device * dev,size_t size,uint32_t flags,const struct VkAllocationCallbacks * alloc,VkSystemAllocationScope scope)874 struct panvk_priv_bo *panvk_priv_bo_create(struct panvk_device *dev,
875 size_t size, uint32_t flags,
876 const struct VkAllocationCallbacks *alloc,
877 VkSystemAllocationScope scope)
878 {
879 int ret;
880 struct panvk_priv_bo *priv_bo =
881 vk_zalloc2(&dev->vk.alloc, alloc, sizeof(*priv_bo), 8, scope);
882
883 if (!priv_bo)
884 return NULL;
885
886 struct pan_kmod_bo *bo =
887 pan_kmod_bo_alloc(dev->kmod.dev, dev->kmod.vm, size, flags);
888 if (!bo)
889 goto err_free_priv_bo;
890
891 priv_bo->bo = bo;
892 priv_bo->dev = dev;
893
894 if (!(flags & PAN_KMOD_BO_FLAG_NO_MMAP)) {
895 priv_bo->addr.host = pan_kmod_bo_mmap(
896 bo, 0, pan_kmod_bo_size(bo), PROT_READ | PROT_WRITE, MAP_SHARED, NULL);
897 if (priv_bo->addr.host == MAP_FAILED)
898 goto err_put_bo;
899 }
900
901 struct pan_kmod_vm_op op = {
902 .type = PAN_KMOD_VM_OP_TYPE_MAP,
903 .va = {
904 .start = PAN_KMOD_VM_MAP_AUTO_VA,
905 .size = pan_kmod_bo_size(bo),
906 },
907 .map = {
908 .bo = priv_bo->bo,
909 .bo_offset = 0,
910 },
911 };
912
913 ret = pan_kmod_vm_bind(dev->kmod.vm, PAN_KMOD_VM_OP_MODE_IMMEDIATE, &op, 1);
914 if (ret)
915 goto err_munmap_bo;
916
917
918 priv_bo->addr.dev = op.va.start;
919
920 if (dev->debug.decode_ctx) {
921 pandecode_inject_mmap(dev->debug.decode_ctx, priv_bo->addr.dev,
922 priv_bo->addr.host, pan_kmod_bo_size(priv_bo->bo),
923 NULL);
924 }
925
926 return priv_bo;
927
928 err_munmap_bo:
929 if (priv_bo->addr.host) {
930 ret = os_munmap(priv_bo->addr.host, pan_kmod_bo_size(bo));
931 assert(!ret);
932 }
933
934 err_put_bo:
935 pan_kmod_bo_put(bo);
936
937 err_free_priv_bo:
938 vk_free2(&dev->vk.alloc, alloc, priv_bo);
939 return NULL;
940 }
941
942 void
panvk_priv_bo_destroy(struct panvk_priv_bo * priv_bo,const VkAllocationCallbacks * alloc)943 panvk_priv_bo_destroy(struct panvk_priv_bo *priv_bo,
944 const VkAllocationCallbacks *alloc)
945 {
946 if (!priv_bo)
947 return;
948
949 struct panvk_device *dev = priv_bo->dev;
950
951 if (dev->debug.decode_ctx) {
952 pandecode_inject_free(dev->debug.decode_ctx, priv_bo->addr.dev,
953 pan_kmod_bo_size(priv_bo->bo));
954 }
955
956 struct pan_kmod_vm_op op = {
957 .type = PAN_KMOD_VM_OP_TYPE_UNMAP,
958 .va = {
959 .start = priv_bo->addr.dev,
960 .size = pan_kmod_bo_size(priv_bo->bo),
961 },
962 };
963 ASSERTED int ret =
964 pan_kmod_vm_bind(dev->kmod.vm, PAN_KMOD_VM_OP_MODE_IMMEDIATE, &op, 1);
965 assert(!ret);
966
967 if (priv_bo->addr.host) {
968 ret = os_munmap(priv_bo->addr.host, pan_kmod_bo_size(priv_bo->bo));
969 assert(!ret);
970 }
971
972 pan_kmod_bo_put(priv_bo->bo);
973 vk_free2(&dev->vk.alloc, alloc, priv_bo);
974 }
975
976 /* Always reserve the lower 32MB. */
977 #define PANVK_VA_RESERVE_BOTTOM 0x2000000ull
978
979 VkResult
panvk_CreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)980 panvk_CreateDevice(VkPhysicalDevice physicalDevice,
981 const VkDeviceCreateInfo *pCreateInfo,
982 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice)
983 {
984 VK_FROM_HANDLE(panvk_physical_device, physical_device, physicalDevice);
985 struct panvk_instance *instance = physical_device->instance;
986 VkResult result;
987 struct panvk_device *device;
988
989 device = vk_zalloc2(&physical_device->instance->vk.alloc, pAllocator,
990 sizeof(*device), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
991 if (!device)
992 return vk_error(physical_device, VK_ERROR_OUT_OF_HOST_MEMORY);
993
994 const struct vk_device_entrypoint_table *dev_entrypoints;
995 const struct vk_command_buffer_ops *cmd_buffer_ops;
996 struct vk_device_dispatch_table dispatch_table;
997 unsigned arch = pan_arch(physical_device->kmod.props.gpu_prod_id);
998
999 switch (arch) {
1000 case 6:
1001 dev_entrypoints = &panvk_v6_device_entrypoints;
1002 cmd_buffer_ops = &panvk_v6_cmd_buffer_ops;
1003 break;
1004 case 7:
1005 dev_entrypoints = &panvk_v7_device_entrypoints;
1006 cmd_buffer_ops = &panvk_v7_cmd_buffer_ops;
1007 break;
1008 default:
1009 unreachable("Unsupported architecture");
1010 }
1011
1012 /* For secondary command buffer support, overwrite any command entrypoints
1013 * in the main device-level dispatch table with
1014 * vk_cmd_enqueue_unless_primary_Cmd*.
1015 */
1016 vk_device_dispatch_table_from_entrypoints(
1017 &dispatch_table, &vk_cmd_enqueue_unless_primary_device_entrypoints, true);
1018
1019 vk_device_dispatch_table_from_entrypoints(&dispatch_table, dev_entrypoints,
1020 false);
1021 vk_device_dispatch_table_from_entrypoints(&dispatch_table,
1022 &panvk_device_entrypoints, false);
1023 vk_device_dispatch_table_from_entrypoints(&dispatch_table,
1024 &wsi_device_entrypoints, false);
1025
1026 /* Populate our primary cmd_dispatch table. */
1027 vk_device_dispatch_table_from_entrypoints(&device->cmd_dispatch,
1028 dev_entrypoints, true);
1029 vk_device_dispatch_table_from_entrypoints(&device->cmd_dispatch,
1030 &panvk_device_entrypoints, false);
1031 vk_device_dispatch_table_from_entrypoints(
1032 &device->cmd_dispatch, &vk_common_device_entrypoints, false);
1033
1034 result = vk_device_init(&device->vk, &physical_device->vk, &dispatch_table,
1035 pCreateInfo, pAllocator);
1036 if (result != VK_SUCCESS) {
1037 vk_free(&device->vk.alloc, device);
1038 return result;
1039 }
1040
1041 /* Must be done after vk_device_init() because this function memset(0) the
1042 * whole struct.
1043 */
1044 device->vk.command_dispatch_table = &device->cmd_dispatch;
1045 device->vk.command_buffer_ops = cmd_buffer_ops;
1046
1047 device->instance = physical_device->instance;
1048 device->physical_device = physical_device;
1049
1050 device->kmod.allocator = (struct pan_kmod_allocator){
1051 .zalloc = panvk_kmod_zalloc,
1052 .free = panvk_kmod_free,
1053 .priv = &device->vk.alloc,
1054 };
1055 device->kmod.dev =
1056 pan_kmod_dev_create(dup(physical_device->kmod.dev->fd),
1057 PAN_KMOD_DEV_FLAG_OWNS_FD, &device->kmod.allocator);
1058
1059 if (instance->debug_flags & PANVK_DEBUG_TRACE)
1060 device->debug.decode_ctx = pandecode_create_context(false);
1061
1062 /* 32bit address space, with the lower 32MB reserved. We clamp
1063 * things so it matches kmod VA range limitations.
1064 */
1065 uint64_t user_va_start = panfrost_clamp_to_usable_va_range(
1066 device->kmod.dev, PANVK_VA_RESERVE_BOTTOM);
1067 uint64_t user_va_end =
1068 panfrost_clamp_to_usable_va_range(device->kmod.dev, 1ull << 32);
1069
1070 device->kmod.vm =
1071 pan_kmod_vm_create(device->kmod.dev, PAN_KMOD_VM_FLAG_AUTO_VA,
1072 user_va_start, user_va_end - user_va_start);
1073
1074 device->tiler_heap = panvk_priv_bo_create(
1075 device, 128 * 1024 * 1024,
1076 PAN_KMOD_BO_FLAG_NO_MMAP | PAN_KMOD_BO_FLAG_ALLOC_ON_FAULT,
1077 &device->vk.alloc, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1078
1079 device->sample_positions = panvk_priv_bo_create(
1080 device, panfrost_sample_positions_buffer_size(), 0,
1081 &device->vk.alloc, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1082 panfrost_upload_sample_positions(device->sample_positions->addr.host);
1083
1084 vk_device_set_drm_fd(&device->vk, device->kmod.dev->fd);
1085
1086 panvk_arch_dispatch(arch, meta_init, device);
1087
1088 for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
1089 const VkDeviceQueueCreateInfo *queue_create =
1090 &pCreateInfo->pQueueCreateInfos[i];
1091 uint32_t qfi = queue_create->queueFamilyIndex;
1092 device->queues[qfi] =
1093 vk_alloc(&device->vk.alloc,
1094 queue_create->queueCount * sizeof(struct panvk_queue), 8,
1095 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1096 if (!device->queues[qfi]) {
1097 result = VK_ERROR_OUT_OF_HOST_MEMORY;
1098 goto fail;
1099 }
1100
1101 memset(device->queues[qfi], 0,
1102 queue_create->queueCount * sizeof(struct panvk_queue));
1103
1104 device->queue_count[qfi] = queue_create->queueCount;
1105
1106 for (unsigned q = 0; q < queue_create->queueCount; q++) {
1107 result =
1108 panvk_queue_init(device, &device->queues[qfi][q], q, queue_create);
1109 if (result != VK_SUCCESS)
1110 goto fail;
1111 }
1112 }
1113
1114 *pDevice = panvk_device_to_handle(device);
1115 return VK_SUCCESS;
1116
1117 fail:
1118 for (unsigned i = 0; i < PANVK_MAX_QUEUE_FAMILIES; i++) {
1119 for (unsigned q = 0; q < device->queue_count[i]; q++)
1120 panvk_queue_finish(&device->queues[i][q]);
1121 if (device->queue_count[i])
1122 vk_object_free(&device->vk, NULL, device->queues[i]);
1123 }
1124
1125 panvk_arch_dispatch(pan_arch(physical_device->kmod.props.gpu_prod_id),
1126 meta_cleanup, device);
1127 panvk_priv_bo_destroy(device->tiler_heap, &device->vk.alloc);
1128 panvk_priv_bo_destroy(device->sample_positions, &device->vk.alloc);
1129 pan_kmod_vm_destroy(device->kmod.vm);
1130 pan_kmod_dev_destroy(device->kmod.dev);
1131
1132 vk_free(&device->vk.alloc, device);
1133 return result;
1134 }
1135
1136 void
panvk_DestroyDevice(VkDevice _device,const VkAllocationCallbacks * pAllocator)1137 panvk_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator)
1138 {
1139 VK_FROM_HANDLE(panvk_device, device, _device);
1140 struct panvk_physical_device *physical_device = device->physical_device;
1141
1142 if (!device)
1143 return;
1144
1145 if (device->debug.decode_ctx)
1146 pandecode_destroy_context(device->debug.decode_ctx);
1147
1148 for (unsigned i = 0; i < PANVK_MAX_QUEUE_FAMILIES; i++) {
1149 for (unsigned q = 0; q < device->queue_count[i]; q++)
1150 panvk_queue_finish(&device->queues[i][q]);
1151 if (device->queue_count[i])
1152 vk_object_free(&device->vk, NULL, device->queues[i]);
1153 }
1154
1155 panvk_arch_dispatch(pan_arch(physical_device->kmod.props.gpu_prod_id),
1156 meta_cleanup, device);
1157 panvk_priv_bo_destroy(device->tiler_heap, &device->vk.alloc);
1158 panvk_priv_bo_destroy(device->sample_positions, &device->vk.alloc);
1159 pan_kmod_vm_destroy(device->kmod.vm);
1160 pan_kmod_dev_destroy(device->kmod.dev);
1161 vk_free(&device->vk.alloc, device);
1162 }
1163
1164 VkResult
panvk_EnumerateInstanceLayerProperties(uint32_t * pPropertyCount,VkLayerProperties * pProperties)1165 panvk_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
1166 VkLayerProperties *pProperties)
1167 {
1168 *pPropertyCount = 0;
1169 return VK_SUCCESS;
1170 }
1171
1172 VkResult
panvk_QueueWaitIdle(VkQueue _queue)1173 panvk_QueueWaitIdle(VkQueue _queue)
1174 {
1175 VK_FROM_HANDLE(panvk_queue, queue, _queue);
1176
1177 if (panvk_device_is_lost(queue->device))
1178 return VK_ERROR_DEVICE_LOST;
1179
1180 struct drm_syncobj_wait wait = {
1181 .handles = (uint64_t)(uintptr_t)(&queue->sync),
1182 .count_handles = 1,
1183 .timeout_nsec = INT64_MAX,
1184 .flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL,
1185 };
1186 int ret;
1187
1188 ret = drmIoctl(queue->vk.base.device->drm_fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait);
1189 assert(!ret);
1190
1191 return VK_SUCCESS;
1192 }
1193
1194 VkResult
panvk_EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)1195 panvk_EnumerateInstanceExtensionProperties(const char *pLayerName,
1196 uint32_t *pPropertyCount,
1197 VkExtensionProperties *pProperties)
1198 {
1199 if (pLayerName)
1200 return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1201
1202 return vk_enumerate_instance_extension_properties(
1203 &panvk_instance_extensions, pPropertyCount, pProperties);
1204 }
1205
1206 PFN_vkVoidFunction
panvk_GetInstanceProcAddr(VkInstance _instance,const char * pName)1207 panvk_GetInstanceProcAddr(VkInstance _instance, const char *pName)
1208 {
1209 VK_FROM_HANDLE(panvk_instance, instance, _instance);
1210 return vk_instance_get_proc_addr(&instance->vk, &panvk_instance_entrypoints,
1211 pName);
1212 }
1213
1214 /* The loader wants us to expose a second GetInstanceProcAddr function
1215 * to work around certain LD_PRELOAD issues seen in apps.
1216 */
1217 PUBLIC
1218 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance,const char * pName)1219 vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)
1220 {
1221 return panvk_GetInstanceProcAddr(instance, pName);
1222 }
1223
1224 VkResult
panvk_AllocateMemory(VkDevice _device,const VkMemoryAllocateInfo * pAllocateInfo,const VkAllocationCallbacks * pAllocator,VkDeviceMemory * pMem)1225 panvk_AllocateMemory(VkDevice _device,
1226 const VkMemoryAllocateInfo *pAllocateInfo,
1227 const VkAllocationCallbacks *pAllocator,
1228 VkDeviceMemory *pMem)
1229 {
1230 VK_FROM_HANDLE(panvk_device, device, _device);
1231 struct panvk_device_memory *mem;
1232 bool can_be_exported = false;
1233
1234 assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
1235
1236 if (pAllocateInfo->allocationSize == 0) {
1237 /* Apparently, this is allowed */
1238 *pMem = VK_NULL_HANDLE;
1239 return VK_SUCCESS;
1240 }
1241
1242 const VkExportMemoryAllocateInfo *export_info =
1243 vk_find_struct_const(pAllocateInfo->pNext, EXPORT_MEMORY_ALLOCATE_INFO);
1244
1245 if (export_info) {
1246 if (export_info->handleTypes &
1247 ~(VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT |
1248 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT))
1249 return vk_error(device, VK_ERROR_INVALID_EXTERNAL_HANDLE);
1250 else if (export_info->handleTypes)
1251 can_be_exported = true;
1252 }
1253
1254 mem = vk_object_zalloc(&device->vk, pAllocator, sizeof(*mem),
1255 VK_OBJECT_TYPE_DEVICE_MEMORY);
1256 if (mem == NULL)
1257 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1258
1259 const VkImportMemoryFdInfoKHR *fd_info =
1260 vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
1261
1262 if (fd_info && !fd_info->handleType)
1263 fd_info = NULL;
1264
1265 if (fd_info) {
1266 assert(
1267 fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
1268 fd_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
1269
1270 /*
1271 * TODO Importing the same fd twice gives us the same handle without
1272 * reference counting. We need to maintain a per-instance handle-to-bo
1273 * table and add reference count to panvk_bo.
1274 */
1275 mem->bo = pan_kmod_bo_import(device->kmod.dev, fd_info->fd, 0);
1276 /* take ownership and close the fd */
1277 close(fd_info->fd);
1278 } else {
1279 mem->bo = pan_kmod_bo_alloc(device->kmod.dev,
1280 can_be_exported ? NULL : device->kmod.vm,
1281 pAllocateInfo->allocationSize, 0);
1282 }
1283
1284 /* Always GPU-map at creation time. */
1285 struct pan_kmod_vm_op op = {
1286 .type = PAN_KMOD_VM_OP_TYPE_MAP,
1287 .va = {
1288 .start = PAN_KMOD_VM_MAP_AUTO_VA,
1289 .size = pan_kmod_bo_size(mem->bo),
1290 },
1291 .map = {
1292 .bo = mem->bo,
1293 .bo_offset = 0,
1294 },
1295 };
1296
1297 ASSERTED int ret =
1298 pan_kmod_vm_bind(device->kmod.vm, PAN_KMOD_VM_OP_MODE_IMMEDIATE, &op, 1);
1299 assert(!ret);
1300
1301 mem->addr.dev = op.va.start;
1302
1303 if (device->debug.decode_ctx) {
1304 pandecode_inject_mmap(device->debug.decode_ctx, mem->addr.dev, NULL,
1305 pan_kmod_bo_size(mem->bo), NULL);
1306 }
1307
1308 *pMem = panvk_device_memory_to_handle(mem);
1309
1310 return VK_SUCCESS;
1311 }
1312
1313 void
panvk_FreeMemory(VkDevice _device,VkDeviceMemory _mem,const VkAllocationCallbacks * pAllocator)1314 panvk_FreeMemory(VkDevice _device, VkDeviceMemory _mem,
1315 const VkAllocationCallbacks *pAllocator)
1316 {
1317 VK_FROM_HANDLE(panvk_device, device, _device);
1318 VK_FROM_HANDLE(panvk_device_memory, mem, _mem);
1319
1320 if (mem == NULL)
1321 return;
1322
1323 if (device->debug.decode_ctx) {
1324 pandecode_inject_free(device->debug.decode_ctx, mem->addr.dev,
1325 pan_kmod_bo_size(mem->bo));
1326 }
1327
1328 struct pan_kmod_vm_op op = {
1329 .type = PAN_KMOD_VM_OP_TYPE_UNMAP,
1330 .va = {
1331 .start = mem->addr.dev,
1332 .size = pan_kmod_bo_size(mem->bo),
1333 },
1334 };
1335
1336 ASSERTED int ret =
1337 pan_kmod_vm_bind(device->kmod.vm, PAN_KMOD_VM_OP_MODE_IMMEDIATE, &op, 1);
1338 assert(!ret);
1339
1340 pan_kmod_bo_put(mem->bo);
1341 vk_object_free(&device->vk, pAllocator, mem);
1342 }
1343
1344 VkResult
panvk_MapMemory(VkDevice _device,VkDeviceMemory _memory,VkDeviceSize offset,VkDeviceSize size,VkMemoryMapFlags flags,void ** ppData)1345 panvk_MapMemory(VkDevice _device, VkDeviceMemory _memory, VkDeviceSize offset,
1346 VkDeviceSize size, VkMemoryMapFlags flags, void **ppData)
1347 {
1348 VK_FROM_HANDLE(panvk_device, device, _device);
1349 VK_FROM_HANDLE(panvk_device_memory, mem, _memory);
1350
1351 if (mem == NULL) {
1352 *ppData = NULL;
1353 return VK_SUCCESS;
1354 }
1355
1356 /* Already mapped. */
1357 if (mem->addr.host)
1358 return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED);
1359
1360 void *addr = pan_kmod_bo_mmap(mem->bo, 0, pan_kmod_bo_size(mem->bo),
1361 PROT_READ | PROT_WRITE, MAP_SHARED, NULL);
1362 if (addr == MAP_FAILED)
1363 return vk_error(device, VK_ERROR_MEMORY_MAP_FAILED);
1364
1365 mem->addr.host = addr;
1366 *ppData = mem->addr.host + offset;
1367 return VK_SUCCESS;
1368 }
1369
1370 void
panvk_UnmapMemory(VkDevice _device,VkDeviceMemory _memory)1371 panvk_UnmapMemory(VkDevice _device, VkDeviceMemory _memory)
1372 {
1373 VK_FROM_HANDLE(panvk_device_memory, mem, _memory);
1374
1375 if (mem->addr.host) {
1376 ASSERTED int ret =
1377 os_munmap((void *)mem->addr.host, pan_kmod_bo_size(mem->bo));
1378
1379 assert(!ret);
1380 mem->addr.host = NULL;
1381 }
1382 }
1383
1384 VkResult
panvk_FlushMappedMemoryRanges(VkDevice _device,uint32_t memoryRangeCount,const VkMappedMemoryRange * pMemoryRanges)1385 panvk_FlushMappedMemoryRanges(VkDevice _device, uint32_t memoryRangeCount,
1386 const VkMappedMemoryRange *pMemoryRanges)
1387 {
1388 return VK_SUCCESS;
1389 }
1390
1391 VkResult
panvk_InvalidateMappedMemoryRanges(VkDevice _device,uint32_t memoryRangeCount,const VkMappedMemoryRange * pMemoryRanges)1392 panvk_InvalidateMappedMemoryRanges(VkDevice _device, uint32_t memoryRangeCount,
1393 const VkMappedMemoryRange *pMemoryRanges)
1394 {
1395 return VK_SUCCESS;
1396 }
1397
1398 VkDeviceAddress
panvk_GetBufferDeviceAddress(VkDevice _device,const VkBufferDeviceAddressInfo * pInfo)1399 panvk_GetBufferDeviceAddress(VkDevice _device, const VkBufferDeviceAddressInfo *pInfo)
1400 {
1401 VK_FROM_HANDLE(panvk_buffer, buffer, pInfo->buffer);
1402
1403 return buffer->dev_addr;
1404 }
1405
1406 void
panvk_GetBufferMemoryRequirements2(VkDevice device,const VkBufferMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1407 panvk_GetBufferMemoryRequirements2(VkDevice device,
1408 const VkBufferMemoryRequirementsInfo2 *pInfo,
1409 VkMemoryRequirements2 *pMemoryRequirements)
1410 {
1411 VK_FROM_HANDLE(panvk_buffer, buffer, pInfo->buffer);
1412
1413 const uint64_t alignment = 64;
1414 const uint64_t size = align64(buffer->vk.size, alignment);
1415
1416 pMemoryRequirements->memoryRequirements.memoryTypeBits = 1;
1417 pMemoryRequirements->memoryRequirements.alignment = alignment;
1418 pMemoryRequirements->memoryRequirements.size = size;
1419 }
1420
1421 void
panvk_GetImageMemoryRequirements2(VkDevice device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)1422 panvk_GetImageMemoryRequirements2(VkDevice device,
1423 const VkImageMemoryRequirementsInfo2 *pInfo,
1424 VkMemoryRequirements2 *pMemoryRequirements)
1425 {
1426 VK_FROM_HANDLE(panvk_image, image, pInfo->image);
1427
1428 const uint64_t alignment = 4096;
1429 const uint64_t size = panvk_image_get_total_size(image);
1430
1431 pMemoryRequirements->memoryRequirements.memoryTypeBits = 1;
1432 pMemoryRequirements->memoryRequirements.alignment = alignment;
1433 pMemoryRequirements->memoryRequirements.size = size;
1434 }
1435
1436 void
panvk_GetImageSparseMemoryRequirements2(VkDevice device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)1437 panvk_GetImageSparseMemoryRequirements2(
1438 VkDevice device, const VkImageSparseMemoryRequirementsInfo2 *pInfo,
1439 uint32_t *pSparseMemoryRequirementCount,
1440 VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
1441 {
1442 panvk_stub();
1443 }
1444
1445 void
panvk_GetDeviceMemoryCommitment(VkDevice device,VkDeviceMemory memory,VkDeviceSize * pCommittedMemoryInBytes)1446 panvk_GetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory,
1447 VkDeviceSize *pCommittedMemoryInBytes)
1448 {
1449 *pCommittedMemoryInBytes = 0;
1450 }
1451
1452 VkResult
panvk_BindBufferMemory2(VkDevice device,uint32_t bindInfoCount,const VkBindBufferMemoryInfo * pBindInfos)1453 panvk_BindBufferMemory2(VkDevice device, uint32_t bindInfoCount,
1454 const VkBindBufferMemoryInfo *pBindInfos)
1455 {
1456 for (uint32_t i = 0; i < bindInfoCount; ++i) {
1457 VK_FROM_HANDLE(panvk_device_memory, mem, pBindInfos[i].memory);
1458 VK_FROM_HANDLE(panvk_buffer, buffer, pBindInfos[i].buffer);
1459 struct pan_kmod_bo *old_bo = buffer->bo;
1460
1461 if (mem) {
1462 buffer->bo = pan_kmod_bo_get(mem->bo);
1463 buffer->dev_addr = mem->addr.dev + pBindInfos[i].memoryOffset;
1464
1465 /* FIXME: Only host map for index buffers so we can do the min/max
1466 * index retrieval on the CPU. This is all broken anyway and the
1467 * min/max search should be done with a compute shader that also
1468 * patches the job descriptor accordingly (basically an indirect draw).
1469 *
1470 * Make sure this goes away as soon as we fixed indirect draws.
1471 */
1472 if (buffer->vk.usage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) {
1473 VkDeviceSize offset = pBindInfos[i].memoryOffset;
1474 VkDeviceSize pgsize = getpagesize();
1475 off_t map_start = offset & ~(pgsize - 1);
1476 off_t map_end = offset + buffer->vk.size;
1477 void *map_addr =
1478 pan_kmod_bo_mmap(mem->bo, map_start, map_end - map_start,
1479 PROT_WRITE, MAP_SHARED, NULL);
1480
1481 assert(map_addr != MAP_FAILED);
1482 buffer->host_ptr = map_addr + (offset & pgsize);
1483 }
1484 } else {
1485 buffer->bo = NULL;
1486 buffer->dev_addr = 0;
1487 buffer->host_ptr = NULL;
1488 if (buffer->host_ptr) {
1489 VkDeviceSize pgsize = getpagesize();
1490 uintptr_t map_start = (uintptr_t)buffer->host_ptr & ~(pgsize - 1);
1491 uintptr_t map_end = (uintptr_t)buffer->host_ptr + buffer->vk.size;
1492 ASSERTED int ret =
1493 os_munmap((void *)map_start, map_end - map_start);
1494
1495 assert(!ret);
1496 buffer->host_ptr = NULL;
1497 }
1498 }
1499
1500 pan_kmod_bo_put(old_bo);
1501 }
1502 return VK_SUCCESS;
1503 }
1504
1505 VkResult
panvk_BindImageMemory2(VkDevice device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)1506 panvk_BindImageMemory2(VkDevice device, uint32_t bindInfoCount,
1507 const VkBindImageMemoryInfo *pBindInfos)
1508 {
1509 for (uint32_t i = 0; i < bindInfoCount; ++i) {
1510 VK_FROM_HANDLE(panvk_image, image, pBindInfos[i].image);
1511 VK_FROM_HANDLE(panvk_device_memory, mem, pBindInfos[i].memory);
1512 struct pan_kmod_bo *old_bo = image->bo;
1513
1514 if (mem) {
1515 image->bo = pan_kmod_bo_get(mem->bo);
1516 image->pimage.data.base = mem->addr.dev;
1517 image->pimage.data.offset = pBindInfos[i].memoryOffset;
1518 /* Reset the AFBC headers */
1519 if (drm_is_afbc(image->pimage.layout.modifier)) {
1520 /* Transient CPU mapping */
1521 void *base = pan_kmod_bo_mmap(mem->bo, 0, pan_kmod_bo_size(mem->bo),
1522 PROT_WRITE, MAP_SHARED, NULL);
1523
1524 assert(base != MAP_FAILED);
1525
1526 for (unsigned layer = 0; layer < image->pimage.layout.array_size;
1527 layer++) {
1528 for (unsigned level = 0; level < image->pimage.layout.nr_slices;
1529 level++) {
1530 void *header = base + image->pimage.data.offset +
1531 (layer * image->pimage.layout.array_stride) +
1532 image->pimage.layout.slices[level].offset;
1533 memset(header, 0,
1534 image->pimage.layout.slices[level].afbc.header_size);
1535 }
1536 }
1537
1538 ASSERTED int ret = os_munmap(base, pan_kmod_bo_size(mem->bo));
1539 assert(!ret);
1540 }
1541 } else {
1542 image->bo = NULL;
1543 image->pimage.data.offset = pBindInfos[i].memoryOffset;
1544 }
1545
1546 pan_kmod_bo_put(old_bo);
1547 }
1548
1549 return VK_SUCCESS;
1550 }
1551
1552 VkResult
panvk_CreateEvent(VkDevice _device,const VkEventCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkEvent * pEvent)1553 panvk_CreateEvent(VkDevice _device, const VkEventCreateInfo *pCreateInfo,
1554 const VkAllocationCallbacks *pAllocator, VkEvent *pEvent)
1555 {
1556 VK_FROM_HANDLE(panvk_device, device, _device);
1557 struct panvk_event *event = vk_object_zalloc(
1558 &device->vk, pAllocator, sizeof(*event), VK_OBJECT_TYPE_EVENT);
1559 if (!event)
1560 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1561
1562 struct drm_syncobj_create create = {
1563 .flags = 0,
1564 };
1565
1566 int ret = drmIoctl(device->vk.drm_fd, DRM_IOCTL_SYNCOBJ_CREATE, &create);
1567 if (ret)
1568 return VK_ERROR_OUT_OF_HOST_MEMORY;
1569
1570 event->syncobj = create.handle;
1571 *pEvent = panvk_event_to_handle(event);
1572
1573 return VK_SUCCESS;
1574 }
1575
1576 void
panvk_DestroyEvent(VkDevice _device,VkEvent _event,const VkAllocationCallbacks * pAllocator)1577 panvk_DestroyEvent(VkDevice _device, VkEvent _event,
1578 const VkAllocationCallbacks *pAllocator)
1579 {
1580 VK_FROM_HANDLE(panvk_device, device, _device);
1581 VK_FROM_HANDLE(panvk_event, event, _event);
1582
1583 if (!event)
1584 return;
1585
1586 struct drm_syncobj_destroy destroy = {.handle = event->syncobj};
1587 drmIoctl(device->vk.drm_fd, DRM_IOCTL_SYNCOBJ_DESTROY, &destroy);
1588
1589 vk_object_free(&device->vk, pAllocator, event);
1590 }
1591
1592 VkResult
panvk_GetEventStatus(VkDevice _device,VkEvent _event)1593 panvk_GetEventStatus(VkDevice _device, VkEvent _event)
1594 {
1595 VK_FROM_HANDLE(panvk_device, device, _device);
1596 VK_FROM_HANDLE(panvk_event, event, _event);
1597 bool signaled;
1598
1599 struct drm_syncobj_wait wait = {
1600 .handles = (uintptr_t)&event->syncobj,
1601 .count_handles = 1,
1602 .timeout_nsec = 0,
1603 .flags = DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT,
1604 };
1605
1606 int ret = drmIoctl(device->vk.drm_fd, DRM_IOCTL_SYNCOBJ_WAIT, &wait);
1607 if (ret) {
1608 if (errno == ETIME)
1609 signaled = false;
1610 else {
1611 assert(0);
1612 return VK_ERROR_DEVICE_LOST; /* TODO */
1613 }
1614 } else
1615 signaled = true;
1616
1617 return signaled ? VK_EVENT_SET : VK_EVENT_RESET;
1618 }
1619
1620 VkResult
panvk_SetEvent(VkDevice _device,VkEvent _event)1621 panvk_SetEvent(VkDevice _device, VkEvent _event)
1622 {
1623 VK_FROM_HANDLE(panvk_device, device, _device);
1624 VK_FROM_HANDLE(panvk_event, event, _event);
1625
1626 struct drm_syncobj_array objs = {
1627 .handles = (uint64_t)(uintptr_t)&event->syncobj,
1628 .count_handles = 1};
1629
1630 /* This is going to just replace the fence for this syncobj with one that
1631 * is already in signaled state. This won't be a problem because the spec
1632 * mandates that the event will have been set before the vkCmdWaitEvents
1633 * command executes.
1634 * https://www.khronos.org/registry/vulkan/specs/1.2/html/chap6.html#commandbuffers-submission-progress
1635 */
1636 if (drmIoctl(device->vk.drm_fd, DRM_IOCTL_SYNCOBJ_SIGNAL, &objs))
1637 return VK_ERROR_DEVICE_LOST;
1638
1639 return VK_SUCCESS;
1640 }
1641
1642 VkResult
panvk_ResetEvent(VkDevice _device,VkEvent _event)1643 panvk_ResetEvent(VkDevice _device, VkEvent _event)
1644 {
1645 VK_FROM_HANDLE(panvk_device, device, _device);
1646 VK_FROM_HANDLE(panvk_event, event, _event);
1647
1648 struct drm_syncobj_array objs = {
1649 .handles = (uint64_t)(uintptr_t)&event->syncobj,
1650 .count_handles = 1};
1651
1652 if (drmIoctl(device->vk.drm_fd, DRM_IOCTL_SYNCOBJ_RESET, &objs))
1653 return VK_ERROR_DEVICE_LOST;
1654
1655 return VK_SUCCESS;
1656 }
1657
1658 VkResult
panvk_CreateBuffer(VkDevice _device,const VkBufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBuffer * pBuffer)1659 panvk_CreateBuffer(VkDevice _device, const VkBufferCreateInfo *pCreateInfo,
1660 const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer)
1661 {
1662 VK_FROM_HANDLE(panvk_device, device, _device);
1663 struct panvk_buffer *buffer;
1664
1665 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
1666
1667 buffer =
1668 vk_buffer_create(&device->vk, pCreateInfo, pAllocator, sizeof(*buffer));
1669 if (buffer == NULL)
1670 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1671
1672 *pBuffer = panvk_buffer_to_handle(buffer);
1673
1674 return VK_SUCCESS;
1675 }
1676
1677 void
panvk_DestroyBuffer(VkDevice _device,VkBuffer _buffer,const VkAllocationCallbacks * pAllocator)1678 panvk_DestroyBuffer(VkDevice _device, VkBuffer _buffer,
1679 const VkAllocationCallbacks *pAllocator)
1680 {
1681 VK_FROM_HANDLE(panvk_device, device, _device);
1682 VK_FROM_HANDLE(panvk_buffer, buffer, _buffer);
1683
1684 if (!buffer)
1685 return;
1686
1687 if (buffer->host_ptr) {
1688 VkDeviceSize pgsize = getpagesize();
1689 uintptr_t map_start = (uintptr_t)buffer->host_ptr & ~(pgsize - 1);
1690 uintptr_t map_end =
1691 ALIGN_POT((uintptr_t)buffer->host_ptr + buffer->vk.size, pgsize);
1692 ASSERTED int ret = os_munmap((void *)map_start, map_end - map_start);
1693
1694 assert(!ret);
1695 buffer->host_ptr = NULL;
1696 }
1697
1698 pan_kmod_bo_put(buffer->bo);
1699 vk_buffer_destroy(&device->vk, pAllocator, &buffer->vk);
1700 }
1701
1702 VkResult
panvk_CreateFramebuffer(VkDevice _device,const VkFramebufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkFramebuffer * pFramebuffer)1703 panvk_CreateFramebuffer(VkDevice _device,
1704 const VkFramebufferCreateInfo *pCreateInfo,
1705 const VkAllocationCallbacks *pAllocator,
1706 VkFramebuffer *pFramebuffer)
1707 {
1708 VK_FROM_HANDLE(panvk_device, device, _device);
1709 struct panvk_framebuffer *framebuffer;
1710
1711 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
1712
1713 size_t size = sizeof(*framebuffer) + sizeof(struct panvk_attachment_info) *
1714 pCreateInfo->attachmentCount;
1715 framebuffer = vk_object_alloc(&device->vk, pAllocator, size,
1716 VK_OBJECT_TYPE_FRAMEBUFFER);
1717 if (framebuffer == NULL)
1718 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1719
1720 framebuffer->attachment_count = pCreateInfo->attachmentCount;
1721 framebuffer->width = pCreateInfo->width;
1722 framebuffer->height = pCreateInfo->height;
1723 framebuffer->layers = pCreateInfo->layers;
1724 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
1725 VkImageView _iview = pCreateInfo->pAttachments[i];
1726 struct panvk_image_view *iview = panvk_image_view_from_handle(_iview);
1727 framebuffer->attachments[i].iview = iview;
1728 }
1729
1730 *pFramebuffer = panvk_framebuffer_to_handle(framebuffer);
1731 return VK_SUCCESS;
1732 }
1733
1734 void
panvk_DestroyFramebuffer(VkDevice _device,VkFramebuffer _fb,const VkAllocationCallbacks * pAllocator)1735 panvk_DestroyFramebuffer(VkDevice _device, VkFramebuffer _fb,
1736 const VkAllocationCallbacks *pAllocator)
1737 {
1738 VK_FROM_HANDLE(panvk_device, device, _device);
1739 VK_FROM_HANDLE(panvk_framebuffer, fb, _fb);
1740
1741 if (fb)
1742 vk_object_free(&device->vk, pAllocator, fb);
1743 }
1744
1745 void
panvk_DestroySampler(VkDevice _device,VkSampler _sampler,const VkAllocationCallbacks * pAllocator)1746 panvk_DestroySampler(VkDevice _device, VkSampler _sampler,
1747 const VkAllocationCallbacks *pAllocator)
1748 {
1749 VK_FROM_HANDLE(panvk_device, device, _device);
1750 VK_FROM_HANDLE(panvk_sampler, sampler, _sampler);
1751
1752 if (!sampler)
1753 return;
1754
1755 vk_object_free(&device->vk, pAllocator, sampler);
1756 }
1757
1758 VkResult
panvk_GetMemoryFdKHR(VkDevice _device,const VkMemoryGetFdInfoKHR * pGetFdInfo,int * pFd)1759 panvk_GetMemoryFdKHR(VkDevice _device, const VkMemoryGetFdInfoKHR *pGetFdInfo,
1760 int *pFd)
1761 {
1762 VK_FROM_HANDLE(panvk_device, device, _device);
1763 VK_FROM_HANDLE(panvk_device_memory, memory, pGetFdInfo->memory);
1764
1765 assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
1766
1767 /* At the moment, we support only the below handle types. */
1768 assert(
1769 pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
1770 pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
1771
1772 int prime_fd = pan_kmod_bo_export(memory->bo);
1773 if (prime_fd < 0)
1774 return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1775
1776 *pFd = prime_fd;
1777 return VK_SUCCESS;
1778 }
1779
1780 VkResult
panvk_GetMemoryFdPropertiesKHR(VkDevice _device,VkExternalMemoryHandleTypeFlagBits handleType,int fd,VkMemoryFdPropertiesKHR * pMemoryFdProperties)1781 panvk_GetMemoryFdPropertiesKHR(VkDevice _device,
1782 VkExternalMemoryHandleTypeFlagBits handleType,
1783 int fd,
1784 VkMemoryFdPropertiesKHR *pMemoryFdProperties)
1785 {
1786 assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
1787 pMemoryFdProperties->memoryTypeBits = 1;
1788 return VK_SUCCESS;
1789 }
1790
1791 void
panvk_GetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalSemaphoreInfo * pExternalSemaphoreInfo,VkExternalSemaphoreProperties * pExternalSemaphoreProperties)1792 panvk_GetPhysicalDeviceExternalSemaphoreProperties(
1793 VkPhysicalDevice physicalDevice,
1794 const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo,
1795 VkExternalSemaphoreProperties *pExternalSemaphoreProperties)
1796 {
1797 if ((pExternalSemaphoreInfo->handleType ==
1798 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT ||
1799 pExternalSemaphoreInfo->handleType ==
1800 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) {
1801 pExternalSemaphoreProperties->exportFromImportedHandleTypes =
1802 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT |
1803 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
1804 pExternalSemaphoreProperties->compatibleHandleTypes =
1805 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT |
1806 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
1807 pExternalSemaphoreProperties->externalSemaphoreFeatures =
1808 VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |
1809 VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT;
1810 } else {
1811 pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
1812 pExternalSemaphoreProperties->compatibleHandleTypes = 0;
1813 pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
1814 }
1815 }
1816
1817 void
panvk_GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalFenceInfo * pExternalFenceInfo,VkExternalFenceProperties * pExternalFenceProperties)1818 panvk_GetPhysicalDeviceExternalFenceProperties(
1819 VkPhysicalDevice physicalDevice,
1820 const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
1821 VkExternalFenceProperties *pExternalFenceProperties)
1822 {
1823 pExternalFenceProperties->exportFromImportedHandleTypes = 0;
1824 pExternalFenceProperties->compatibleHandleTypes = 0;
1825 pExternalFenceProperties->externalFenceFeatures = 0;
1826 }
1827