9f2881724cfc8b600a9a89bbeeb645a4f915217e
[mesa.git] / src / freedreno / vulkan / tu_device.c
1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 *
5 * based in part on anv driver which is:
6 * Copyright © 2015 Intel Corporation
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 * DEALINGS IN THE SOFTWARE.
26 */
27
28 #include "tu_private.h"
29
30 #include <fcntl.h>
31 #include <libsync.h>
32 #include <stdbool.h>
33 #include <string.h>
34 #include <sys/mman.h>
35 #include <sys/sysinfo.h>
36 #include <unistd.h>
37 #include <xf86drm.h>
38
39 #include "compiler/glsl_types.h"
40 #include "util/debug.h"
41 #include "util/disk_cache.h"
42 #include "util/u_atomic.h"
43 #include "vk_format.h"
44 #include "vk_util.h"
45
46 #include "drm-uapi/msm_drm.h"
47
48 /* for fd_get_driver/device_uuid() */
49 #include "freedreno/common/freedreno_uuid.h"
50
51 static void
52 tu_semaphore_remove_temp(struct tu_device *device,
53 struct tu_semaphore *sem);
54
55 static int
56 tu_device_get_cache_uuid(uint16_t family, void *uuid)
57 {
58 uint32_t mesa_timestamp;
59 uint16_t f = family;
60 memset(uuid, 0, VK_UUID_SIZE);
61 if (!disk_cache_get_function_timestamp(tu_device_get_cache_uuid,
62 &mesa_timestamp))
63 return -1;
64
65 memcpy(uuid, &mesa_timestamp, 4);
66 memcpy((char *) uuid + 4, &f, 2);
67 snprintf((char *) uuid + 6, VK_UUID_SIZE - 10, "tu");
68 return 0;
69 }
70
71 static VkResult
72 tu_bo_init(struct tu_device *dev,
73 struct tu_bo *bo,
74 uint32_t gem_handle,
75 uint64_t size)
76 {
77 uint64_t iova = tu_gem_info_iova(dev, gem_handle);
78 if (!iova)
79 return VK_ERROR_OUT_OF_DEVICE_MEMORY;
80
81 *bo = (struct tu_bo) {
82 .gem_handle = gem_handle,
83 .size = size,
84 .iova = iova,
85 };
86
87 return VK_SUCCESS;
88 }
89
90 VkResult
91 tu_bo_init_new(struct tu_device *dev, struct tu_bo *bo, uint64_t size)
92 {
93 /* TODO: Choose better flags. As of 2018-11-12, freedreno/drm/msm_bo.c
94 * always sets `flags = MSM_BO_WC`, and we copy that behavior here.
95 */
96 uint32_t gem_handle = tu_gem_new(dev, size, MSM_BO_WC);
97 if (!gem_handle)
98 return vk_error(dev->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
99
100 VkResult result = tu_bo_init(dev, bo, gem_handle, size);
101 if (result != VK_SUCCESS) {
102 tu_gem_close(dev, gem_handle);
103 return vk_error(dev->instance, result);
104 }
105
106 return VK_SUCCESS;
107 }
108
109 VkResult
110 tu_bo_init_dmabuf(struct tu_device *dev,
111 struct tu_bo *bo,
112 uint64_t size,
113 int fd)
114 {
115 uint32_t gem_handle = tu_gem_import_dmabuf(dev, fd, size);
116 if (!gem_handle)
117 return vk_error(dev->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
118
119 VkResult result = tu_bo_init(dev, bo, gem_handle, size);
120 if (result != VK_SUCCESS) {
121 tu_gem_close(dev, gem_handle);
122 return vk_error(dev->instance, result);
123 }
124
125 return VK_SUCCESS;
126 }
127
128 int
129 tu_bo_export_dmabuf(struct tu_device *dev, struct tu_bo *bo)
130 {
131 return tu_gem_export_dmabuf(dev, bo->gem_handle);
132 }
133
134 VkResult
135 tu_bo_map(struct tu_device *dev, struct tu_bo *bo)
136 {
137 if (bo->map)
138 return VK_SUCCESS;
139
140 uint64_t offset = tu_gem_info_offset(dev, bo->gem_handle);
141 if (!offset)
142 return vk_error(dev->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
143
144 /* TODO: Should we use the wrapper os_mmap() like Freedreno does? */
145 void *map = mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
146 dev->physical_device->local_fd, offset);
147 if (map == MAP_FAILED)
148 return vk_error(dev->instance, VK_ERROR_MEMORY_MAP_FAILED);
149
150 bo->map = map;
151 return VK_SUCCESS;
152 }
153
154 void
155 tu_bo_finish(struct tu_device *dev, struct tu_bo *bo)
156 {
157 assert(bo->gem_handle);
158
159 if (bo->map)
160 munmap(bo->map, bo->size);
161
162 tu_gem_close(dev, bo->gem_handle);
163 }
164
165 VkResult
166 tu_physical_device_init(struct tu_physical_device *device,
167 struct tu_instance *instance)
168 {
169 VkResult result = VK_SUCCESS;
170
171 memset(device->name, 0, sizeof(device->name));
172 sprintf(device->name, "FD%d", device->gpu_id);
173
174 device->limited_z24s8 = (device->gpu_id == 630);
175
176 switch (device->gpu_id) {
177 case 618:
178 device->ccu_offset_gmem = 0x7c000; /* 0x7e000 in some cases? */
179 device->ccu_offset_bypass = 0x10000;
180 device->tile_align_w = 32;
181 device->magic.PC_UNKNOWN_9805 = 0x0;
182 device->magic.SP_UNKNOWN_A0F8 = 0x0;
183 break;
184 case 630:
185 case 640:
186 device->ccu_offset_gmem = 0xf8000;
187 device->ccu_offset_bypass = 0x20000;
188 device->tile_align_w = 32;
189 device->magic.PC_UNKNOWN_9805 = 0x1;
190 device->magic.SP_UNKNOWN_A0F8 = 0x1;
191 break;
192 case 650:
193 device->ccu_offset_gmem = 0x114000;
194 device->ccu_offset_bypass = 0x30000;
195 device->tile_align_w = 96;
196 device->magic.PC_UNKNOWN_9805 = 0x2;
197 device->magic.SP_UNKNOWN_A0F8 = 0x2;
198 break;
199 default:
200 result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
201 "device %s is unsupported", device->name);
202 goto fail;
203 }
204 if (tu_device_get_cache_uuid(device->gpu_id, device->cache_uuid)) {
205 result = vk_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
206 "cannot generate UUID");
207 goto fail;
208 }
209
210 /* The gpu id is already embedded in the uuid so we just pass "tu"
211 * when creating the cache.
212 */
213 char buf[VK_UUID_SIZE * 2 + 1];
214 disk_cache_format_hex_id(buf, device->cache_uuid, VK_UUID_SIZE * 2);
215 device->disk_cache = disk_cache_create(device->name, buf, 0);
216
217 fprintf(stderr, "WARNING: tu is not a conformant vulkan implementation, "
218 "testing use only.\n");
219
220 fd_get_driver_uuid(device->driver_uuid);
221 fd_get_device_uuid(device->device_uuid, device->gpu_id);
222
223 tu_physical_device_get_supported_extensions(device, &device->supported_extensions);
224
225 if (result != VK_SUCCESS) {
226 vk_error(instance, result);
227 goto fail;
228 }
229
230 result = tu_wsi_init(device);
231 if (result != VK_SUCCESS) {
232 vk_error(instance, result);
233 goto fail;
234 }
235
236 return VK_SUCCESS;
237
238 fail:
239 close(device->local_fd);
240 if (device->master_fd != -1)
241 close(device->master_fd);
242 return result;
243 }
244
245 static void
246 tu_physical_device_finish(struct tu_physical_device *device)
247 {
248 tu_wsi_finish(device);
249
250 disk_cache_destroy(device->disk_cache);
251 close(device->local_fd);
252 if (device->master_fd != -1)
253 close(device->master_fd);
254
255 vk_object_base_finish(&device->base);
256 }
257
258 static VKAPI_ATTR void *
259 default_alloc_func(void *pUserData,
260 size_t size,
261 size_t align,
262 VkSystemAllocationScope allocationScope)
263 {
264 return malloc(size);
265 }
266
267 static VKAPI_ATTR void *
268 default_realloc_func(void *pUserData,
269 void *pOriginal,
270 size_t size,
271 size_t align,
272 VkSystemAllocationScope allocationScope)
273 {
274 return realloc(pOriginal, size);
275 }
276
277 static VKAPI_ATTR void
278 default_free_func(void *pUserData, void *pMemory)
279 {
280 free(pMemory);
281 }
282
283 static const VkAllocationCallbacks default_alloc = {
284 .pUserData = NULL,
285 .pfnAllocation = default_alloc_func,
286 .pfnReallocation = default_realloc_func,
287 .pfnFree = default_free_func,
288 };
289
290 static const struct debug_control tu_debug_options[] = {
291 { "startup", TU_DEBUG_STARTUP },
292 { "nir", TU_DEBUG_NIR },
293 { "ir3", TU_DEBUG_IR3 },
294 { "nobin", TU_DEBUG_NOBIN },
295 { "sysmem", TU_DEBUG_SYSMEM },
296 { "forcebin", TU_DEBUG_FORCEBIN },
297 { "noubwc", TU_DEBUG_NOUBWC },
298 { NULL, 0 }
299 };
300
301 const char *
302 tu_get_debug_option_name(int id)
303 {
304 assert(id < ARRAY_SIZE(tu_debug_options) - 1);
305 return tu_debug_options[id].string;
306 }
307
308 static int
309 tu_get_instance_extension_index(const char *name)
310 {
311 for (unsigned i = 0; i < TU_INSTANCE_EXTENSION_COUNT; ++i) {
312 if (strcmp(name, tu_instance_extensions[i].extensionName) == 0)
313 return i;
314 }
315 return -1;
316 }
317
318 VkResult
319 tu_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
320 const VkAllocationCallbacks *pAllocator,
321 VkInstance *pInstance)
322 {
323 struct tu_instance *instance;
324 VkResult result;
325
326 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
327
328 uint32_t client_version;
329 if (pCreateInfo->pApplicationInfo &&
330 pCreateInfo->pApplicationInfo->apiVersion != 0) {
331 client_version = pCreateInfo->pApplicationInfo->apiVersion;
332 } else {
333 tu_EnumerateInstanceVersion(&client_version);
334 }
335
336 instance = vk_zalloc2(&default_alloc, pAllocator, sizeof(*instance), 8,
337 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
338
339 if (!instance)
340 return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
341
342 vk_object_base_init(NULL, &instance->base, VK_OBJECT_TYPE_INSTANCE);
343
344 if (pAllocator)
345 instance->alloc = *pAllocator;
346 else
347 instance->alloc = default_alloc;
348
349 instance->api_version = client_version;
350 instance->physical_device_count = -1;
351
352 instance->debug_flags =
353 parse_debug_string(getenv("TU_DEBUG"), tu_debug_options);
354
355 if (instance->debug_flags & TU_DEBUG_STARTUP)
356 tu_logi("Created an instance");
357
358 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
359 const char *ext_name = pCreateInfo->ppEnabledExtensionNames[i];
360 int index = tu_get_instance_extension_index(ext_name);
361
362 if (index < 0 || !tu_instance_extensions_supported.extensions[index]) {
363 vk_object_base_finish(&instance->base);
364 vk_free2(&default_alloc, pAllocator, instance);
365 return vk_error(instance, VK_ERROR_EXTENSION_NOT_PRESENT);
366 }
367
368 instance->enabled_extensions.extensions[index] = true;
369 }
370
371 result = vk_debug_report_instance_init(&instance->debug_report_callbacks);
372 if (result != VK_SUCCESS) {
373 vk_object_base_finish(&instance->base);
374 vk_free2(&default_alloc, pAllocator, instance);
375 return vk_error(instance, result);
376 }
377
378 glsl_type_singleton_init_or_ref();
379
380 VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
381
382 *pInstance = tu_instance_to_handle(instance);
383
384 return VK_SUCCESS;
385 }
386
387 void
388 tu_DestroyInstance(VkInstance _instance,
389 const VkAllocationCallbacks *pAllocator)
390 {
391 TU_FROM_HANDLE(tu_instance, instance, _instance);
392
393 if (!instance)
394 return;
395
396 for (int i = 0; i < instance->physical_device_count; ++i) {
397 tu_physical_device_finish(instance->physical_devices + i);
398 }
399
400 VG(VALGRIND_DESTROY_MEMPOOL(instance));
401
402 glsl_type_singleton_decref();
403
404 vk_debug_report_instance_destroy(&instance->debug_report_callbacks);
405
406 vk_object_base_finish(&instance->base);
407 vk_free(&instance->alloc, instance);
408 }
409
410 VkResult
411 tu_EnumeratePhysicalDevices(VkInstance _instance,
412 uint32_t *pPhysicalDeviceCount,
413 VkPhysicalDevice *pPhysicalDevices)
414 {
415 TU_FROM_HANDLE(tu_instance, instance, _instance);
416 VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
417
418 VkResult result;
419
420 if (instance->physical_device_count < 0) {
421 result = tu_enumerate_devices(instance);
422 if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)
423 return result;
424 }
425
426 for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
427 vk_outarray_append(&out, p)
428 {
429 *p = tu_physical_device_to_handle(instance->physical_devices + i);
430 }
431 }
432
433 return vk_outarray_status(&out);
434 }
435
436 VkResult
437 tu_EnumeratePhysicalDeviceGroups(
438 VkInstance _instance,
439 uint32_t *pPhysicalDeviceGroupCount,
440 VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties)
441 {
442 TU_FROM_HANDLE(tu_instance, instance, _instance);
443 VK_OUTARRAY_MAKE(out, pPhysicalDeviceGroupProperties,
444 pPhysicalDeviceGroupCount);
445 VkResult result;
446
447 if (instance->physical_device_count < 0) {
448 result = tu_enumerate_devices(instance);
449 if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)
450 return result;
451 }
452
453 for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
454 vk_outarray_append(&out, p)
455 {
456 p->physicalDeviceCount = 1;
457 p->physicalDevices[0] =
458 tu_physical_device_to_handle(instance->physical_devices + i);
459 p->subsetAllocation = false;
460 }
461 }
462
463 return vk_outarray_status(&out);
464 }
465
466 void
467 tu_GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice,
468 VkPhysicalDeviceFeatures *pFeatures)
469 {
470 memset(pFeatures, 0, sizeof(*pFeatures));
471
472 *pFeatures = (VkPhysicalDeviceFeatures) {
473 .robustBufferAccess = true,
474 .fullDrawIndexUint32 = true,
475 .imageCubeArray = true,
476 .independentBlend = true,
477 .geometryShader = true,
478 .tessellationShader = true,
479 .sampleRateShading = true,
480 .dualSrcBlend = true,
481 .logicOp = true,
482 .multiDrawIndirect = true,
483 .drawIndirectFirstInstance = true,
484 .depthClamp = true,
485 .depthBiasClamp = true,
486 .fillModeNonSolid = true,
487 .depthBounds = true,
488 .wideLines = false,
489 .largePoints = true,
490 .alphaToOne = true,
491 .multiViewport = false,
492 .samplerAnisotropy = true,
493 .textureCompressionETC2 = true,
494 .textureCompressionASTC_LDR = true,
495 .textureCompressionBC = true,
496 .occlusionQueryPrecise = true,
497 .pipelineStatisticsQuery = false,
498 .vertexPipelineStoresAndAtomics = true,
499 .fragmentStoresAndAtomics = true,
500 .shaderTessellationAndGeometryPointSize = false,
501 .shaderImageGatherExtended = false,
502 .shaderStorageImageExtendedFormats = false,
503 .shaderStorageImageMultisample = false,
504 .shaderUniformBufferArrayDynamicIndexing = true,
505 .shaderSampledImageArrayDynamicIndexing = true,
506 .shaderStorageBufferArrayDynamicIndexing = true,
507 .shaderStorageImageArrayDynamicIndexing = true,
508 .shaderStorageImageReadWithoutFormat = false,
509 .shaderStorageImageWriteWithoutFormat = false,
510 .shaderClipDistance = false,
511 .shaderCullDistance = false,
512 .shaderFloat64 = false,
513 .shaderInt64 = false,
514 .shaderInt16 = false,
515 .sparseBinding = false,
516 .variableMultisampleRate = false,
517 .inheritedQueries = false,
518 };
519 }
520
521 void
522 tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
523 VkPhysicalDeviceFeatures2 *pFeatures)
524 {
525 vk_foreach_struct(ext, pFeatures->pNext)
526 {
527 switch (ext->sType) {
528 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES: {
529 VkPhysicalDeviceVulkan11Features *features = (void *) ext;
530 features->storageBuffer16BitAccess = false;
531 features->uniformAndStorageBuffer16BitAccess = false;
532 features->storagePushConstant16 = false;
533 features->storageInputOutput16 = false;
534 features->multiview = false;
535 features->multiviewGeometryShader = false;
536 features->multiviewTessellationShader = false;
537 features->variablePointersStorageBuffer = true;
538 features->variablePointers = true;
539 features->protectedMemory = false;
540 features->samplerYcbcrConversion = true;
541 features->shaderDrawParameters = true;
542 break;
543 }
544 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES: {
545 VkPhysicalDeviceVulkan12Features *features = (void *) ext;
546 features->samplerMirrorClampToEdge = true;
547 features->drawIndirectCount = true;
548 features->storageBuffer8BitAccess = false;
549 features->uniformAndStorageBuffer8BitAccess = false;
550 features->storagePushConstant8 = false;
551 features->shaderBufferInt64Atomics = false;
552 features->shaderSharedInt64Atomics = false;
553 features->shaderFloat16 = false;
554 features->shaderInt8 = false;
555
556 features->descriptorIndexing = false;
557 features->shaderInputAttachmentArrayDynamicIndexing = false;
558 features->shaderUniformTexelBufferArrayDynamicIndexing = false;
559 features->shaderStorageTexelBufferArrayDynamicIndexing = false;
560 features->shaderUniformBufferArrayNonUniformIndexing = false;
561 features->shaderSampledImageArrayNonUniformIndexing = false;
562 features->shaderStorageBufferArrayNonUniformIndexing = false;
563 features->shaderStorageImageArrayNonUniformIndexing = false;
564 features->shaderInputAttachmentArrayNonUniformIndexing = false;
565 features->shaderUniformTexelBufferArrayNonUniformIndexing = false;
566 features->shaderStorageTexelBufferArrayNonUniformIndexing = false;
567 features->descriptorBindingUniformBufferUpdateAfterBind = false;
568 features->descriptorBindingSampledImageUpdateAfterBind = false;
569 features->descriptorBindingStorageImageUpdateAfterBind = false;
570 features->descriptorBindingStorageBufferUpdateAfterBind = false;
571 features->descriptorBindingUniformTexelBufferUpdateAfterBind = false;
572 features->descriptorBindingStorageTexelBufferUpdateAfterBind = false;
573 features->descriptorBindingUpdateUnusedWhilePending = false;
574 features->descriptorBindingPartiallyBound = false;
575 features->descriptorBindingVariableDescriptorCount = false;
576 features->runtimeDescriptorArray = false;
577
578 features->samplerFilterMinmax = true;
579 features->scalarBlockLayout = false;
580 features->imagelessFramebuffer = false;
581 features->uniformBufferStandardLayout = false;
582 features->shaderSubgroupExtendedTypes = false;
583 features->separateDepthStencilLayouts = false;
584 features->hostQueryReset = false;
585 features->timelineSemaphore = false;
586 features->bufferDeviceAddress = false;
587 features->bufferDeviceAddressCaptureReplay = false;
588 features->bufferDeviceAddressMultiDevice = false;
589 features->vulkanMemoryModel = false;
590 features->vulkanMemoryModelDeviceScope = false;
591 features->vulkanMemoryModelAvailabilityVisibilityChains = false;
592 features->shaderOutputViewportIndex = false;
593 features->shaderOutputLayer = false;
594 features->subgroupBroadcastDynamicId = false;
595 break;
596 }
597 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTERS_FEATURES: {
598 VkPhysicalDeviceVariablePointersFeatures *features = (void *) ext;
599 features->variablePointersStorageBuffer = true;
600 features->variablePointers = true;
601 break;
602 }
603 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES: {
604 VkPhysicalDeviceMultiviewFeatures *features =
605 (VkPhysicalDeviceMultiviewFeatures *) ext;
606 features->multiview = false;
607 features->multiviewGeometryShader = false;
608 features->multiviewTessellationShader = false;
609 break;
610 }
611 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DRAW_PARAMETERS_FEATURES: {
612 VkPhysicalDeviceShaderDrawParametersFeatures *features =
613 (VkPhysicalDeviceShaderDrawParametersFeatures *) ext;
614 features->shaderDrawParameters = true;
615 break;
616 }
617 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES: {
618 VkPhysicalDeviceProtectedMemoryFeatures *features =
619 (VkPhysicalDeviceProtectedMemoryFeatures *) ext;
620 features->protectedMemory = false;
621 break;
622 }
623 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
624 VkPhysicalDevice16BitStorageFeatures *features =
625 (VkPhysicalDevice16BitStorageFeatures *) ext;
626 features->storageBuffer16BitAccess = false;
627 features->uniformAndStorageBuffer16BitAccess = false;
628 features->storagePushConstant16 = false;
629 features->storageInputOutput16 = false;
630 break;
631 }
632 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES: {
633 VkPhysicalDeviceSamplerYcbcrConversionFeatures *features =
634 (VkPhysicalDeviceSamplerYcbcrConversionFeatures *) ext;
635 features->samplerYcbcrConversion = true;
636 break;
637 }
638 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT: {
639 VkPhysicalDeviceDescriptorIndexingFeaturesEXT *features =
640 (VkPhysicalDeviceDescriptorIndexingFeaturesEXT *) ext;
641 features->shaderInputAttachmentArrayDynamicIndexing = false;
642 features->shaderUniformTexelBufferArrayDynamicIndexing = false;
643 features->shaderStorageTexelBufferArrayDynamicIndexing = false;
644 features->shaderUniformBufferArrayNonUniformIndexing = false;
645 features->shaderSampledImageArrayNonUniformIndexing = false;
646 features->shaderStorageBufferArrayNonUniformIndexing = false;
647 features->shaderStorageImageArrayNonUniformIndexing = false;
648 features->shaderInputAttachmentArrayNonUniformIndexing = false;
649 features->shaderUniformTexelBufferArrayNonUniformIndexing = false;
650 features->shaderStorageTexelBufferArrayNonUniformIndexing = false;
651 features->descriptorBindingUniformBufferUpdateAfterBind = false;
652 features->descriptorBindingSampledImageUpdateAfterBind = false;
653 features->descriptorBindingStorageImageUpdateAfterBind = false;
654 features->descriptorBindingStorageBufferUpdateAfterBind = false;
655 features->descriptorBindingUniformTexelBufferUpdateAfterBind = false;
656 features->descriptorBindingStorageTexelBufferUpdateAfterBind = false;
657 features->descriptorBindingUpdateUnusedWhilePending = false;
658 features->descriptorBindingPartiallyBound = false;
659 features->descriptorBindingVariableDescriptorCount = false;
660 features->runtimeDescriptorArray = false;
661 break;
662 }
663 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {
664 VkPhysicalDeviceConditionalRenderingFeaturesEXT *features =
665 (VkPhysicalDeviceConditionalRenderingFeaturesEXT *) ext;
666 features->conditionalRendering = true;
667 features->inheritedConditionalRendering = true;
668 break;
669 }
670 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {
671 VkPhysicalDeviceTransformFeedbackFeaturesEXT *features =
672 (VkPhysicalDeviceTransformFeedbackFeaturesEXT *) ext;
673 features->transformFeedback = true;
674 features->geometryStreams = false;
675 break;
676 }
677 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {
678 VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features =
679 (VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext;
680 features->indexTypeUint8 = true;
681 break;
682 }
683 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
684 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features =
685 (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext;
686 features->vertexAttributeInstanceRateDivisor = true;
687 features->vertexAttributeInstanceRateZeroDivisor = true;
688 break;
689 }
690 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: {
691 VkPhysicalDevicePrivateDataFeaturesEXT *features =
692 (VkPhysicalDevicePrivateDataFeaturesEXT *)ext;
693 features->privateData = true;
694 break;
695 }
696 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: {
697 VkPhysicalDeviceDepthClipEnableFeaturesEXT *features =
698 (VkPhysicalDeviceDepthClipEnableFeaturesEXT *)ext;
699 features->depthClipEnable = true;
700 break;
701 }
702 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {
703 VkPhysicalDevice4444FormatsFeaturesEXT *features = (void *)ext;
704 features->formatA4R4G4B4 = true;
705 features->formatA4B4G4R4 = true;
706 break;
707 }
708 default:
709 break;
710 }
711 }
712 return tu_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features);
713 }
714
715 void
716 tu_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
717 VkPhysicalDeviceProperties *pProperties)
718 {
719 TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
720 VkSampleCountFlags sample_counts =
721 VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;
722
723 /* I have no idea what the maximum size is, but the hardware supports very
724 * large numbers of descriptors (at least 2^16). This limit is based on
725 * CP_LOAD_STATE6, which has a 28-bit field for the DWORD offset, so that
726 * we don't have to think about what to do if that overflows, but really
727 * nothing is likely to get close to this.
728 */
729 const size_t max_descriptor_set_size = (1 << 28) / A6XX_TEX_CONST_DWORDS;
730
731 VkPhysicalDeviceLimits limits = {
732 .maxImageDimension1D = (1 << 14),
733 .maxImageDimension2D = (1 << 14),
734 .maxImageDimension3D = (1 << 11),
735 .maxImageDimensionCube = (1 << 14),
736 .maxImageArrayLayers = (1 << 11),
737 .maxTexelBufferElements = 128 * 1024 * 1024,
738 .maxUniformBufferRange = MAX_UNIFORM_BUFFER_RANGE,
739 .maxStorageBufferRange = MAX_STORAGE_BUFFER_RANGE,
740 .maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,
741 .maxMemoryAllocationCount = UINT32_MAX,
742 .maxSamplerAllocationCount = 64 * 1024,
743 .bufferImageGranularity = 64, /* A cache line */
744 .sparseAddressSpaceSize = 0xffffffffu, /* buffer max size */
745 .maxBoundDescriptorSets = MAX_SETS,
746 .maxPerStageDescriptorSamplers = max_descriptor_set_size,
747 .maxPerStageDescriptorUniformBuffers = max_descriptor_set_size,
748 .maxPerStageDescriptorStorageBuffers = max_descriptor_set_size,
749 .maxPerStageDescriptorSampledImages = max_descriptor_set_size,
750 .maxPerStageDescriptorStorageImages = max_descriptor_set_size,
751 .maxPerStageDescriptorInputAttachments = MAX_RTS,
752 .maxPerStageResources = max_descriptor_set_size,
753 .maxDescriptorSetSamplers = max_descriptor_set_size,
754 .maxDescriptorSetUniformBuffers = max_descriptor_set_size,
755 .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS,
756 .maxDescriptorSetStorageBuffers = max_descriptor_set_size,
757 .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS,
758 .maxDescriptorSetSampledImages = max_descriptor_set_size,
759 .maxDescriptorSetStorageImages = max_descriptor_set_size,
760 .maxDescriptorSetInputAttachments = MAX_RTS,
761 .maxVertexInputAttributes = 32,
762 .maxVertexInputBindings = 32,
763 .maxVertexInputAttributeOffset = 4095,
764 .maxVertexInputBindingStride = 2048,
765 .maxVertexOutputComponents = 128,
766 .maxTessellationGenerationLevel = 64,
767 .maxTessellationPatchSize = 32,
768 .maxTessellationControlPerVertexInputComponents = 128,
769 .maxTessellationControlPerVertexOutputComponents = 128,
770 .maxTessellationControlPerPatchOutputComponents = 120,
771 .maxTessellationControlTotalOutputComponents = 4096,
772 .maxTessellationEvaluationInputComponents = 128,
773 .maxTessellationEvaluationOutputComponents = 128,
774 .maxGeometryShaderInvocations = 32,
775 .maxGeometryInputComponents = 64,
776 .maxGeometryOutputComponents = 128,
777 .maxGeometryOutputVertices = 256,
778 .maxGeometryTotalOutputComponents = 1024,
779 .maxFragmentInputComponents = 124,
780 .maxFragmentOutputAttachments = 8,
781 .maxFragmentDualSrcAttachments = 1,
782 .maxFragmentCombinedOutputResources = 8,
783 .maxComputeSharedMemorySize = 32768,
784 .maxComputeWorkGroupCount = { 65535, 65535, 65535 },
785 .maxComputeWorkGroupInvocations = 2048,
786 .maxComputeWorkGroupSize = { 2048, 2048, 2048 },
787 .subPixelPrecisionBits = 8,
788 .subTexelPrecisionBits = 8,
789 .mipmapPrecisionBits = 8,
790 .maxDrawIndexedIndexValue = UINT32_MAX,
791 .maxDrawIndirectCount = UINT32_MAX,
792 .maxSamplerLodBias = 4095.0 / 256.0, /* [-16, 15.99609375] */
793 .maxSamplerAnisotropy = 16,
794 .maxViewports = MAX_VIEWPORTS,
795 .maxViewportDimensions = { (1 << 14), (1 << 14) },
796 .viewportBoundsRange = { INT16_MIN, INT16_MAX },
797 .viewportSubPixelBits = 8,
798 .minMemoryMapAlignment = 4096, /* A page */
799 .minTexelBufferOffsetAlignment = 64,
800 .minUniformBufferOffsetAlignment = 64,
801 .minStorageBufferOffsetAlignment = 64,
802 .minTexelOffset = -16,
803 .maxTexelOffset = 15,
804 .minTexelGatherOffset = -32,
805 .maxTexelGatherOffset = 31,
806 .minInterpolationOffset = -0.5,
807 .maxInterpolationOffset = 0.4375,
808 .subPixelInterpolationOffsetBits = 4,
809 .maxFramebufferWidth = (1 << 14),
810 .maxFramebufferHeight = (1 << 14),
811 .maxFramebufferLayers = (1 << 10),
812 .framebufferColorSampleCounts = sample_counts,
813 .framebufferDepthSampleCounts = sample_counts,
814 .framebufferStencilSampleCounts = sample_counts,
815 .framebufferNoAttachmentsSampleCounts = sample_counts,
816 .maxColorAttachments = MAX_RTS,
817 .sampledImageColorSampleCounts = sample_counts,
818 .sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT,
819 .sampledImageDepthSampleCounts = sample_counts,
820 .sampledImageStencilSampleCounts = sample_counts,
821 .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT,
822 .maxSampleMaskWords = 1,
823 .timestampComputeAndGraphics = true,
824 .timestampPeriod = 1000000000.0 / 19200000.0, /* CP_ALWAYS_ON_COUNTER is fixed 19.2MHz */
825 .maxClipDistances = 8,
826 .maxCullDistances = 8,
827 .maxCombinedClipAndCullDistances = 8,
828 .discreteQueuePriorities = 1,
829 .pointSizeRange = { 1, 4092 },
830 .lineWidthRange = { 0.0, 7.9921875 },
831 .pointSizeGranularity = 0.0625,
832 .lineWidthGranularity = (1.0 / 128.0),
833 .strictLines = false, /* FINISHME */
834 .standardSampleLocations = true,
835 .optimalBufferCopyOffsetAlignment = 128,
836 .optimalBufferCopyRowPitchAlignment = 128,
837 .nonCoherentAtomSize = 64,
838 };
839
840 *pProperties = (VkPhysicalDeviceProperties) {
841 .apiVersion = tu_physical_device_api_version(pdevice),
842 .driverVersion = vk_get_driver_version(),
843 .vendorID = 0, /* TODO */
844 .deviceID = 0,
845 .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
846 .limits = limits,
847 .sparseProperties = { 0 },
848 };
849
850 strcpy(pProperties->deviceName, pdevice->name);
851 memcpy(pProperties->pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);
852 }
853
854 void
855 tu_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
856 VkPhysicalDeviceProperties2 *pProperties)
857 {
858 TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
859 tu_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties);
860
861 vk_foreach_struct(ext, pProperties->pNext)
862 {
863 switch (ext->sType) {
864 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
865 VkPhysicalDevicePushDescriptorPropertiesKHR *properties =
866 (VkPhysicalDevicePushDescriptorPropertiesKHR *) ext;
867 properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
868 break;
869 }
870 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES: {
871 VkPhysicalDeviceIDProperties *properties =
872 (VkPhysicalDeviceIDProperties *) ext;
873 memcpy(properties->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
874 memcpy(properties->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
875 properties->deviceLUIDValid = false;
876 break;
877 }
878 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES: {
879 VkPhysicalDeviceMultiviewProperties *properties =
880 (VkPhysicalDeviceMultiviewProperties *) ext;
881 properties->maxMultiviewViewCount = MAX_VIEWS;
882 properties->maxMultiviewInstanceIndex = INT_MAX;
883 break;
884 }
885 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {
886 VkPhysicalDevicePointClippingProperties *properties =
887 (VkPhysicalDevicePointClippingProperties *) ext;
888 properties->pointClippingBehavior =
889 VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
890 break;
891 }
892 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
893 VkPhysicalDeviceMaintenance3Properties *properties =
894 (VkPhysicalDeviceMaintenance3Properties *) ext;
895 /* Make sure everything is addressable by a signed 32-bit int, and
896 * our largest descriptors are 96 bytes. */
897 properties->maxPerSetDescriptors = (1ull << 31) / 96;
898 /* Our buffer size fields allow only this much */
899 properties->maxMemoryAllocationSize = 0xFFFFFFFFull;
900 break;
901 }
902 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT: {
903 VkPhysicalDeviceTransformFeedbackPropertiesEXT *properties =
904 (VkPhysicalDeviceTransformFeedbackPropertiesEXT *)ext;
905
906 properties->maxTransformFeedbackStreams = IR3_MAX_SO_STREAMS;
907 properties->maxTransformFeedbackBuffers = IR3_MAX_SO_BUFFERS;
908 properties->maxTransformFeedbackBufferSize = UINT32_MAX;
909 properties->maxTransformFeedbackStreamDataSize = 512;
910 properties->maxTransformFeedbackBufferDataSize = 512;
911 properties->maxTransformFeedbackBufferDataStride = 512;
912 properties->transformFeedbackQueries = true;
913 properties->transformFeedbackStreamsLinesTriangles = false;
914 properties->transformFeedbackRasterizationStreamSelect = false;
915 properties->transformFeedbackDraw = true;
916 break;
917 }
918 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT: {
919 VkPhysicalDeviceSampleLocationsPropertiesEXT *properties =
920 (VkPhysicalDeviceSampleLocationsPropertiesEXT *)ext;
921 properties->sampleLocationSampleCounts = 0;
922 if (pdevice->supported_extensions.EXT_sample_locations) {
923 properties->sampleLocationSampleCounts =
924 VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;
925 }
926 properties->maxSampleLocationGridSize = (VkExtent2D) { 1 , 1 };
927 properties->sampleLocationCoordinateRange[0] = 0.0f;
928 properties->sampleLocationCoordinateRange[1] = 0.9375f;
929 properties->sampleLocationSubPixelBits = 4;
930 properties->variableSampleLocations = true;
931 break;
932 }
933 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES: {
934 VkPhysicalDeviceSamplerFilterMinmaxProperties *properties =
935 (VkPhysicalDeviceSamplerFilterMinmaxProperties *)ext;
936 properties->filterMinmaxImageComponentMapping = true;
937 properties->filterMinmaxSingleComponentFormats = true;
938 break;
939 }
940 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES: {
941 VkPhysicalDeviceSubgroupProperties *properties =
942 (VkPhysicalDeviceSubgroupProperties *)ext;
943 properties->subgroupSize = 64;
944 properties->supportedStages = VK_SHADER_STAGE_COMPUTE_BIT;
945 properties->supportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT |
946 VK_SUBGROUP_FEATURE_VOTE_BIT;
947 properties->quadOperationsInAllStages = false;
948 break;
949 }
950 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
951 VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *props =
952 (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext;
953 props->maxVertexAttribDivisor = UINT32_MAX;
954 break;
955 }
956 default:
957 break;
958 }
959 }
960 }
961
962 static const VkQueueFamilyProperties tu_queue_family_properties = {
963 .queueFlags =
964 VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT,
965 .queueCount = 1,
966 .timestampValidBits = 48,
967 .minImageTransferGranularity = { 1, 1, 1 },
968 };
969
970 void
971 tu_GetPhysicalDeviceQueueFamilyProperties(
972 VkPhysicalDevice physicalDevice,
973 uint32_t *pQueueFamilyPropertyCount,
974 VkQueueFamilyProperties *pQueueFamilyProperties)
975 {
976 VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
977
978 vk_outarray_append(&out, p) { *p = tu_queue_family_properties; }
979 }
980
981 void
982 tu_GetPhysicalDeviceQueueFamilyProperties2(
983 VkPhysicalDevice physicalDevice,
984 uint32_t *pQueueFamilyPropertyCount,
985 VkQueueFamilyProperties2 *pQueueFamilyProperties)
986 {
987 VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
988
989 vk_outarray_append(&out, p)
990 {
991 p->queueFamilyProperties = tu_queue_family_properties;
992 }
993 }
994
995 static uint64_t
996 tu_get_system_heap_size()
997 {
998 struct sysinfo info;
999 sysinfo(&info);
1000
1001 uint64_t total_ram = (uint64_t) info.totalram * (uint64_t) info.mem_unit;
1002
1003 /* We don't want to burn too much ram with the GPU. If the user has 4GiB
1004 * or less, we use at most half. If they have more than 4GiB, we use 3/4.
1005 */
1006 uint64_t available_ram;
1007 if (total_ram <= 4ull * 1024ull * 1024ull * 1024ull)
1008 available_ram = total_ram / 2;
1009 else
1010 available_ram = total_ram * 3 / 4;
1011
1012 return available_ram;
1013 }
1014
1015 void
1016 tu_GetPhysicalDeviceMemoryProperties(
1017 VkPhysicalDevice physicalDevice,
1018 VkPhysicalDeviceMemoryProperties *pMemoryProperties)
1019 {
1020 pMemoryProperties->memoryHeapCount = 1;
1021 pMemoryProperties->memoryHeaps[0].size = tu_get_system_heap_size();
1022 pMemoryProperties->memoryHeaps[0].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT;
1023
1024 pMemoryProperties->memoryTypeCount = 1;
1025 pMemoryProperties->memoryTypes[0].propertyFlags =
1026 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
1027 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
1028 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
1029 pMemoryProperties->memoryTypes[0].heapIndex = 0;
1030 }
1031
1032 void
1033 tu_GetPhysicalDeviceMemoryProperties2(
1034 VkPhysicalDevice physicalDevice,
1035 VkPhysicalDeviceMemoryProperties2 *pMemoryProperties)
1036 {
1037 return tu_GetPhysicalDeviceMemoryProperties(
1038 physicalDevice, &pMemoryProperties->memoryProperties);
1039 }
1040
1041 static VkResult
1042 tu_queue_init(struct tu_device *device,
1043 struct tu_queue *queue,
1044 uint32_t queue_family_index,
1045 int idx,
1046 VkDeviceQueueCreateFlags flags)
1047 {
1048 vk_object_base_init(&device->vk, &queue->base, VK_OBJECT_TYPE_QUEUE);
1049
1050 queue->device = device;
1051 queue->queue_family_index = queue_family_index;
1052 queue->queue_idx = idx;
1053 queue->flags = flags;
1054
1055 int ret = tu_drm_submitqueue_new(device, 0, &queue->msm_queue_id);
1056 if (ret)
1057 return VK_ERROR_INITIALIZATION_FAILED;
1058
1059 tu_fence_init(&queue->submit_fence, false);
1060
1061 return VK_SUCCESS;
1062 }
1063
1064 static void
1065 tu_queue_finish(struct tu_queue *queue)
1066 {
1067 tu_fence_finish(&queue->submit_fence);
1068 tu_drm_submitqueue_close(queue->device, queue->msm_queue_id);
1069 }
1070
1071 static int
1072 tu_get_device_extension_index(const char *name)
1073 {
1074 for (unsigned i = 0; i < TU_DEVICE_EXTENSION_COUNT; ++i) {
1075 if (strcmp(name, tu_device_extensions[i].extensionName) == 0)
1076 return i;
1077 }
1078 return -1;
1079 }
1080
1081 struct PACKED bcolor_entry {
1082 uint32_t fp32[4];
1083 uint16_t ui16[4];
1084 int16_t si16[4];
1085 uint16_t fp16[4];
1086 uint16_t rgb565;
1087 uint16_t rgb5a1;
1088 uint16_t rgba4;
1089 uint8_t __pad0[2];
1090 uint8_t ui8[4];
1091 int8_t si8[4];
1092 uint32_t rgb10a2;
1093 uint32_t z24; /* also s8? */
1094 uint16_t srgb[4]; /* appears to duplicate fp16[], but clamped, used for srgb */
1095 uint8_t __pad1[56];
1096 } border_color[] = {
1097 [VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK] = {},
1098 [VK_BORDER_COLOR_INT_TRANSPARENT_BLACK] = {},
1099 [VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK] = {
1100 .fp32[3] = 0x3f800000,
1101 .ui16[3] = 0xffff,
1102 .si16[3] = 0x7fff,
1103 .fp16[3] = 0x3c00,
1104 .rgb5a1 = 0x8000,
1105 .rgba4 = 0xf000,
1106 .ui8[3] = 0xff,
1107 .si8[3] = 0x7f,
1108 .rgb10a2 = 0xc0000000,
1109 .srgb[3] = 0x3c00,
1110 },
1111 [VK_BORDER_COLOR_INT_OPAQUE_BLACK] = {
1112 .fp32[3] = 1,
1113 .fp16[3] = 1,
1114 },
1115 [VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE] = {
1116 .fp32[0 ... 3] = 0x3f800000,
1117 .ui16[0 ... 3] = 0xffff,
1118 .si16[0 ... 3] = 0x7fff,
1119 .fp16[0 ... 3] = 0x3c00,
1120 .rgb565 = 0xffff,
1121 .rgb5a1 = 0xffff,
1122 .rgba4 = 0xffff,
1123 .ui8[0 ... 3] = 0xff,
1124 .si8[0 ... 3] = 0x7f,
1125 .rgb10a2 = 0xffffffff,
1126 .z24 = 0xffffff,
1127 .srgb[0 ... 3] = 0x3c00,
1128 },
1129 [VK_BORDER_COLOR_INT_OPAQUE_WHITE] = {
1130 .fp32[0 ... 3] = 1,
1131 .fp16[0 ... 3] = 1,
1132 },
1133 };
1134
1135 VkResult
1136 tu_CreateDevice(VkPhysicalDevice physicalDevice,
1137 const VkDeviceCreateInfo *pCreateInfo,
1138 const VkAllocationCallbacks *pAllocator,
1139 VkDevice *pDevice)
1140 {
1141 TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
1142 VkResult result;
1143 struct tu_device *device;
1144
1145 /* Check enabled features */
1146 if (pCreateInfo->pEnabledFeatures) {
1147 VkPhysicalDeviceFeatures supported_features;
1148 tu_GetPhysicalDeviceFeatures(physicalDevice, &supported_features);
1149 VkBool32 *supported_feature = (VkBool32 *) &supported_features;
1150 VkBool32 *enabled_feature = (VkBool32 *) pCreateInfo->pEnabledFeatures;
1151 unsigned num_features =
1152 sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
1153 for (uint32_t i = 0; i < num_features; i++) {
1154 if (enabled_feature[i] && !supported_feature[i])
1155 return vk_error(physical_device->instance,
1156 VK_ERROR_FEATURE_NOT_PRESENT);
1157 }
1158 }
1159
1160 device = vk_zalloc2(&physical_device->instance->alloc, pAllocator,
1161 sizeof(*device), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1162 if (!device)
1163 return vk_error(physical_device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1164
1165 vk_device_init(&device->vk, pCreateInfo,
1166 &physical_device->instance->alloc, pAllocator);
1167
1168 device->instance = physical_device->instance;
1169 device->physical_device = physical_device;
1170 device->_lost = false;
1171
1172 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
1173 const char *ext_name = pCreateInfo->ppEnabledExtensionNames[i];
1174 int index = tu_get_device_extension_index(ext_name);
1175 if (index < 0 ||
1176 !physical_device->supported_extensions.extensions[index]) {
1177 vk_free(&device->vk.alloc, device);
1178 return vk_error(physical_device->instance,
1179 VK_ERROR_EXTENSION_NOT_PRESENT);
1180 }
1181
1182 device->enabled_extensions.extensions[index] = true;
1183 }
1184
1185 for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
1186 const VkDeviceQueueCreateInfo *queue_create =
1187 &pCreateInfo->pQueueCreateInfos[i];
1188 uint32_t qfi = queue_create->queueFamilyIndex;
1189 device->queues[qfi] = vk_alloc(
1190 &device->vk.alloc, queue_create->queueCount * sizeof(struct tu_queue),
1191 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1192 if (!device->queues[qfi]) {
1193 result = VK_ERROR_OUT_OF_HOST_MEMORY;
1194 goto fail_queues;
1195 }
1196
1197 memset(device->queues[qfi], 0,
1198 queue_create->queueCount * sizeof(struct tu_queue));
1199
1200 device->queue_count[qfi] = queue_create->queueCount;
1201
1202 for (unsigned q = 0; q < queue_create->queueCount; q++) {
1203 result = tu_queue_init(device, &device->queues[qfi][q], qfi, q,
1204 queue_create->flags);
1205 if (result != VK_SUCCESS)
1206 goto fail_queues;
1207 }
1208 }
1209
1210 device->compiler = ir3_compiler_create(NULL, physical_device->gpu_id);
1211 if (!device->compiler)
1212 goto fail_queues;
1213
1214 /* initial sizes, these will increase if there is overflow */
1215 device->vsc_draw_strm_pitch = 0x1000 + VSC_PAD;
1216 device->vsc_prim_strm_pitch = 0x4000 + VSC_PAD;
1217
1218 STATIC_ASSERT(sizeof(border_color) == sizeof(((struct tu6_global*) 0)->border_color));
1219 result = tu_bo_init_new(device, &device->global_bo, sizeof(struct tu6_global));
1220 if (result != VK_SUCCESS)
1221 goto fail_global_bo;
1222
1223 result = tu_bo_map(device, &device->global_bo);
1224 if (result != VK_SUCCESS)
1225 goto fail_global_bo_map;
1226
1227 struct tu6_global *global = device->global_bo.map;
1228 memcpy(global->border_color, border_color, sizeof(border_color));
1229 global->predicate = 0;
1230 tu_init_clear_blit_shaders(global);
1231
1232 VkPipelineCacheCreateInfo ci;
1233 ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
1234 ci.pNext = NULL;
1235 ci.flags = 0;
1236 ci.pInitialData = NULL;
1237 ci.initialDataSize = 0;
1238 VkPipelineCache pc;
1239 result =
1240 tu_CreatePipelineCache(tu_device_to_handle(device), &ci, NULL, &pc);
1241 if (result != VK_SUCCESS)
1242 goto fail_pipeline_cache;
1243
1244 device->mem_cache = tu_pipeline_cache_from_handle(pc);
1245
1246 for (unsigned i = 0; i < ARRAY_SIZE(device->scratch_bos); i++)
1247 mtx_init(&device->scratch_bos[i].construct_mtx, mtx_plain);
1248
1249 mtx_init(&device->vsc_pitch_mtx, mtx_plain);
1250
1251 *pDevice = tu_device_to_handle(device);
1252 return VK_SUCCESS;
1253
1254 fail_pipeline_cache:
1255 fail_global_bo_map:
1256 tu_bo_finish(device, &device->global_bo);
1257
1258 fail_global_bo:
1259 ralloc_free(device->compiler);
1260
1261 fail_queues:
1262 for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {
1263 for (unsigned q = 0; q < device->queue_count[i]; q++)
1264 tu_queue_finish(&device->queues[i][q]);
1265 if (device->queue_count[i])
1266 vk_object_free(&device->vk, NULL, device->queues[i]);
1267 }
1268
1269 vk_free(&device->vk.alloc, device);
1270 return result;
1271 }
1272
1273 void
1274 tu_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator)
1275 {
1276 TU_FROM_HANDLE(tu_device, device, _device);
1277
1278 if (!device)
1279 return;
1280
1281 for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {
1282 for (unsigned q = 0; q < device->queue_count[i]; q++)
1283 tu_queue_finish(&device->queues[i][q]);
1284 if (device->queue_count[i])
1285 vk_object_free(&device->vk, NULL, device->queues[i]);
1286 }
1287
1288 for (unsigned i = 0; i < ARRAY_SIZE(device->scratch_bos); i++) {
1289 if (device->scratch_bos[i].initialized)
1290 tu_bo_finish(device, &device->scratch_bos[i].bo);
1291 }
1292
1293 ir3_compiler_destroy(device->compiler);
1294
1295 VkPipelineCache pc = tu_pipeline_cache_to_handle(device->mem_cache);
1296 tu_DestroyPipelineCache(tu_device_to_handle(device), pc, NULL);
1297
1298 vk_free(&device->vk.alloc, device);
1299 }
1300
1301 VkResult
1302 _tu_device_set_lost(struct tu_device *device,
1303 const char *file, int line,
1304 const char *msg, ...)
1305 {
1306 /* Set the flag indicating that waits should return in finite time even
1307 * after device loss.
1308 */
1309 p_atomic_inc(&device->_lost);
1310
1311 /* TODO: Report the log message through VkDebugReportCallbackEXT instead */
1312 fprintf(stderr, "%s:%d: ", file, line);
1313 va_list ap;
1314 va_start(ap, msg);
1315 vfprintf(stderr, msg, ap);
1316 va_end(ap);
1317
1318 if (env_var_as_boolean("TU_ABORT_ON_DEVICE_LOSS", false))
1319 abort();
1320
1321 return VK_ERROR_DEVICE_LOST;
1322 }
1323
1324 VkResult
1325 tu_get_scratch_bo(struct tu_device *dev, uint64_t size, struct tu_bo **bo)
1326 {
1327 unsigned size_log2 = MAX2(util_logbase2_ceil64(size), MIN_SCRATCH_BO_SIZE_LOG2);
1328 unsigned index = size_log2 - MIN_SCRATCH_BO_SIZE_LOG2;
1329 assert(index < ARRAY_SIZE(dev->scratch_bos));
1330
1331 for (unsigned i = index; i < ARRAY_SIZE(dev->scratch_bos); i++) {
1332 if (p_atomic_read(&dev->scratch_bos[i].initialized)) {
1333 /* Fast path: just return the already-allocated BO. */
1334 *bo = &dev->scratch_bos[i].bo;
1335 return VK_SUCCESS;
1336 }
1337 }
1338
1339 /* Slow path: actually allocate the BO. We take a lock because the process
1340 * of allocating it is slow, and we don't want to block the CPU while it
1341 * finishes.
1342 */
1343 mtx_lock(&dev->scratch_bos[index].construct_mtx);
1344
1345 /* Another thread may have allocated it already while we were waiting on
1346 * the lock. We need to check this in order to avoid double-allocating.
1347 */
1348 if (dev->scratch_bos[index].initialized) {
1349 mtx_unlock(&dev->scratch_bos[index].construct_mtx);
1350 *bo = &dev->scratch_bos[index].bo;
1351 return VK_SUCCESS;
1352 }
1353
1354 unsigned bo_size = 1ull << size_log2;
1355 VkResult result = tu_bo_init_new(dev, &dev->scratch_bos[index].bo, bo_size);
1356 if (result != VK_SUCCESS) {
1357 mtx_unlock(&dev->scratch_bos[index].construct_mtx);
1358 return result;
1359 }
1360
1361 p_atomic_set(&dev->scratch_bos[index].initialized, true);
1362
1363 mtx_unlock(&dev->scratch_bos[index].construct_mtx);
1364
1365 *bo = &dev->scratch_bos[index].bo;
1366 return VK_SUCCESS;
1367 }
1368
1369 VkResult
1370 tu_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
1371 VkLayerProperties *pProperties)
1372 {
1373 *pPropertyCount = 0;
1374 return VK_SUCCESS;
1375 }
1376
1377 VkResult
1378 tu_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
1379 uint32_t *pPropertyCount,
1380 VkLayerProperties *pProperties)
1381 {
1382 *pPropertyCount = 0;
1383 return VK_SUCCESS;
1384 }
1385
1386 void
1387 tu_GetDeviceQueue2(VkDevice _device,
1388 const VkDeviceQueueInfo2 *pQueueInfo,
1389 VkQueue *pQueue)
1390 {
1391 TU_FROM_HANDLE(tu_device, device, _device);
1392 struct tu_queue *queue;
1393
1394 queue =
1395 &device->queues[pQueueInfo->queueFamilyIndex][pQueueInfo->queueIndex];
1396 if (pQueueInfo->flags != queue->flags) {
1397 /* From the Vulkan 1.1.70 spec:
1398 *
1399 * "The queue returned by vkGetDeviceQueue2 must have the same
1400 * flags value from this structure as that used at device
1401 * creation time in a VkDeviceQueueCreateInfo instance. If no
1402 * matching flags were specified at device creation time then
1403 * pQueue will return VK_NULL_HANDLE."
1404 */
1405 *pQueue = VK_NULL_HANDLE;
1406 return;
1407 }
1408
1409 *pQueue = tu_queue_to_handle(queue);
1410 }
1411
1412 void
1413 tu_GetDeviceQueue(VkDevice _device,
1414 uint32_t queueFamilyIndex,
1415 uint32_t queueIndex,
1416 VkQueue *pQueue)
1417 {
1418 const VkDeviceQueueInfo2 info =
1419 (VkDeviceQueueInfo2) { .sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_INFO_2,
1420 .queueFamilyIndex = queueFamilyIndex,
1421 .queueIndex = queueIndex };
1422
1423 tu_GetDeviceQueue2(_device, &info, pQueue);
1424 }
1425
1426 static VkResult
1427 tu_get_semaphore_syncobjs(const VkSemaphore *sems,
1428 uint32_t sem_count,
1429 bool wait,
1430 struct drm_msm_gem_submit_syncobj **out,
1431 uint32_t *out_count)
1432 {
1433 uint32_t syncobj_count = 0;
1434 struct drm_msm_gem_submit_syncobj *syncobjs;
1435
1436 for (uint32_t i = 0; i < sem_count; ++i) {
1437 TU_FROM_HANDLE(tu_semaphore, sem, sems[i]);
1438
1439 struct tu_semaphore_part *part =
1440 sem->temporary.kind != TU_SEMAPHORE_NONE ?
1441 &sem->temporary : &sem->permanent;
1442
1443 if (part->kind == TU_SEMAPHORE_SYNCOBJ)
1444 ++syncobj_count;
1445 }
1446
1447 *out = NULL;
1448 *out_count = syncobj_count;
1449 if (!syncobj_count)
1450 return VK_SUCCESS;
1451
1452 *out = syncobjs = calloc(syncobj_count, sizeof (*syncobjs));
1453 if (!syncobjs)
1454 return VK_ERROR_OUT_OF_HOST_MEMORY;
1455
1456 for (uint32_t i = 0, j = 0; i < sem_count; ++i) {
1457 TU_FROM_HANDLE(tu_semaphore, sem, sems[i]);
1458
1459 struct tu_semaphore_part *part =
1460 sem->temporary.kind != TU_SEMAPHORE_NONE ?
1461 &sem->temporary : &sem->permanent;
1462
1463 if (part->kind == TU_SEMAPHORE_SYNCOBJ) {
1464 syncobjs[j].handle = part->syncobj;
1465 syncobjs[j].flags = wait ? MSM_SUBMIT_SYNCOBJ_RESET : 0;
1466 ++j;
1467 }
1468 }
1469
1470 return VK_SUCCESS;
1471 }
1472
1473
1474 static void
1475 tu_semaphores_remove_temp(struct tu_device *device,
1476 const VkSemaphore *sems,
1477 uint32_t sem_count)
1478 {
1479 for (uint32_t i = 0; i < sem_count; ++i) {
1480 TU_FROM_HANDLE(tu_semaphore, sem, sems[i]);
1481 tu_semaphore_remove_temp(device, sem);
1482 }
1483 }
1484
1485 VkResult
1486 tu_QueueSubmit(VkQueue _queue,
1487 uint32_t submitCount,
1488 const VkSubmitInfo *pSubmits,
1489 VkFence _fence)
1490 {
1491 TU_FROM_HANDLE(tu_queue, queue, _queue);
1492 VkResult result;
1493
1494 for (uint32_t i = 0; i < submitCount; ++i) {
1495 const VkSubmitInfo *submit = pSubmits + i;
1496 const bool last_submit = (i == submitCount - 1);
1497 struct drm_msm_gem_submit_syncobj *in_syncobjs = NULL, *out_syncobjs = NULL;
1498 uint32_t nr_in_syncobjs, nr_out_syncobjs;
1499 struct tu_bo_list bo_list;
1500 tu_bo_list_init(&bo_list);
1501
1502 result = tu_get_semaphore_syncobjs(pSubmits[i].pWaitSemaphores,
1503 pSubmits[i].waitSemaphoreCount,
1504 false, &in_syncobjs, &nr_in_syncobjs);
1505 if (result != VK_SUCCESS) {
1506 return tu_device_set_lost(queue->device,
1507 "failed to allocate space for semaphore submission\n");
1508 }
1509
1510 result = tu_get_semaphore_syncobjs(pSubmits[i].pSignalSemaphores,
1511 pSubmits[i].signalSemaphoreCount,
1512 false, &out_syncobjs, &nr_out_syncobjs);
1513 if (result != VK_SUCCESS) {
1514 free(in_syncobjs);
1515 return tu_device_set_lost(queue->device,
1516 "failed to allocate space for semaphore submission\n");
1517 }
1518
1519 uint32_t entry_count = 0;
1520 for (uint32_t j = 0; j < submit->commandBufferCount; ++j) {
1521 TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, submit->pCommandBuffers[j]);
1522 entry_count += cmdbuf->cs.entry_count;
1523 }
1524
1525 struct drm_msm_gem_submit_cmd cmds[entry_count];
1526 uint32_t entry_idx = 0;
1527 for (uint32_t j = 0; j < submit->commandBufferCount; ++j) {
1528 TU_FROM_HANDLE(tu_cmd_buffer, cmdbuf, submit->pCommandBuffers[j]);
1529 struct tu_cs *cs = &cmdbuf->cs;
1530 for (unsigned i = 0; i < cs->entry_count; ++i, ++entry_idx) {
1531 cmds[entry_idx].type = MSM_SUBMIT_CMD_BUF;
1532 cmds[entry_idx].submit_idx =
1533 tu_bo_list_add(&bo_list, cs->entries[i].bo,
1534 MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_DUMP);
1535 cmds[entry_idx].submit_offset = cs->entries[i].offset;
1536 cmds[entry_idx].size = cs->entries[i].size;
1537 cmds[entry_idx].pad = 0;
1538 cmds[entry_idx].nr_relocs = 0;
1539 cmds[entry_idx].relocs = 0;
1540 }
1541
1542 tu_bo_list_merge(&bo_list, &cmdbuf->bo_list);
1543 }
1544
1545 uint32_t flags = MSM_PIPE_3D0;
1546 if (nr_in_syncobjs) {
1547 flags |= MSM_SUBMIT_SYNCOBJ_IN;
1548 }
1549 if (nr_out_syncobjs) {
1550 flags |= MSM_SUBMIT_SYNCOBJ_OUT;
1551 }
1552
1553 if (last_submit) {
1554 flags |= MSM_SUBMIT_FENCE_FD_OUT;
1555 }
1556
1557 struct drm_msm_gem_submit req = {
1558 .flags = flags,
1559 .queueid = queue->msm_queue_id,
1560 .bos = (uint64_t)(uintptr_t) bo_list.bo_infos,
1561 .nr_bos = bo_list.count,
1562 .cmds = (uint64_t)(uintptr_t)cmds,
1563 .nr_cmds = entry_count,
1564 .in_syncobjs = (uint64_t)(uintptr_t)in_syncobjs,
1565 .out_syncobjs = (uint64_t)(uintptr_t)out_syncobjs,
1566 .nr_in_syncobjs = nr_in_syncobjs,
1567 .nr_out_syncobjs = nr_out_syncobjs,
1568 .syncobj_stride = sizeof(struct drm_msm_gem_submit_syncobj),
1569 };
1570
1571 int ret = drmCommandWriteRead(queue->device->physical_device->local_fd,
1572 DRM_MSM_GEM_SUBMIT,
1573 &req, sizeof(req));
1574 if (ret) {
1575 free(in_syncobjs);
1576 free(out_syncobjs);
1577 return tu_device_set_lost(queue->device, "submit failed: %s\n",
1578 strerror(errno));
1579 }
1580
1581 tu_bo_list_destroy(&bo_list);
1582 free(in_syncobjs);
1583 free(out_syncobjs);
1584
1585 tu_semaphores_remove_temp(queue->device, pSubmits[i].pWaitSemaphores,
1586 pSubmits[i].waitSemaphoreCount);
1587 if (last_submit) {
1588 /* no need to merge fences as queue execution is serialized */
1589 tu_fence_update_fd(&queue->submit_fence, req.fence_fd);
1590 } else if (last_submit) {
1591 close(req.fence_fd);
1592 }
1593 }
1594
1595 if (_fence != VK_NULL_HANDLE) {
1596 TU_FROM_HANDLE(tu_fence, fence, _fence);
1597 tu_fence_copy(fence, &queue->submit_fence);
1598 }
1599
1600 return VK_SUCCESS;
1601 }
1602
1603 VkResult
1604 tu_QueueWaitIdle(VkQueue _queue)
1605 {
1606 TU_FROM_HANDLE(tu_queue, queue, _queue);
1607
1608 if (tu_device_is_lost(queue->device))
1609 return VK_ERROR_DEVICE_LOST;
1610
1611 tu_fence_wait_idle(&queue->submit_fence);
1612
1613 return VK_SUCCESS;
1614 }
1615
1616 VkResult
1617 tu_DeviceWaitIdle(VkDevice _device)
1618 {
1619 TU_FROM_HANDLE(tu_device, device, _device);
1620
1621 if (tu_device_is_lost(device))
1622 return VK_ERROR_DEVICE_LOST;
1623
1624 for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {
1625 for (unsigned q = 0; q < device->queue_count[i]; q++) {
1626 tu_QueueWaitIdle(tu_queue_to_handle(&device->queues[i][q]));
1627 }
1628 }
1629 return VK_SUCCESS;
1630 }
1631
1632 VkResult
1633 tu_EnumerateInstanceExtensionProperties(const char *pLayerName,
1634 uint32_t *pPropertyCount,
1635 VkExtensionProperties *pProperties)
1636 {
1637 VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
1638
1639 /* We spport no lyaers */
1640 if (pLayerName)
1641 return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1642
1643 for (int i = 0; i < TU_INSTANCE_EXTENSION_COUNT; i++) {
1644 if (tu_instance_extensions_supported.extensions[i]) {
1645 vk_outarray_append(&out, prop) { *prop = tu_instance_extensions[i]; }
1646 }
1647 }
1648
1649 return vk_outarray_status(&out);
1650 }
1651
1652 VkResult
1653 tu_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
1654 const char *pLayerName,
1655 uint32_t *pPropertyCount,
1656 VkExtensionProperties *pProperties)
1657 {
1658 /* We spport no lyaers */
1659 TU_FROM_HANDLE(tu_physical_device, device, physicalDevice);
1660 VK_OUTARRAY_MAKE(out, pProperties, pPropertyCount);
1661
1662 /* We spport no lyaers */
1663 if (pLayerName)
1664 return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1665
1666 for (int i = 0; i < TU_DEVICE_EXTENSION_COUNT; i++) {
1667 if (device->supported_extensions.extensions[i]) {
1668 vk_outarray_append(&out, prop) { *prop = tu_device_extensions[i]; }
1669 }
1670 }
1671
1672 return vk_outarray_status(&out);
1673 }
1674
1675 PFN_vkVoidFunction
1676 tu_GetInstanceProcAddr(VkInstance _instance, const char *pName)
1677 {
1678 TU_FROM_HANDLE(tu_instance, instance, _instance);
1679
1680 return tu_lookup_entrypoint_checked(
1681 pName, instance ? instance->api_version : 0,
1682 instance ? &instance->enabled_extensions : NULL, NULL);
1683 }
1684
1685 /* The loader wants us to expose a second GetInstanceProcAddr function
1686 * to work around certain LD_PRELOAD issues seen in apps.
1687 */
1688 PUBLIC
1689 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1690 vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName);
1691
1692 PUBLIC
1693 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1694 vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)
1695 {
1696 return tu_GetInstanceProcAddr(instance, pName);
1697 }
1698
1699 PFN_vkVoidFunction
1700 tu_GetDeviceProcAddr(VkDevice _device, const char *pName)
1701 {
1702 TU_FROM_HANDLE(tu_device, device, _device);
1703
1704 return tu_lookup_entrypoint_checked(pName, device->instance->api_version,
1705 &device->instance->enabled_extensions,
1706 &device->enabled_extensions);
1707 }
1708
1709 static VkResult
1710 tu_alloc_memory(struct tu_device *device,
1711 const VkMemoryAllocateInfo *pAllocateInfo,
1712 const VkAllocationCallbacks *pAllocator,
1713 VkDeviceMemory *pMem)
1714 {
1715 struct tu_device_memory *mem;
1716 VkResult result;
1717
1718 assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
1719
1720 if (pAllocateInfo->allocationSize == 0) {
1721 /* Apparently, this is allowed */
1722 *pMem = VK_NULL_HANDLE;
1723 return VK_SUCCESS;
1724 }
1725
1726 mem = vk_object_alloc(&device->vk, pAllocator, sizeof(*mem),
1727 VK_OBJECT_TYPE_DEVICE_MEMORY);
1728 if (mem == NULL)
1729 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
1730
1731 const VkImportMemoryFdInfoKHR *fd_info =
1732 vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
1733 if (fd_info && !fd_info->handleType)
1734 fd_info = NULL;
1735
1736 if (fd_info) {
1737 assert(fd_info->handleType ==
1738 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
1739 fd_info->handleType ==
1740 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
1741
1742 /*
1743 * TODO Importing the same fd twice gives us the same handle without
1744 * reference counting. We need to maintain a per-instance handle-to-bo
1745 * table and add reference count to tu_bo.
1746 */
1747 result = tu_bo_init_dmabuf(device, &mem->bo,
1748 pAllocateInfo->allocationSize, fd_info->fd);
1749 if (result == VK_SUCCESS) {
1750 /* take ownership and close the fd */
1751 close(fd_info->fd);
1752 }
1753 } else {
1754 result =
1755 tu_bo_init_new(device, &mem->bo, pAllocateInfo->allocationSize);
1756 }
1757
1758 if (result != VK_SUCCESS) {
1759 vk_object_free(&device->vk, pAllocator, mem);
1760 return result;
1761 }
1762
1763 mem->size = pAllocateInfo->allocationSize;
1764 mem->type_index = pAllocateInfo->memoryTypeIndex;
1765
1766 mem->map = NULL;
1767 mem->user_ptr = NULL;
1768
1769 *pMem = tu_device_memory_to_handle(mem);
1770
1771 return VK_SUCCESS;
1772 }
1773
1774 VkResult
1775 tu_AllocateMemory(VkDevice _device,
1776 const VkMemoryAllocateInfo *pAllocateInfo,
1777 const VkAllocationCallbacks *pAllocator,
1778 VkDeviceMemory *pMem)
1779 {
1780 TU_FROM_HANDLE(tu_device, device, _device);
1781 return tu_alloc_memory(device, pAllocateInfo, pAllocator, pMem);
1782 }
1783
1784 void
1785 tu_FreeMemory(VkDevice _device,
1786 VkDeviceMemory _mem,
1787 const VkAllocationCallbacks *pAllocator)
1788 {
1789 TU_FROM_HANDLE(tu_device, device, _device);
1790 TU_FROM_HANDLE(tu_device_memory, mem, _mem);
1791
1792 if (mem == NULL)
1793 return;
1794
1795 tu_bo_finish(device, &mem->bo);
1796 vk_object_free(&device->vk, pAllocator, mem);
1797 }
1798
1799 VkResult
1800 tu_MapMemory(VkDevice _device,
1801 VkDeviceMemory _memory,
1802 VkDeviceSize offset,
1803 VkDeviceSize size,
1804 VkMemoryMapFlags flags,
1805 void **ppData)
1806 {
1807 TU_FROM_HANDLE(tu_device, device, _device);
1808 TU_FROM_HANDLE(tu_device_memory, mem, _memory);
1809 VkResult result;
1810
1811 if (mem == NULL) {
1812 *ppData = NULL;
1813 return VK_SUCCESS;
1814 }
1815
1816 if (mem->user_ptr) {
1817 *ppData = mem->user_ptr;
1818 } else if (!mem->map) {
1819 result = tu_bo_map(device, &mem->bo);
1820 if (result != VK_SUCCESS)
1821 return result;
1822 *ppData = mem->map = mem->bo.map;
1823 } else
1824 *ppData = mem->map;
1825
1826 if (*ppData) {
1827 *ppData += offset;
1828 return VK_SUCCESS;
1829 }
1830
1831 return vk_error(device->instance, VK_ERROR_MEMORY_MAP_FAILED);
1832 }
1833
1834 void
1835 tu_UnmapMemory(VkDevice _device, VkDeviceMemory _memory)
1836 {
1837 /* I do not see any unmapping done by the freedreno Gallium driver. */
1838 }
1839
1840 VkResult
1841 tu_FlushMappedMemoryRanges(VkDevice _device,
1842 uint32_t memoryRangeCount,
1843 const VkMappedMemoryRange *pMemoryRanges)
1844 {
1845 return VK_SUCCESS;
1846 }
1847
1848 VkResult
1849 tu_InvalidateMappedMemoryRanges(VkDevice _device,
1850 uint32_t memoryRangeCount,
1851 const VkMappedMemoryRange *pMemoryRanges)
1852 {
1853 return VK_SUCCESS;
1854 }
1855
1856 void
1857 tu_GetBufferMemoryRequirements(VkDevice _device,
1858 VkBuffer _buffer,
1859 VkMemoryRequirements *pMemoryRequirements)
1860 {
1861 TU_FROM_HANDLE(tu_buffer, buffer, _buffer);
1862
1863 pMemoryRequirements->memoryTypeBits = 1;
1864 pMemoryRequirements->alignment = 64;
1865 pMemoryRequirements->size =
1866 align64(buffer->size, pMemoryRequirements->alignment);
1867 }
1868
1869 void
1870 tu_GetBufferMemoryRequirements2(
1871 VkDevice device,
1872 const VkBufferMemoryRequirementsInfo2 *pInfo,
1873 VkMemoryRequirements2 *pMemoryRequirements)
1874 {
1875 tu_GetBufferMemoryRequirements(device, pInfo->buffer,
1876 &pMemoryRequirements->memoryRequirements);
1877 }
1878
1879 void
1880 tu_GetImageMemoryRequirements(VkDevice _device,
1881 VkImage _image,
1882 VkMemoryRequirements *pMemoryRequirements)
1883 {
1884 TU_FROM_HANDLE(tu_image, image, _image);
1885
1886 pMemoryRequirements->memoryTypeBits = 1;
1887 pMemoryRequirements->size = image->total_size;
1888 pMemoryRequirements->alignment = image->layout[0].base_align;
1889 }
1890
1891 void
1892 tu_GetImageMemoryRequirements2(VkDevice device,
1893 const VkImageMemoryRequirementsInfo2 *pInfo,
1894 VkMemoryRequirements2 *pMemoryRequirements)
1895 {
1896 tu_GetImageMemoryRequirements(device, pInfo->image,
1897 &pMemoryRequirements->memoryRequirements);
1898 }
1899
1900 void
1901 tu_GetImageSparseMemoryRequirements(
1902 VkDevice device,
1903 VkImage image,
1904 uint32_t *pSparseMemoryRequirementCount,
1905 VkSparseImageMemoryRequirements *pSparseMemoryRequirements)
1906 {
1907 tu_stub();
1908 }
1909
1910 void
1911 tu_GetImageSparseMemoryRequirements2(
1912 VkDevice device,
1913 const VkImageSparseMemoryRequirementsInfo2 *pInfo,
1914 uint32_t *pSparseMemoryRequirementCount,
1915 VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
1916 {
1917 tu_stub();
1918 }
1919
1920 void
1921 tu_GetDeviceMemoryCommitment(VkDevice device,
1922 VkDeviceMemory memory,
1923 VkDeviceSize *pCommittedMemoryInBytes)
1924 {
1925 *pCommittedMemoryInBytes = 0;
1926 }
1927
1928 VkResult
1929 tu_BindBufferMemory2(VkDevice device,
1930 uint32_t bindInfoCount,
1931 const VkBindBufferMemoryInfo *pBindInfos)
1932 {
1933 for (uint32_t i = 0; i < bindInfoCount; ++i) {
1934 TU_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);
1935 TU_FROM_HANDLE(tu_buffer, buffer, pBindInfos[i].buffer);
1936
1937 if (mem) {
1938 buffer->bo = &mem->bo;
1939 buffer->bo_offset = pBindInfos[i].memoryOffset;
1940 } else {
1941 buffer->bo = NULL;
1942 }
1943 }
1944 return VK_SUCCESS;
1945 }
1946
1947 VkResult
1948 tu_BindBufferMemory(VkDevice device,
1949 VkBuffer buffer,
1950 VkDeviceMemory memory,
1951 VkDeviceSize memoryOffset)
1952 {
1953 const VkBindBufferMemoryInfo info = {
1954 .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
1955 .buffer = buffer,
1956 .memory = memory,
1957 .memoryOffset = memoryOffset
1958 };
1959
1960 return tu_BindBufferMemory2(device, 1, &info);
1961 }
1962
1963 VkResult
1964 tu_BindImageMemory2(VkDevice device,
1965 uint32_t bindInfoCount,
1966 const VkBindImageMemoryInfo *pBindInfos)
1967 {
1968 for (uint32_t i = 0; i < bindInfoCount; ++i) {
1969 TU_FROM_HANDLE(tu_image, image, pBindInfos[i].image);
1970 TU_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);
1971
1972 if (mem) {
1973 image->bo = &mem->bo;
1974 image->bo_offset = pBindInfos[i].memoryOffset;
1975 } else {
1976 image->bo = NULL;
1977 image->bo_offset = 0;
1978 }
1979 }
1980
1981 return VK_SUCCESS;
1982 }
1983
1984 VkResult
1985 tu_BindImageMemory(VkDevice device,
1986 VkImage image,
1987 VkDeviceMemory memory,
1988 VkDeviceSize memoryOffset)
1989 {
1990 const VkBindImageMemoryInfo info = {
1991 .sType = VK_STRUCTURE_TYPE_BIND_BUFFER_MEMORY_INFO,
1992 .image = image,
1993 .memory = memory,
1994 .memoryOffset = memoryOffset
1995 };
1996
1997 return tu_BindImageMemory2(device, 1, &info);
1998 }
1999
2000 VkResult
2001 tu_QueueBindSparse(VkQueue _queue,
2002 uint32_t bindInfoCount,
2003 const VkBindSparseInfo *pBindInfo,
2004 VkFence _fence)
2005 {
2006 return VK_SUCCESS;
2007 }
2008
2009 // Queue semaphore functions
2010
2011
2012 static void
2013 tu_semaphore_part_destroy(struct tu_device *device,
2014 struct tu_semaphore_part *part)
2015 {
2016 switch(part->kind) {
2017 case TU_SEMAPHORE_NONE:
2018 break;
2019 case TU_SEMAPHORE_SYNCOBJ:
2020 drmSyncobjDestroy(device->physical_device->local_fd, part->syncobj);
2021 break;
2022 }
2023 part->kind = TU_SEMAPHORE_NONE;
2024 }
2025
2026 static void
2027 tu_semaphore_remove_temp(struct tu_device *device,
2028 struct tu_semaphore *sem)
2029 {
2030 if (sem->temporary.kind != TU_SEMAPHORE_NONE) {
2031 tu_semaphore_part_destroy(device, &sem->temporary);
2032 }
2033 }
2034
2035 VkResult
2036 tu_CreateSemaphore(VkDevice _device,
2037 const VkSemaphoreCreateInfo *pCreateInfo,
2038 const VkAllocationCallbacks *pAllocator,
2039 VkSemaphore *pSemaphore)
2040 {
2041 TU_FROM_HANDLE(tu_device, device, _device);
2042
2043 struct tu_semaphore *sem =
2044 vk_object_alloc(&device->vk, pAllocator, sizeof(*sem),
2045 VK_OBJECT_TYPE_SEMAPHORE);
2046 if (!sem)
2047 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2048
2049 const VkExportSemaphoreCreateInfo *export =
2050 vk_find_struct_const(pCreateInfo->pNext, EXPORT_SEMAPHORE_CREATE_INFO);
2051 VkExternalSemaphoreHandleTypeFlags handleTypes =
2052 export ? export->handleTypes : 0;
2053
2054 sem->permanent.kind = TU_SEMAPHORE_NONE;
2055 sem->temporary.kind = TU_SEMAPHORE_NONE;
2056
2057 if (handleTypes) {
2058 if (drmSyncobjCreate(device->physical_device->local_fd, 0, &sem->permanent.syncobj) < 0) {
2059 vk_free2(&device->vk.alloc, pAllocator, sem);
2060 return VK_ERROR_OUT_OF_HOST_MEMORY;
2061 }
2062 sem->permanent.kind = TU_SEMAPHORE_SYNCOBJ;
2063 }
2064 *pSemaphore = tu_semaphore_to_handle(sem);
2065 return VK_SUCCESS;
2066 }
2067
2068 void
2069 tu_DestroySemaphore(VkDevice _device,
2070 VkSemaphore _semaphore,
2071 const VkAllocationCallbacks *pAllocator)
2072 {
2073 TU_FROM_HANDLE(tu_device, device, _device);
2074 TU_FROM_HANDLE(tu_semaphore, sem, _semaphore);
2075 if (!_semaphore)
2076 return;
2077
2078 tu_semaphore_part_destroy(device, &sem->permanent);
2079 tu_semaphore_part_destroy(device, &sem->temporary);
2080
2081 vk_object_free(&device->vk, pAllocator, sem);
2082 }
2083
2084 VkResult
2085 tu_CreateEvent(VkDevice _device,
2086 const VkEventCreateInfo *pCreateInfo,
2087 const VkAllocationCallbacks *pAllocator,
2088 VkEvent *pEvent)
2089 {
2090 TU_FROM_HANDLE(tu_device, device, _device);
2091
2092 struct tu_event *event =
2093 vk_object_alloc(&device->vk, pAllocator, sizeof(*event),
2094 VK_OBJECT_TYPE_EVENT);
2095 if (!event)
2096 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2097
2098 VkResult result = tu_bo_init_new(device, &event->bo, 0x1000);
2099 if (result != VK_SUCCESS)
2100 goto fail_alloc;
2101
2102 result = tu_bo_map(device, &event->bo);
2103 if (result != VK_SUCCESS)
2104 goto fail_map;
2105
2106 *pEvent = tu_event_to_handle(event);
2107
2108 return VK_SUCCESS;
2109
2110 fail_map:
2111 tu_bo_finish(device, &event->bo);
2112 fail_alloc:
2113 vk_object_free(&device->vk, pAllocator, event);
2114 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2115 }
2116
2117 void
2118 tu_DestroyEvent(VkDevice _device,
2119 VkEvent _event,
2120 const VkAllocationCallbacks *pAllocator)
2121 {
2122 TU_FROM_HANDLE(tu_device, device, _device);
2123 TU_FROM_HANDLE(tu_event, event, _event);
2124
2125 if (!event)
2126 return;
2127
2128 tu_bo_finish(device, &event->bo);
2129 vk_object_free(&device->vk, pAllocator, event);
2130 }
2131
2132 VkResult
2133 tu_GetEventStatus(VkDevice _device, VkEvent _event)
2134 {
2135 TU_FROM_HANDLE(tu_event, event, _event);
2136
2137 if (*(uint64_t*) event->bo.map == 1)
2138 return VK_EVENT_SET;
2139 return VK_EVENT_RESET;
2140 }
2141
2142 VkResult
2143 tu_SetEvent(VkDevice _device, VkEvent _event)
2144 {
2145 TU_FROM_HANDLE(tu_event, event, _event);
2146 *(uint64_t*) event->bo.map = 1;
2147
2148 return VK_SUCCESS;
2149 }
2150
2151 VkResult
2152 tu_ResetEvent(VkDevice _device, VkEvent _event)
2153 {
2154 TU_FROM_HANDLE(tu_event, event, _event);
2155 *(uint64_t*) event->bo.map = 0;
2156
2157 return VK_SUCCESS;
2158 }
2159
2160 VkResult
2161 tu_CreateBuffer(VkDevice _device,
2162 const VkBufferCreateInfo *pCreateInfo,
2163 const VkAllocationCallbacks *pAllocator,
2164 VkBuffer *pBuffer)
2165 {
2166 TU_FROM_HANDLE(tu_device, device, _device);
2167 struct tu_buffer *buffer;
2168
2169 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
2170
2171 buffer = vk_object_alloc(&device->vk, pAllocator, sizeof(*buffer),
2172 VK_OBJECT_TYPE_BUFFER);
2173 if (buffer == NULL)
2174 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2175
2176 buffer->size = pCreateInfo->size;
2177 buffer->usage = pCreateInfo->usage;
2178 buffer->flags = pCreateInfo->flags;
2179
2180 *pBuffer = tu_buffer_to_handle(buffer);
2181
2182 return VK_SUCCESS;
2183 }
2184
2185 void
2186 tu_DestroyBuffer(VkDevice _device,
2187 VkBuffer _buffer,
2188 const VkAllocationCallbacks *pAllocator)
2189 {
2190 TU_FROM_HANDLE(tu_device, device, _device);
2191 TU_FROM_HANDLE(tu_buffer, buffer, _buffer);
2192
2193 if (!buffer)
2194 return;
2195
2196 vk_object_free(&device->vk, pAllocator, buffer);
2197 }
2198
2199 VkResult
2200 tu_CreateFramebuffer(VkDevice _device,
2201 const VkFramebufferCreateInfo *pCreateInfo,
2202 const VkAllocationCallbacks *pAllocator,
2203 VkFramebuffer *pFramebuffer)
2204 {
2205 TU_FROM_HANDLE(tu_device, device, _device);
2206 TU_FROM_HANDLE(tu_render_pass, pass, pCreateInfo->renderPass);
2207 struct tu_framebuffer *framebuffer;
2208
2209 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
2210
2211 size_t size = sizeof(*framebuffer) + sizeof(struct tu_attachment_info) *
2212 pCreateInfo->attachmentCount;
2213 framebuffer = vk_object_alloc(&device->vk, pAllocator, size,
2214 VK_OBJECT_TYPE_FRAMEBUFFER);
2215 if (framebuffer == NULL)
2216 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2217
2218 framebuffer->attachment_count = pCreateInfo->attachmentCount;
2219 framebuffer->width = pCreateInfo->width;
2220 framebuffer->height = pCreateInfo->height;
2221 framebuffer->layers = pCreateInfo->layers;
2222 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
2223 VkImageView _iview = pCreateInfo->pAttachments[i];
2224 struct tu_image_view *iview = tu_image_view_from_handle(_iview);
2225 framebuffer->attachments[i].attachment = iview;
2226 }
2227
2228 tu_framebuffer_tiling_config(framebuffer, device, pass);
2229
2230 *pFramebuffer = tu_framebuffer_to_handle(framebuffer);
2231 return VK_SUCCESS;
2232 }
2233
2234 void
2235 tu_DestroyFramebuffer(VkDevice _device,
2236 VkFramebuffer _fb,
2237 const VkAllocationCallbacks *pAllocator)
2238 {
2239 TU_FROM_HANDLE(tu_device, device, _device);
2240 TU_FROM_HANDLE(tu_framebuffer, fb, _fb);
2241
2242 if (!fb)
2243 return;
2244
2245 vk_object_free(&device->vk, pAllocator, fb);
2246 }
2247
2248 static void
2249 tu_init_sampler(struct tu_device *device,
2250 struct tu_sampler *sampler,
2251 const VkSamplerCreateInfo *pCreateInfo)
2252 {
2253 const struct VkSamplerReductionModeCreateInfo *reduction =
2254 vk_find_struct_const(pCreateInfo->pNext, SAMPLER_REDUCTION_MODE_CREATE_INFO);
2255 const struct VkSamplerYcbcrConversionInfo *ycbcr_conversion =
2256 vk_find_struct_const(pCreateInfo->pNext, SAMPLER_YCBCR_CONVERSION_INFO);
2257
2258 unsigned aniso = pCreateInfo->anisotropyEnable ?
2259 util_last_bit(MIN2((uint32_t)pCreateInfo->maxAnisotropy >> 1, 8)) : 0;
2260 bool miplinear = (pCreateInfo->mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR);
2261 float min_lod = CLAMP(pCreateInfo->minLod, 0.0f, 4095.0f / 256.0f);
2262 float max_lod = CLAMP(pCreateInfo->maxLod, 0.0f, 4095.0f / 256.0f);
2263
2264 sampler->descriptor[0] =
2265 COND(miplinear, A6XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR) |
2266 A6XX_TEX_SAMP_0_XY_MAG(tu6_tex_filter(pCreateInfo->magFilter, aniso)) |
2267 A6XX_TEX_SAMP_0_XY_MIN(tu6_tex_filter(pCreateInfo->minFilter, aniso)) |
2268 A6XX_TEX_SAMP_0_ANISO(aniso) |
2269 A6XX_TEX_SAMP_0_WRAP_S(tu6_tex_wrap(pCreateInfo->addressModeU)) |
2270 A6XX_TEX_SAMP_0_WRAP_T(tu6_tex_wrap(pCreateInfo->addressModeV)) |
2271 A6XX_TEX_SAMP_0_WRAP_R(tu6_tex_wrap(pCreateInfo->addressModeW)) |
2272 A6XX_TEX_SAMP_0_LOD_BIAS(pCreateInfo->mipLodBias);
2273 sampler->descriptor[1] =
2274 /* COND(!cso->seamless_cube_map, A6XX_TEX_SAMP_1_CUBEMAPSEAMLESSFILTOFF) | */
2275 COND(pCreateInfo->unnormalizedCoordinates, A6XX_TEX_SAMP_1_UNNORM_COORDS) |
2276 A6XX_TEX_SAMP_1_MIN_LOD(min_lod) |
2277 A6XX_TEX_SAMP_1_MAX_LOD(max_lod) |
2278 COND(pCreateInfo->compareEnable,
2279 A6XX_TEX_SAMP_1_COMPARE_FUNC(tu6_compare_func(pCreateInfo->compareOp)));
2280 /* This is an offset into the border_color BO, which we fill with all the
2281 * possible Vulkan border colors in the correct order, so we can just use
2282 * the Vulkan enum with no translation necessary.
2283 */
2284 sampler->descriptor[2] =
2285 A6XX_TEX_SAMP_2_BCOLOR_OFFSET((unsigned) pCreateInfo->borderColor *
2286 sizeof(struct bcolor_entry));
2287 sampler->descriptor[3] = 0;
2288
2289 if (reduction) {
2290 sampler->descriptor[2] |= A6XX_TEX_SAMP_2_REDUCTION_MODE(
2291 tu6_reduction_mode(reduction->reductionMode));
2292 }
2293
2294 sampler->ycbcr_sampler = ycbcr_conversion ?
2295 tu_sampler_ycbcr_conversion_from_handle(ycbcr_conversion->conversion) : NULL;
2296
2297 if (sampler->ycbcr_sampler &&
2298 sampler->ycbcr_sampler->chroma_filter == VK_FILTER_LINEAR) {
2299 sampler->descriptor[2] |= A6XX_TEX_SAMP_2_CHROMA_LINEAR;
2300 }
2301
2302 /* TODO:
2303 * A6XX_TEX_SAMP_1_MIPFILTER_LINEAR_FAR disables mipmapping, but vk has no NONE mipfilter?
2304 */
2305 }
2306
2307 VkResult
2308 tu_CreateSampler(VkDevice _device,
2309 const VkSamplerCreateInfo *pCreateInfo,
2310 const VkAllocationCallbacks *pAllocator,
2311 VkSampler *pSampler)
2312 {
2313 TU_FROM_HANDLE(tu_device, device, _device);
2314 struct tu_sampler *sampler;
2315
2316 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
2317
2318 sampler = vk_object_alloc(&device->vk, pAllocator, sizeof(*sampler),
2319 VK_OBJECT_TYPE_SAMPLER);
2320 if (!sampler)
2321 return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
2322
2323 tu_init_sampler(device, sampler, pCreateInfo);
2324 *pSampler = tu_sampler_to_handle(sampler);
2325
2326 return VK_SUCCESS;
2327 }
2328
2329 void
2330 tu_DestroySampler(VkDevice _device,
2331 VkSampler _sampler,
2332 const VkAllocationCallbacks *pAllocator)
2333 {
2334 TU_FROM_HANDLE(tu_device, device, _device);
2335 TU_FROM_HANDLE(tu_sampler, sampler, _sampler);
2336
2337 if (!sampler)
2338 return;
2339
2340 vk_object_free(&device->vk, pAllocator, sampler);
2341 }
2342
2343 /* vk_icd.h does not declare this function, so we declare it here to
2344 * suppress Wmissing-prototypes.
2345 */
2346 PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
2347 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion);
2348
2349 PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
2350 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion)
2351 {
2352 /* For the full details on loader interface versioning, see
2353 * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
2354 * What follows is a condensed summary, to help you navigate the large and
2355 * confusing official doc.
2356 *
2357 * - Loader interface v0 is incompatible with later versions. We don't
2358 * support it.
2359 *
2360 * - In loader interface v1:
2361 * - The first ICD entrypoint called by the loader is
2362 * vk_icdGetInstanceProcAddr(). The ICD must statically expose this
2363 * entrypoint.
2364 * - The ICD must statically expose no other Vulkan symbol unless it
2365 * is linked with -Bsymbolic.
2366 * - Each dispatchable Vulkan handle created by the ICD must be
2367 * a pointer to a struct whose first member is VK_LOADER_DATA. The
2368 * ICD must initialize VK_LOADER_DATA.loadMagic to
2369 * ICD_LOADER_MAGIC.
2370 * - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
2371 * vkDestroySurfaceKHR(). The ICD must be capable of working with
2372 * such loader-managed surfaces.
2373 *
2374 * - Loader interface v2 differs from v1 in:
2375 * - The first ICD entrypoint called by the loader is
2376 * vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
2377 * statically expose this entrypoint.
2378 *
2379 * - Loader interface v3 differs from v2 in:
2380 * - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
2381 * vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
2382 * because the loader no longer does so.
2383 */
2384 *pSupportedVersion = MIN2(*pSupportedVersion, 3u);
2385 return VK_SUCCESS;
2386 }
2387
2388 VkResult
2389 tu_GetMemoryFdKHR(VkDevice _device,
2390 const VkMemoryGetFdInfoKHR *pGetFdInfo,
2391 int *pFd)
2392 {
2393 TU_FROM_HANDLE(tu_device, device, _device);
2394 TU_FROM_HANDLE(tu_device_memory, memory, pGetFdInfo->memory);
2395
2396 assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
2397
2398 /* At the moment, we support only the below handle types. */
2399 assert(pGetFdInfo->handleType ==
2400 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
2401 pGetFdInfo->handleType ==
2402 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
2403
2404 int prime_fd = tu_bo_export_dmabuf(device, &memory->bo);
2405 if (prime_fd < 0)
2406 return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);
2407
2408 *pFd = prime_fd;
2409 return VK_SUCCESS;
2410 }
2411
2412 VkResult
2413 tu_GetMemoryFdPropertiesKHR(VkDevice _device,
2414 VkExternalMemoryHandleTypeFlagBits handleType,
2415 int fd,
2416 VkMemoryFdPropertiesKHR *pMemoryFdProperties)
2417 {
2418 assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
2419 pMemoryFdProperties->memoryTypeBits = 1;
2420 return VK_SUCCESS;
2421 }
2422
2423 VkResult
2424 tu_ImportFenceFdKHR(VkDevice _device,
2425 const VkImportFenceFdInfoKHR *pImportFenceFdInfo)
2426 {
2427 tu_stub();
2428
2429 return VK_SUCCESS;
2430 }
2431
2432 VkResult
2433 tu_GetFenceFdKHR(VkDevice _device,
2434 const VkFenceGetFdInfoKHR *pGetFdInfo,
2435 int *pFd)
2436 {
2437 tu_stub();
2438
2439 return VK_SUCCESS;
2440 }
2441
2442 VkResult
2443 tu_ImportSemaphoreFdKHR(VkDevice _device,
2444 const VkImportSemaphoreFdInfoKHR *pImportSemaphoreFdInfo)
2445 {
2446 TU_FROM_HANDLE(tu_device, device, _device);
2447 TU_FROM_HANDLE(tu_semaphore, sem, pImportSemaphoreFdInfo->semaphore);
2448 int ret;
2449 struct tu_semaphore_part *dst = NULL;
2450
2451 if (pImportSemaphoreFdInfo->flags & VK_SEMAPHORE_IMPORT_TEMPORARY_BIT) {
2452 dst = &sem->temporary;
2453 } else {
2454 dst = &sem->permanent;
2455 }
2456
2457 uint32_t syncobj = dst->kind == TU_SEMAPHORE_SYNCOBJ ? dst->syncobj : 0;
2458
2459 switch(pImportSemaphoreFdInfo->handleType) {
2460 case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT: {
2461 uint32_t old_syncobj = syncobj;
2462 ret = drmSyncobjFDToHandle(device->physical_device->local_fd, pImportSemaphoreFdInfo->fd, &syncobj);
2463 if (ret == 0) {
2464 close(pImportSemaphoreFdInfo->fd);
2465 if (old_syncobj)
2466 drmSyncobjDestroy(device->physical_device->local_fd, old_syncobj);
2467 }
2468 break;
2469 }
2470 case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT: {
2471 if (!syncobj) {
2472 ret = drmSyncobjCreate(device->physical_device->local_fd, 0, &syncobj);
2473 if (ret)
2474 break;
2475 }
2476 if (pImportSemaphoreFdInfo->fd == -1) {
2477 ret = drmSyncobjSignal(device->physical_device->local_fd, &syncobj, 1);
2478 } else {
2479 ret = drmSyncobjImportSyncFile(device->physical_device->local_fd, syncobj, pImportSemaphoreFdInfo->fd);
2480 }
2481 if (!ret)
2482 close(pImportSemaphoreFdInfo->fd);
2483 break;
2484 }
2485 default:
2486 unreachable("Unhandled semaphore handle type");
2487 }
2488
2489 if (ret) {
2490 return VK_ERROR_INVALID_EXTERNAL_HANDLE;
2491 }
2492 dst->syncobj = syncobj;
2493 dst->kind = TU_SEMAPHORE_SYNCOBJ;
2494
2495 return VK_SUCCESS;
2496 }
2497
2498 VkResult
2499 tu_GetSemaphoreFdKHR(VkDevice _device,
2500 const VkSemaphoreGetFdInfoKHR *pGetFdInfo,
2501 int *pFd)
2502 {
2503 TU_FROM_HANDLE(tu_device, device, _device);
2504 TU_FROM_HANDLE(tu_semaphore, sem, pGetFdInfo->semaphore);
2505 int ret;
2506 uint32_t syncobj_handle;
2507
2508 if (sem->temporary.kind != TU_SEMAPHORE_NONE) {
2509 assert(sem->temporary.kind == TU_SEMAPHORE_SYNCOBJ);
2510 syncobj_handle = sem->temporary.syncobj;
2511 } else {
2512 assert(sem->permanent.kind == TU_SEMAPHORE_SYNCOBJ);
2513 syncobj_handle = sem->permanent.syncobj;
2514 }
2515
2516 switch(pGetFdInfo->handleType) {
2517 case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT:
2518 ret = drmSyncobjHandleToFD(device->physical_device->local_fd, syncobj_handle, pFd);
2519 break;
2520 case VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT:
2521 ret = drmSyncobjExportSyncFile(device->physical_device->local_fd, syncobj_handle, pFd);
2522 if (!ret) {
2523 if (sem->temporary.kind != TU_SEMAPHORE_NONE) {
2524 tu_semaphore_part_destroy(device, &sem->temporary);
2525 } else {
2526 drmSyncobjReset(device->physical_device->local_fd, &syncobj_handle, 1);
2527 }
2528 }
2529 break;
2530 default:
2531 unreachable("Unhandled semaphore handle type");
2532 }
2533
2534 if (ret)
2535 return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE);
2536 return VK_SUCCESS;
2537 }
2538
2539
2540 static bool tu_has_syncobj(struct tu_physical_device *pdev)
2541 {
2542 uint64_t value;
2543 if (drmGetCap(pdev->local_fd, DRM_CAP_SYNCOBJ, &value))
2544 return false;
2545 return value && pdev->msm_major_version == 1 && pdev->msm_minor_version >= 6;
2546 }
2547
2548 void
2549 tu_GetPhysicalDeviceExternalSemaphoreProperties(
2550 VkPhysicalDevice physicalDevice,
2551 const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo,
2552 VkExternalSemaphoreProperties *pExternalSemaphoreProperties)
2553 {
2554 TU_FROM_HANDLE(tu_physical_device, pdev, physicalDevice);
2555
2556 if (tu_has_syncobj(pdev) &&
2557 (pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT ||
2558 pExternalSemaphoreInfo->handleType == VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) {
2559 pExternalSemaphoreProperties->exportFromImportedHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
2560 pExternalSemaphoreProperties->compatibleHandleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT | VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
2561 pExternalSemaphoreProperties->externalSemaphoreFeatures = VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT |
2562 VK_EXTERNAL_SEMAPHORE_FEATURE_IMPORTABLE_BIT;
2563 } else {
2564 pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0;
2565 pExternalSemaphoreProperties->compatibleHandleTypes = 0;
2566 pExternalSemaphoreProperties->externalSemaphoreFeatures = 0;
2567 }
2568 }
2569
2570 void
2571 tu_GetPhysicalDeviceExternalFenceProperties(
2572 VkPhysicalDevice physicalDevice,
2573 const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
2574 VkExternalFenceProperties *pExternalFenceProperties)
2575 {
2576 pExternalFenceProperties->exportFromImportedHandleTypes = 0;
2577 pExternalFenceProperties->compatibleHandleTypes = 0;
2578 pExternalFenceProperties->externalFenceFeatures = 0;
2579 }
2580
2581 VkResult
2582 tu_CreateDebugReportCallbackEXT(
2583 VkInstance _instance,
2584 const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
2585 const VkAllocationCallbacks *pAllocator,
2586 VkDebugReportCallbackEXT *pCallback)
2587 {
2588 TU_FROM_HANDLE(tu_instance, instance, _instance);
2589 return vk_create_debug_report_callback(&instance->debug_report_callbacks,
2590 pCreateInfo, pAllocator,
2591 &instance->alloc, pCallback);
2592 }
2593
2594 void
2595 tu_DestroyDebugReportCallbackEXT(VkInstance _instance,
2596 VkDebugReportCallbackEXT _callback,
2597 const VkAllocationCallbacks *pAllocator)
2598 {
2599 TU_FROM_HANDLE(tu_instance, instance, _instance);
2600 vk_destroy_debug_report_callback(&instance->debug_report_callbacks,
2601 _callback, pAllocator, &instance->alloc);
2602 }
2603
2604 void
2605 tu_DebugReportMessageEXT(VkInstance _instance,
2606 VkDebugReportFlagsEXT flags,
2607 VkDebugReportObjectTypeEXT objectType,
2608 uint64_t object,
2609 size_t location,
2610 int32_t messageCode,
2611 const char *pLayerPrefix,
2612 const char *pMessage)
2613 {
2614 TU_FROM_HANDLE(tu_instance, instance, _instance);
2615 vk_debug_report(&instance->debug_report_callbacks, flags, objectType,
2616 object, location, messageCode, pLayerPrefix, pMessage);
2617 }
2618
2619 void
2620 tu_GetDeviceGroupPeerMemoryFeatures(
2621 VkDevice device,
2622 uint32_t heapIndex,
2623 uint32_t localDeviceIndex,
2624 uint32_t remoteDeviceIndex,
2625 VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)
2626 {
2627 assert(localDeviceIndex == remoteDeviceIndex);
2628
2629 *pPeerMemoryFeatures = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT |
2630 VK_PEER_MEMORY_FEATURE_COPY_DST_BIT |
2631 VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT |
2632 VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT;
2633 }
2634
2635 void tu_GetPhysicalDeviceMultisamplePropertiesEXT(
2636 VkPhysicalDevice physicalDevice,
2637 VkSampleCountFlagBits samples,
2638 VkMultisamplePropertiesEXT* pMultisampleProperties)
2639 {
2640 TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
2641
2642 if (samples <= VK_SAMPLE_COUNT_4_BIT && pdevice->supported_extensions.EXT_sample_locations)
2643 pMultisampleProperties->maxSampleLocationGridSize = (VkExtent2D){ 1, 1 };
2644 else
2645 pMultisampleProperties->maxSampleLocationGridSize = (VkExtent2D){ 0, 0 };
2646 }
2647
2648
2649 VkResult
2650 tu_CreatePrivateDataSlotEXT(VkDevice _device,
2651 const VkPrivateDataSlotCreateInfoEXT* pCreateInfo,
2652 const VkAllocationCallbacks* pAllocator,
2653 VkPrivateDataSlotEXT* pPrivateDataSlot)
2654 {
2655 TU_FROM_HANDLE(tu_device, device, _device);
2656 return vk_private_data_slot_create(&device->vk,
2657 pCreateInfo,
2658 pAllocator,
2659 pPrivateDataSlot);
2660 }
2661
2662 void
2663 tu_DestroyPrivateDataSlotEXT(VkDevice _device,
2664 VkPrivateDataSlotEXT privateDataSlot,
2665 const VkAllocationCallbacks* pAllocator)
2666 {
2667 TU_FROM_HANDLE(tu_device, device, _device);
2668 vk_private_data_slot_destroy(&device->vk, privateDataSlot, pAllocator);
2669 }
2670
2671 VkResult
2672 tu_SetPrivateDataEXT(VkDevice _device,
2673 VkObjectType objectType,
2674 uint64_t objectHandle,
2675 VkPrivateDataSlotEXT privateDataSlot,
2676 uint64_t data)
2677 {
2678 TU_FROM_HANDLE(tu_device, device, _device);
2679 return vk_object_base_set_private_data(&device->vk,
2680 objectType,
2681 objectHandle,
2682 privateDataSlot,
2683 data);
2684 }
2685
2686 void
2687 tu_GetPrivateDataEXT(VkDevice _device,
2688 VkObjectType objectType,
2689 uint64_t objectHandle,
2690 VkPrivateDataSlotEXT privateDataSlot,
2691 uint64_t* pData)
2692 {
2693 TU_FROM_HANDLE(tu_device, device, _device);
2694 vk_object_base_get_private_data(&device->vk,
2695 objectType,
2696 objectHandle,
2697 privateDataSlot,
2698 pData);
2699 }