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 #include "tu_cs.h"
30 #include "git_sha1.h"
31
32 #include <fcntl.h>
33 #include <poll.h>
34 #include <stdbool.h>
35 #include <string.h>
36 #include <sys/sysinfo.h>
37 #include <unistd.h>
38
39 #include "util/debug.h"
40 #include "util/disk_cache.h"
41 #include "util/u_atomic.h"
42 #include "vk_format.h"
43 #include "vk_util.h"
44
45 /* for fd_get_driver/device_uuid() */
46 #include "freedreno/common/freedreno_uuid.h"
47
48 #if defined(VK_USE_PLATFORM_WAYLAND_KHR) || \
49 defined(VK_USE_PLATFORM_XCB_KHR) || \
50 defined(VK_USE_PLATFORM_XLIB_KHR) || \
51 defined(VK_USE_PLATFORM_DISPLAY_KHR)
52 #define TU_HAS_SURFACE 1
53 #else
54 #define TU_HAS_SURFACE 0
55 #endif
56
57
58 static int
tu_device_get_cache_uuid(uint16_t family,void * uuid)59 tu_device_get_cache_uuid(uint16_t family, void *uuid)
60 {
61 uint32_t mesa_timestamp;
62 uint16_t f = family;
63 memset(uuid, 0, VK_UUID_SIZE);
64 if (!disk_cache_get_function_timestamp(tu_device_get_cache_uuid,
65 &mesa_timestamp))
66 return -1;
67
68 memcpy(uuid, &mesa_timestamp, 4);
69 memcpy((char *) uuid + 4, &f, 2);
70 snprintf((char *) uuid + 6, VK_UUID_SIZE - 10, "tu");
71 return 0;
72 }
73
74 #define TU_API_VERSION VK_MAKE_VERSION(1, 1, VK_HEADER_VERSION)
75
76 VKAPI_ATTR VkResult VKAPI_CALL
tu_EnumerateInstanceVersion(uint32_t * pApiVersion)77 tu_EnumerateInstanceVersion(uint32_t *pApiVersion)
78 {
79 *pApiVersion = TU_API_VERSION;
80 return VK_SUCCESS;
81 }
82
83 static const struct vk_instance_extension_table tu_instance_extensions_supported = {
84 .KHR_device_group_creation = true,
85 .KHR_external_fence_capabilities = true,
86 .KHR_external_memory_capabilities = true,
87 .KHR_external_semaphore_capabilities = true,
88 .KHR_get_physical_device_properties2 = true,
89 .KHR_surface = TU_HAS_SURFACE,
90 .KHR_get_surface_capabilities2 = TU_HAS_SURFACE,
91 .EXT_debug_report = true,
92 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
93 .KHR_wayland_surface = true,
94 #endif
95 #ifdef VK_USE_PLATFORM_XCB_KHR
96 .KHR_xcb_surface = true,
97 #endif
98 #ifdef VK_USE_PLATFORM_XLIB_KHR
99 .KHR_xlib_surface = true,
100 #endif
101 #ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
102 .EXT_acquire_xlib_display = true,
103 #endif
104 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
105 .KHR_display = true,
106 .KHR_get_display_properties2 = true,
107 .EXT_direct_mode_display = true,
108 .EXT_display_surface_counter = true,
109 #endif
110 };
111
112 static void
get_device_extensions(const struct tu_physical_device * device,struct vk_device_extension_table * ext)113 get_device_extensions(const struct tu_physical_device *device,
114 struct vk_device_extension_table *ext)
115 {
116 *ext = (struct vk_device_extension_table) {
117 .KHR_16bit_storage = device->info->a6xx.storage_16bit,
118 .KHR_bind_memory2 = true,
119 .KHR_create_renderpass2 = true,
120 .KHR_dedicated_allocation = true,
121 .KHR_depth_stencil_resolve = true,
122 .KHR_descriptor_update_template = true,
123 .KHR_device_group = true,
124 .KHR_draw_indirect_count = true,
125 .KHR_external_fence = true,
126 .KHR_external_fence_fd = true,
127 .KHR_external_memory = true,
128 .KHR_external_memory_fd = true,
129 .KHR_external_semaphore = true,
130 .KHR_external_semaphore_fd = true,
131 .KHR_get_memory_requirements2 = true,
132 .KHR_imageless_framebuffer = true,
133 .KHR_incremental_present = TU_HAS_SURFACE,
134 .KHR_image_format_list = true,
135 .KHR_maintenance1 = true,
136 .KHR_maintenance2 = true,
137 .KHR_maintenance3 = true,
138 .KHR_multiview = true,
139 .KHR_performance_query = device->instance->debug_flags & TU_DEBUG_PERFC,
140 .KHR_pipeline_executable_properties = true,
141 .KHR_push_descriptor = true,
142 .KHR_relaxed_block_layout = true,
143 .KHR_sampler_mirror_clamp_to_edge = true,
144 .KHR_sampler_ycbcr_conversion = true,
145 .KHR_shader_draw_parameters = true,
146 .KHR_shader_float_controls = true,
147 .KHR_shader_float16_int8 = true,
148 .KHR_shader_subgroup_extended_types = true,
149 .KHR_shader_terminate_invocation = true,
150 .KHR_spirv_1_4 = true,
151 .KHR_storage_buffer_storage_class = true,
152 .KHR_swapchain = TU_HAS_SURFACE,
153 .KHR_uniform_buffer_standard_layout = true,
154 .KHR_variable_pointers = true,
155 .KHR_vulkan_memory_model = true,
156 #ifndef TU_USE_KGSL
157 .KHR_timeline_semaphore = true,
158 #endif
159 #ifdef VK_USE_PLATFORM_DISPLAY_KHR
160 /* This extension is supported by common code across drivers, but it is
161 * missing some core functionality and fails
162 * dEQP-VK.wsi.display_control.register_device_event. Once some variant of
163 * https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12305 lands,
164 * then we can re-enable it.
165 */
166 /* .EXT_display_control = true, */
167 #endif
168 .EXT_external_memory_dma_buf = true,
169 .EXT_image_drm_format_modifier = true,
170 .EXT_sample_locations = device->info->a6xx.has_sample_locations,
171 .EXT_sampler_filter_minmax = true,
172 .EXT_transform_feedback = true,
173 .EXT_4444_formats = true,
174 .EXT_conditional_rendering = true,
175 .EXT_custom_border_color = true,
176 .EXT_depth_clip_enable = true,
177 .EXT_descriptor_indexing = true,
178 .EXT_extended_dynamic_state = true,
179 .EXT_extended_dynamic_state2 = true,
180 .EXT_filter_cubic = device->info->a6xx.has_tex_filter_cubic,
181 .EXT_host_query_reset = true,
182 .EXT_index_type_uint8 = true,
183 .EXT_memory_budget = true,
184 .EXT_private_data = true,
185 .EXT_robustness2 = true,
186 .EXT_scalar_block_layout = true,
187 .EXT_separate_stencil_usage = true,
188 .EXT_shader_demote_to_helper_invocation = true,
189 .EXT_shader_stencil_export = true,
190 .EXT_shader_viewport_index_layer = true,
191 .EXT_vertex_attribute_divisor = true,
192 .EXT_provoking_vertex = true,
193 .EXT_line_rasterization = true,
194 #ifdef ANDROID
195 .ANDROID_native_buffer = true,
196 #endif
197 .IMG_filter_cubic = device->info->a6xx.has_tex_filter_cubic,
198 .VALVE_mutable_descriptor_type = true,
199 };
200 }
201
202 VkResult
tu_physical_device_init(struct tu_physical_device * device,struct tu_instance * instance)203 tu_physical_device_init(struct tu_physical_device *device,
204 struct tu_instance *instance)
205 {
206 VkResult result = VK_SUCCESS;
207
208 const char *fd_name = fd_dev_name(&device->dev_id);
209 if (strncmp(fd_name, "FD", 2) == 0) {
210 device->name = vk_asprintf(&instance->vk.alloc,
211 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE,
212 "Turnip Adreno (TM) %s", &fd_name[2]);
213 } else {
214 device->name = vk_strdup(&instance->vk.alloc, fd_name,
215 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
216
217 }
218 if (!device->name) {
219 return vk_startup_errorf(instance, VK_ERROR_OUT_OF_HOST_MEMORY,
220 "device name alloc fail");
221 }
222
223 const struct fd_dev_info *info = fd_dev_info(&device->dev_id);
224 if (!info) {
225 result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
226 "device %s is unsupported", device->name);
227 goto fail_free_name;
228 }
229 switch (fd_dev_gen(&device->dev_id)) {
230 case 6:
231 device->info = info;
232 device->ccu_offset_bypass = device->info->num_ccu * A6XX_CCU_DEPTH_SIZE;
233 device->ccu_offset_gmem = (device->gmem_size -
234 device->info->num_ccu * A6XX_CCU_GMEM_COLOR_SIZE);
235 break;
236 default:
237 result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
238 "device %s is unsupported", device->name);
239 goto fail_free_name;
240 }
241 if (tu_device_get_cache_uuid(fd_dev_gpu_id(&device->dev_id), device->cache_uuid)) {
242 result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
243 "cannot generate UUID");
244 goto fail_free_name;
245 }
246
247 /* The gpu id is already embedded in the uuid so we just pass "tu"
248 * when creating the cache.
249 */
250 char buf[VK_UUID_SIZE * 2 + 1];
251 disk_cache_format_hex_id(buf, device->cache_uuid, VK_UUID_SIZE * 2);
252 device->disk_cache = disk_cache_create(device->name, buf, 0);
253
254 vk_warn_non_conformant_implementation("tu");
255
256 fd_get_driver_uuid(device->driver_uuid);
257 fd_get_device_uuid(device->device_uuid, &device->dev_id);
258
259 struct vk_device_extension_table supported_extensions;
260 get_device_extensions(device, &supported_extensions);
261
262 struct vk_physical_device_dispatch_table dispatch_table;
263 vk_physical_device_dispatch_table_from_entrypoints(
264 &dispatch_table, &tu_physical_device_entrypoints, true);
265 vk_physical_device_dispatch_table_from_entrypoints(
266 &dispatch_table, &wsi_physical_device_entrypoints, false);
267
268 result = vk_physical_device_init(&device->vk, &instance->vk,
269 &supported_extensions,
270 &dispatch_table);
271 if (result != VK_SUCCESS)
272 goto fail_free_cache;
273
274 #if TU_HAS_SURFACE
275 result = tu_wsi_init(device);
276 if (result != VK_SUCCESS) {
277 vk_startup_errorf(instance, result, "WSI init failure");
278 vk_physical_device_finish(&device->vk);
279 goto fail_free_cache;
280 }
281 #endif
282
283 return VK_SUCCESS;
284
285 fail_free_cache:
286 disk_cache_destroy(device->disk_cache);
287 fail_free_name:
288 vk_free(&instance->vk.alloc, (void *)device->name);
289 return result;
290 }
291
292 static void
tu_physical_device_finish(struct tu_physical_device * device)293 tu_physical_device_finish(struct tu_physical_device *device)
294 {
295 #if TU_HAS_SURFACE
296 tu_wsi_finish(device);
297 #endif
298
299 disk_cache_destroy(device->disk_cache);
300 close(device->local_fd);
301 if (device->master_fd != -1)
302 close(device->master_fd);
303
304 vk_free(&device->instance->vk.alloc, (void *)device->name);
305
306 vk_physical_device_finish(&device->vk);
307 }
308
309 static const struct debug_control tu_debug_options[] = {
310 { "startup", TU_DEBUG_STARTUP },
311 { "nir", TU_DEBUG_NIR },
312 { "nobin", TU_DEBUG_NOBIN },
313 { "sysmem", TU_DEBUG_SYSMEM },
314 { "forcebin", TU_DEBUG_FORCEBIN },
315 { "noubwc", TU_DEBUG_NOUBWC },
316 { "nomultipos", TU_DEBUG_NOMULTIPOS },
317 { "nolrz", TU_DEBUG_NOLRZ },
318 { "perfc", TU_DEBUG_PERFC },
319 { "flushall", TU_DEBUG_FLUSHALL },
320 { "syncdraw", TU_DEBUG_SYNCDRAW },
321 { NULL, 0 }
322 };
323
324 const char *
tu_get_debug_option_name(int id)325 tu_get_debug_option_name(int id)
326 {
327 assert(id < ARRAY_SIZE(tu_debug_options) - 1);
328 return tu_debug_options[id].string;
329 }
330
331 VKAPI_ATTR VkResult VKAPI_CALL
tu_CreateInstance(const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkInstance * pInstance)332 tu_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
333 const VkAllocationCallbacks *pAllocator,
334 VkInstance *pInstance)
335 {
336 struct tu_instance *instance;
337 VkResult result;
338
339 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
340
341 if (pAllocator == NULL)
342 pAllocator = vk_default_allocator();
343
344 instance = vk_zalloc(pAllocator, sizeof(*instance), 8,
345 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
346
347 if (!instance)
348 return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
349
350 struct vk_instance_dispatch_table dispatch_table;
351 vk_instance_dispatch_table_from_entrypoints(
352 &dispatch_table, &tu_instance_entrypoints, true);
353 vk_instance_dispatch_table_from_entrypoints(
354 &dispatch_table, &wsi_instance_entrypoints, false);
355
356 result = vk_instance_init(&instance->vk,
357 &tu_instance_extensions_supported,
358 &dispatch_table,
359 pCreateInfo, pAllocator);
360 if (result != VK_SUCCESS) {
361 vk_free(pAllocator, instance);
362 return vk_error(NULL, result);
363 }
364
365 instance->physical_device_count = -1;
366
367 instance->debug_flags =
368 parse_debug_string(getenv("TU_DEBUG"), tu_debug_options);
369
370 #ifdef DEBUG
371 /* Enable startup debugging by default on debug drivers. You almost always
372 * want to see your startup failures in that case, and it's hard to set
373 * this env var on android.
374 */
375 instance->debug_flags |= TU_DEBUG_STARTUP;
376 #endif
377
378 if (instance->debug_flags & TU_DEBUG_STARTUP)
379 mesa_logi("Created an instance");
380
381 VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
382
383 *pInstance = tu_instance_to_handle(instance);
384
385 #ifdef HAVE_PERFETTO
386 tu_perfetto_init();
387 #endif
388
389 return VK_SUCCESS;
390 }
391
392 VKAPI_ATTR void VKAPI_CALL
tu_DestroyInstance(VkInstance _instance,const VkAllocationCallbacks * pAllocator)393 tu_DestroyInstance(VkInstance _instance,
394 const VkAllocationCallbacks *pAllocator)
395 {
396 TU_FROM_HANDLE(tu_instance, instance, _instance);
397
398 if (!instance)
399 return;
400
401 for (int i = 0; i < instance->physical_device_count; ++i) {
402 tu_physical_device_finish(instance->physical_devices + i);
403 }
404
405 VG(VALGRIND_DESTROY_MEMPOOL(instance));
406
407 vk_instance_finish(&instance->vk);
408 vk_free(&instance->vk.alloc, instance);
409 }
410
411 VKAPI_ATTR VkResult VKAPI_CALL
tu_EnumeratePhysicalDevices(VkInstance _instance,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices)412 tu_EnumeratePhysicalDevices(VkInstance _instance,
413 uint32_t *pPhysicalDeviceCount,
414 VkPhysicalDevice *pPhysicalDevices)
415 {
416 TU_FROM_HANDLE(tu_instance, instance, _instance);
417 VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
418
419 VkResult result;
420
421 if (instance->physical_device_count < 0) {
422 result = tu_enumerate_devices(instance);
423 if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)
424 return result;
425 }
426
427 for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
428 vk_outarray_append(&out, p)
429 {
430 *p = tu_physical_device_to_handle(instance->physical_devices + i);
431 }
432 }
433
434 return vk_outarray_status(&out);
435 }
436
437 VKAPI_ATTR VkResult VKAPI_CALL
tu_EnumeratePhysicalDeviceGroups(VkInstance _instance,uint32_t * pPhysicalDeviceGroupCount,VkPhysicalDeviceGroupProperties * pPhysicalDeviceGroupProperties)438 tu_EnumeratePhysicalDeviceGroups(
439 VkInstance _instance,
440 uint32_t *pPhysicalDeviceGroupCount,
441 VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties)
442 {
443 TU_FROM_HANDLE(tu_instance, instance, _instance);
444 VK_OUTARRAY_MAKE(out, pPhysicalDeviceGroupProperties,
445 pPhysicalDeviceGroupCount);
446 VkResult result;
447
448 if (instance->physical_device_count < 0) {
449 result = tu_enumerate_devices(instance);
450 if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)
451 return result;
452 }
453
454 for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
455 vk_outarray_append(&out, p)
456 {
457 p->physicalDeviceCount = 1;
458 p->physicalDevices[0] =
459 tu_physical_device_to_handle(instance->physical_devices + i);
460 p->subsetAllocation = false;
461 }
462 }
463
464 return vk_outarray_status(&out);
465 }
466
467 static void
tu_get_physical_device_features_1_1(struct tu_physical_device * pdevice,VkPhysicalDeviceVulkan11Features * features)468 tu_get_physical_device_features_1_1(struct tu_physical_device *pdevice,
469 VkPhysicalDeviceVulkan11Features *features)
470 {
471 features->storageBuffer16BitAccess = pdevice->info->a6xx.storage_16bit;
472 features->uniformAndStorageBuffer16BitAccess = false;
473 features->storagePushConstant16 = false;
474 features->storageInputOutput16 = false;
475 features->multiview = true;
476 features->multiviewGeometryShader = false;
477 features->multiviewTessellationShader = false;
478 features->variablePointersStorageBuffer = true;
479 features->variablePointers = true;
480 features->protectedMemory = false;
481 features->samplerYcbcrConversion = true;
482 features->shaderDrawParameters = true;
483 }
484
485 static void
tu_get_physical_device_features_1_2(struct tu_physical_device * pdevice,VkPhysicalDeviceVulkan12Features * features)486 tu_get_physical_device_features_1_2(struct tu_physical_device *pdevice,
487 VkPhysicalDeviceVulkan12Features *features)
488 {
489 features->samplerMirrorClampToEdge = true;
490 features->drawIndirectCount = true;
491 features->storageBuffer8BitAccess = false;
492 features->uniformAndStorageBuffer8BitAccess = false;
493 features->storagePushConstant8 = false;
494 features->shaderBufferInt64Atomics = false;
495 features->shaderSharedInt64Atomics = false;
496 features->shaderFloat16 = true;
497 features->shaderInt8 = false;
498
499 features->descriptorIndexing = true;
500 features->shaderInputAttachmentArrayDynamicIndexing = false;
501 features->shaderUniformTexelBufferArrayDynamicIndexing = true;
502 features->shaderStorageTexelBufferArrayDynamicIndexing = true;
503 features->shaderUniformBufferArrayNonUniformIndexing = true;
504 features->shaderSampledImageArrayNonUniformIndexing = true;
505 features->shaderStorageBufferArrayNonUniformIndexing = true;
506 features->shaderStorageImageArrayNonUniformIndexing = true;
507 features->shaderInputAttachmentArrayNonUniformIndexing = false;
508 features->shaderUniformTexelBufferArrayNonUniformIndexing = true;
509 features->shaderStorageTexelBufferArrayNonUniformIndexing = true;
510 features->descriptorBindingUniformBufferUpdateAfterBind = false;
511 features->descriptorBindingSampledImageUpdateAfterBind = true;
512 features->descriptorBindingStorageImageUpdateAfterBind = true;
513 features->descriptorBindingStorageBufferUpdateAfterBind = true;
514 features->descriptorBindingUniformTexelBufferUpdateAfterBind = true;
515 features->descriptorBindingStorageTexelBufferUpdateAfterBind = true;
516 features->descriptorBindingUpdateUnusedWhilePending = true;
517 features->descriptorBindingPartiallyBound = true;
518 features->descriptorBindingVariableDescriptorCount = true;
519 features->runtimeDescriptorArray = true;
520
521 features->samplerFilterMinmax = true;
522 features->scalarBlockLayout = true;
523 features->imagelessFramebuffer = true;
524 features->uniformBufferStandardLayout = true;
525 features->shaderSubgroupExtendedTypes = true;
526 features->separateDepthStencilLayouts = false;
527 features->hostQueryReset = true;
528 features->timelineSemaphore = true;
529 features->bufferDeviceAddress = false;
530 features->bufferDeviceAddressCaptureReplay = false;
531 features->bufferDeviceAddressMultiDevice = false;
532 features->vulkanMemoryModel = true;
533 features->vulkanMemoryModelDeviceScope = true;
534 features->vulkanMemoryModelAvailabilityVisibilityChains = true;
535 features->shaderOutputViewportIndex = true;
536 features->shaderOutputLayer = true;
537 features->subgroupBroadcastDynamicId = false;
538 }
539
540 void
tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceFeatures2 * pFeatures)541 tu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
542 VkPhysicalDeviceFeatures2 *pFeatures)
543 {
544 TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
545
546 pFeatures->features = (VkPhysicalDeviceFeatures) {
547 .robustBufferAccess = true,
548 .fullDrawIndexUint32 = true,
549 .imageCubeArray = true,
550 .independentBlend = true,
551 .geometryShader = true,
552 .tessellationShader = true,
553 .sampleRateShading = true,
554 .dualSrcBlend = true,
555 .logicOp = true,
556 .multiDrawIndirect = true,
557 .drawIndirectFirstInstance = true,
558 .depthClamp = true,
559 .depthBiasClamp = true,
560 .fillModeNonSolid = true,
561 .depthBounds = true,
562 .wideLines = false,
563 .largePoints = true,
564 .alphaToOne = true,
565 .multiViewport = true,
566 .samplerAnisotropy = true,
567 .textureCompressionETC2 = true,
568 .textureCompressionASTC_LDR = true,
569 .textureCompressionBC = true,
570 .occlusionQueryPrecise = true,
571 .pipelineStatisticsQuery = true,
572 .vertexPipelineStoresAndAtomics = true,
573 .fragmentStoresAndAtomics = true,
574 .shaderTessellationAndGeometryPointSize = false,
575 .shaderImageGatherExtended = true,
576 .shaderStorageImageExtendedFormats = true,
577 .shaderStorageImageMultisample = false,
578 .shaderUniformBufferArrayDynamicIndexing = true,
579 .shaderSampledImageArrayDynamicIndexing = true,
580 .shaderStorageBufferArrayDynamicIndexing = true,
581 .shaderStorageImageArrayDynamicIndexing = true,
582 .shaderStorageImageReadWithoutFormat = true,
583 .shaderStorageImageWriteWithoutFormat = true,
584 .shaderClipDistance = true,
585 .shaderCullDistance = true,
586 .shaderFloat64 = false,
587 .shaderInt64 = false,
588 .shaderInt16 = true,
589 .sparseBinding = false,
590 .variableMultisampleRate = true,
591 .inheritedQueries = true,
592 };
593
594 VkPhysicalDeviceVulkan11Features core_1_1 = {
595 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
596 };
597 tu_get_physical_device_features_1_1(pdevice, &core_1_1);
598
599 VkPhysicalDeviceVulkan12Features core_1_2 = {
600 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
601 };
602 tu_get_physical_device_features_1_2(pdevice, &core_1_2);
603
604 vk_foreach_struct(ext, pFeatures->pNext)
605 {
606 if (vk_get_physical_device_core_1_1_feature_ext(ext, &core_1_1))
607 continue;
608 if (vk_get_physical_device_core_1_2_feature_ext(ext, &core_1_2))
609 continue;
610
611 switch (ext->sType) {
612 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {
613 VkPhysicalDeviceConditionalRenderingFeaturesEXT *features =
614 (VkPhysicalDeviceConditionalRenderingFeaturesEXT *) ext;
615 features->conditionalRendering = true;
616 features->inheritedConditionalRendering = true;
617 break;
618 }
619 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {
620 VkPhysicalDeviceTransformFeedbackFeaturesEXT *features =
621 (VkPhysicalDeviceTransformFeedbackFeaturesEXT *) ext;
622 features->transformFeedback = true;
623 features->geometryStreams = true;
624 break;
625 }
626 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {
627 VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features =
628 (VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext;
629 features->indexTypeUint8 = true;
630 break;
631 }
632 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
633 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features =
634 (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext;
635 features->vertexAttributeInstanceRateDivisor = true;
636 features->vertexAttributeInstanceRateZeroDivisor = true;
637 break;
638 }
639 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: {
640 VkPhysicalDevicePrivateDataFeaturesEXT *features =
641 (VkPhysicalDevicePrivateDataFeaturesEXT *)ext;
642 features->privateData = true;
643 break;
644 }
645 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: {
646 VkPhysicalDeviceDepthClipEnableFeaturesEXT *features =
647 (VkPhysicalDeviceDepthClipEnableFeaturesEXT *)ext;
648 features->depthClipEnable = true;
649 break;
650 }
651 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {
652 VkPhysicalDevice4444FormatsFeaturesEXT *features = (void *)ext;
653 features->formatA4R4G4B4 = true;
654 features->formatA4B4G4R4 = true;
655 break;
656 }
657 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {
658 VkPhysicalDeviceCustomBorderColorFeaturesEXT *features = (void *) ext;
659 features->customBorderColors = true;
660 features->customBorderColorWithoutFormat = true;
661 break;
662 }
663 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT: {
664 VkPhysicalDeviceExtendedDynamicStateFeaturesEXT *features = (void *)ext;
665 features->extendedDynamicState = true;
666 break;
667 }
668 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT: {
669 VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *features =
670 (VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *)ext;
671 features->extendedDynamicState2 = true;
672 features->extendedDynamicState2LogicOp = false;
673 features->extendedDynamicState2PatchControlPoints = false;
674 break;
675 }
676 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: {
677 VkPhysicalDevicePerformanceQueryFeaturesKHR *feature =
678 (VkPhysicalDevicePerformanceQueryFeaturesKHR *)ext;
679 feature->performanceCounterQueryPools = true;
680 feature->performanceCounterMultipleQueryPools = false;
681 break;
682 }
683 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR: {
684 VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *features =
685 (VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *)ext;
686 features->pipelineExecutableInfo = true;
687 break;
688 }
689 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES: {
690 VkPhysicalDeviceShaderFloat16Int8Features *features =
691 (VkPhysicalDeviceShaderFloat16Int8Features *) ext;
692 features->shaderFloat16 = true;
693 features->shaderInt8 = false;
694 break;
695 }
696 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT: {
697 VkPhysicalDeviceScalarBlockLayoutFeaturesEXT *features = (void *)ext;
698 features->scalarBlockLayout = true;
699 break;
700 }
701 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT: {
702 VkPhysicalDeviceRobustness2FeaturesEXT *features = (void *)ext;
703 features->robustBufferAccess2 = true;
704 features->robustImageAccess2 = true;
705 features->nullDescriptor = true;
706 break;
707 }
708 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT: {
709 VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *features =
710 (VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *)ext;
711 features->shaderDemoteToHelperInvocation = true;
712 break;
713 }
714 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR: {
715 VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR *features =
716 (VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR *)ext;
717 features->shaderTerminateInvocation = true;
718 break;
719 }
720 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES: {
721 VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *features =
722 (VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *) ext;
723 features->timelineSemaphore = true;
724 break;
725 }
726 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: {
727 VkPhysicalDeviceProvokingVertexFeaturesEXT *features =
728 (VkPhysicalDeviceProvokingVertexFeaturesEXT *)ext;
729 features->provokingVertexLast = true;
730 features->transformFeedbackPreservesProvokingVertex = true;
731 break;
732 }
733 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE: {
734 VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE *features =
735 (VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE *)ext;
736 features->mutableDescriptorType = true;
737 break;
738 }
739 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: {
740 VkPhysicalDeviceLineRasterizationFeaturesEXT *features =
741 (VkPhysicalDeviceLineRasterizationFeaturesEXT *)ext;
742 features->rectangularLines = true;
743 features->bresenhamLines = true;
744 features->smoothLines = false;
745 features->stippledRectangularLines = false;
746 features->stippledBresenhamLines = false;
747 features->stippledSmoothLines = false;
748 break;
749 }
750
751 default:
752 break;
753 }
754 }
755 }
756
757
758 static void
tu_get_physical_device_properties_1_1(struct tu_physical_device * pdevice,VkPhysicalDeviceVulkan11Properties * p)759 tu_get_physical_device_properties_1_1(struct tu_physical_device *pdevice,
760 VkPhysicalDeviceVulkan11Properties *p)
761 {
762 assert(p->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES);
763
764 memcpy(p->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
765 memcpy(p->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
766 memset(p->deviceLUID, 0, VK_LUID_SIZE);
767 p->deviceNodeMask = 0;
768 p->deviceLUIDValid = false;
769
770 p->subgroupSize = 128;
771 p->subgroupSupportedStages = VK_SHADER_STAGE_COMPUTE_BIT;
772 p->subgroupSupportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT |
773 VK_SUBGROUP_FEATURE_VOTE_BIT |
774 VK_SUBGROUP_FEATURE_BALLOT_BIT;
775 p->subgroupQuadOperationsInAllStages = false;
776
777 p->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
778 p->maxMultiviewViewCount = MAX_VIEWS;
779 p->maxMultiviewInstanceIndex = INT_MAX;
780 p->protectedNoFault = false;
781 /* Make sure everything is addressable by a signed 32-bit int, and
782 * our largest descriptors are 96 bytes.
783 */
784 p->maxPerSetDescriptors = (1ull << 31) / 96;
785 /* Our buffer size fields allow only this much */
786 p->maxMemoryAllocationSize = 0xFFFFFFFFull;
787
788 }
789
790
791 /* I have no idea what the maximum size is, but the hardware supports very
792 * large numbers of descriptors (at least 2^16). This limit is based on
793 * CP_LOAD_STATE6, which has a 28-bit field for the DWORD offset, so that
794 * we don't have to think about what to do if that overflows, but really
795 * nothing is likely to get close to this.
796 */
797 static const size_t max_descriptor_set_size = (1 << 28) / A6XX_TEX_CONST_DWORDS;
798 static const VkSampleCountFlags sample_counts =
799 VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;
800
801 static void
tu_get_physical_device_properties_1_2(struct tu_physical_device * pdevice,VkPhysicalDeviceVulkan12Properties * p)802 tu_get_physical_device_properties_1_2(struct tu_physical_device *pdevice,
803 VkPhysicalDeviceVulkan12Properties *p)
804 {
805 assert(p->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES);
806
807 p->driverID = VK_DRIVER_ID_MESA_TURNIP;
808 memset(p->driverName, 0, sizeof(p->driverName));
809 snprintf(p->driverName, VK_MAX_DRIVER_NAME_SIZE_KHR,
810 "turnip Mesa driver");
811 memset(p->driverInfo, 0, sizeof(p->driverInfo));
812 snprintf(p->driverInfo, VK_MAX_DRIVER_INFO_SIZE_KHR,
813 "Mesa " PACKAGE_VERSION MESA_GIT_SHA1);
814 /* XXX: VK 1.2: Need to pass conformance. */
815 p->conformanceVersion = (VkConformanceVersionKHR) {
816 .major = 0,
817 .minor = 0,
818 .subminor = 0,
819 .patch = 0,
820 };
821
822 p->denormBehaviorIndependence =
823 VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;
824 p->roundingModeIndependence =
825 VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;
826
827 p->shaderDenormFlushToZeroFloat16 = true;
828 p->shaderDenormPreserveFloat16 = false;
829 p->shaderRoundingModeRTEFloat16 = true;
830 p->shaderRoundingModeRTZFloat16 = false;
831 p->shaderSignedZeroInfNanPreserveFloat16 = true;
832
833 p->shaderDenormFlushToZeroFloat32 = true;
834 p->shaderDenormPreserveFloat32 = false;
835 p->shaderRoundingModeRTEFloat32 = true;
836 p->shaderRoundingModeRTZFloat32 = false;
837 p->shaderSignedZeroInfNanPreserveFloat32 = true;
838
839 p->shaderDenormFlushToZeroFloat64 = false;
840 p->shaderDenormPreserveFloat64 = false;
841 p->shaderRoundingModeRTEFloat64 = false;
842 p->shaderRoundingModeRTZFloat64 = false;
843 p->shaderSignedZeroInfNanPreserveFloat64 = false;
844
845 p->shaderUniformBufferArrayNonUniformIndexingNative = true;
846 p->shaderSampledImageArrayNonUniformIndexingNative = true;
847 p->shaderStorageBufferArrayNonUniformIndexingNative = true;
848 p->shaderStorageImageArrayNonUniformIndexingNative = true;
849 p->shaderInputAttachmentArrayNonUniformIndexingNative = false;
850 p->robustBufferAccessUpdateAfterBind = false;
851 p->quadDivergentImplicitLod = false;
852
853 p->maxUpdateAfterBindDescriptorsInAllPools = max_descriptor_set_size;
854 p->maxPerStageDescriptorUpdateAfterBindSamplers = max_descriptor_set_size;
855 p->maxPerStageDescriptorUpdateAfterBindUniformBuffers = max_descriptor_set_size;
856 p->maxPerStageDescriptorUpdateAfterBindStorageBuffers = max_descriptor_set_size;
857 p->maxPerStageDescriptorUpdateAfterBindSampledImages = max_descriptor_set_size;
858 p->maxPerStageDescriptorUpdateAfterBindStorageImages = max_descriptor_set_size;
859 p->maxPerStageDescriptorUpdateAfterBindInputAttachments = max_descriptor_set_size;
860 p->maxPerStageUpdateAfterBindResources = max_descriptor_set_size;
861 p->maxDescriptorSetUpdateAfterBindSamplers = max_descriptor_set_size;
862 p->maxDescriptorSetUpdateAfterBindUniformBuffers = max_descriptor_set_size;
863 p->maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS;
864 p->maxDescriptorSetUpdateAfterBindStorageBuffers = max_descriptor_set_size;
865 p->maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS;
866 p->maxDescriptorSetUpdateAfterBindSampledImages = max_descriptor_set_size;
867 p->maxDescriptorSetUpdateAfterBindStorageImages = max_descriptor_set_size;
868 p->maxDescriptorSetUpdateAfterBindInputAttachments = max_descriptor_set_size;
869
870 p->supportedDepthResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
871 p->supportedStencilResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
872 p->independentResolveNone = false;
873 p->independentResolve = false;
874
875 p->filterMinmaxSingleComponentFormats = true;
876 p->filterMinmaxImageComponentMapping = true;
877
878 p->maxTimelineSemaphoreValueDifference = UINT64_MAX;
879
880 p->framebufferIntegerColorSampleCounts = sample_counts;
881 }
882
883 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,VkPhysicalDeviceProperties2 * pProperties)884 tu_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
885 VkPhysicalDeviceProperties2 *pProperties)
886 {
887 TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
888
889 VkPhysicalDeviceLimits limits = {
890 .maxImageDimension1D = (1 << 14),
891 .maxImageDimension2D = (1 << 14),
892 .maxImageDimension3D = (1 << 11),
893 .maxImageDimensionCube = (1 << 14),
894 .maxImageArrayLayers = (1 << 11),
895 .maxTexelBufferElements = 128 * 1024 * 1024,
896 .maxUniformBufferRange = MAX_UNIFORM_BUFFER_RANGE,
897 .maxStorageBufferRange = MAX_STORAGE_BUFFER_RANGE,
898 .maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,
899 .maxMemoryAllocationCount = UINT32_MAX,
900 .maxSamplerAllocationCount = 64 * 1024,
901 .bufferImageGranularity = 64, /* A cache line */
902 .sparseAddressSpaceSize = 0,
903 .maxBoundDescriptorSets = MAX_SETS,
904 .maxPerStageDescriptorSamplers = max_descriptor_set_size,
905 .maxPerStageDescriptorUniformBuffers = max_descriptor_set_size,
906 .maxPerStageDescriptorStorageBuffers = max_descriptor_set_size,
907 .maxPerStageDescriptorSampledImages = max_descriptor_set_size,
908 .maxPerStageDescriptorStorageImages = max_descriptor_set_size,
909 .maxPerStageDescriptorInputAttachments = MAX_RTS,
910 .maxPerStageResources = max_descriptor_set_size,
911 .maxDescriptorSetSamplers = max_descriptor_set_size,
912 .maxDescriptorSetUniformBuffers = max_descriptor_set_size,
913 .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS,
914 .maxDescriptorSetStorageBuffers = max_descriptor_set_size,
915 .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS,
916 .maxDescriptorSetSampledImages = max_descriptor_set_size,
917 .maxDescriptorSetStorageImages = max_descriptor_set_size,
918 .maxDescriptorSetInputAttachments = MAX_RTS,
919 .maxVertexInputAttributes = 32,
920 .maxVertexInputBindings = 32,
921 .maxVertexInputAttributeOffset = 4095,
922 .maxVertexInputBindingStride = 2048,
923 .maxVertexOutputComponents = 128,
924 .maxTessellationGenerationLevel = 64,
925 .maxTessellationPatchSize = 32,
926 .maxTessellationControlPerVertexInputComponents = 128,
927 .maxTessellationControlPerVertexOutputComponents = 128,
928 .maxTessellationControlPerPatchOutputComponents = 120,
929 .maxTessellationControlTotalOutputComponents = 4096,
930 .maxTessellationEvaluationInputComponents = 128,
931 .maxTessellationEvaluationOutputComponents = 128,
932 .maxGeometryShaderInvocations = 32,
933 .maxGeometryInputComponents = 64,
934 .maxGeometryOutputComponents = 128,
935 .maxGeometryOutputVertices = 256,
936 .maxGeometryTotalOutputComponents = 1024,
937 .maxFragmentInputComponents = 124,
938 .maxFragmentOutputAttachments = 8,
939 .maxFragmentDualSrcAttachments = 1,
940 .maxFragmentCombinedOutputResources = 8,
941 .maxComputeSharedMemorySize = 32768,
942 .maxComputeWorkGroupCount = { 65535, 65535, 65535 },
943 .maxComputeWorkGroupInvocations = 2048,
944 .maxComputeWorkGroupSize = { 1024, 1024, 1024 },
945 .subPixelPrecisionBits = 8,
946 .subTexelPrecisionBits = 8,
947 .mipmapPrecisionBits = 8,
948 .maxDrawIndexedIndexValue = UINT32_MAX,
949 .maxDrawIndirectCount = UINT32_MAX,
950 .maxSamplerLodBias = 4095.0 / 256.0, /* [-16, 15.99609375] */
951 .maxSamplerAnisotropy = 16,
952 .maxViewports = MAX_VIEWPORTS,
953 .maxViewportDimensions = { MAX_VIEWPORT_SIZE, MAX_VIEWPORT_SIZE },
954 .viewportBoundsRange = { INT16_MIN, INT16_MAX },
955 .viewportSubPixelBits = 8,
956 .minMemoryMapAlignment = 4096, /* A page */
957 .minTexelBufferOffsetAlignment = 64,
958 .minUniformBufferOffsetAlignment = 64,
959 .minStorageBufferOffsetAlignment = 64,
960 .minTexelOffset = -16,
961 .maxTexelOffset = 15,
962 .minTexelGatherOffset = -32,
963 .maxTexelGatherOffset = 31,
964 .minInterpolationOffset = -0.5,
965 .maxInterpolationOffset = 0.4375,
966 .subPixelInterpolationOffsetBits = 4,
967 .maxFramebufferWidth = (1 << 14),
968 .maxFramebufferHeight = (1 << 14),
969 .maxFramebufferLayers = (1 << 10),
970 .framebufferColorSampleCounts = sample_counts,
971 .framebufferDepthSampleCounts = sample_counts,
972 .framebufferStencilSampleCounts = sample_counts,
973 .framebufferNoAttachmentsSampleCounts = sample_counts,
974 .maxColorAttachments = MAX_RTS,
975 .sampledImageColorSampleCounts = sample_counts,
976 .sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT,
977 .sampledImageDepthSampleCounts = sample_counts,
978 .sampledImageStencilSampleCounts = sample_counts,
979 .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT,
980 .maxSampleMaskWords = 1,
981 .timestampComputeAndGraphics = true,
982 .timestampPeriod = 1000000000.0 / 19200000.0, /* CP_ALWAYS_ON_COUNTER is fixed 19.2MHz */
983 .maxClipDistances = 8,
984 .maxCullDistances = 8,
985 .maxCombinedClipAndCullDistances = 8,
986 .discreteQueuePriorities = 2,
987 .pointSizeRange = { 1, 4092 },
988 .lineWidthRange = { 1.0, 1.0 },
989 .pointSizeGranularity = 0.0625,
990 .lineWidthGranularity = 0.0,
991 .strictLines = true,
992 .standardSampleLocations = true,
993 .optimalBufferCopyOffsetAlignment = 128,
994 .optimalBufferCopyRowPitchAlignment = 128,
995 .nonCoherentAtomSize = 64,
996 };
997
998 pProperties->properties = (VkPhysicalDeviceProperties) {
999 .apiVersion = TU_API_VERSION,
1000 .driverVersion = vk_get_driver_version(),
1001 .vendorID = 0x5143,
1002 .deviceID = pdevice->dev_id.chip_id,
1003 .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
1004 .limits = limits,
1005 .sparseProperties = { 0 },
1006 };
1007
1008 strcpy(pProperties->properties.deviceName, pdevice->name);
1009 memcpy(pProperties->properties.pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);
1010
1011 VkPhysicalDeviceVulkan11Properties core_1_1 = {
1012 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES,
1013 };
1014 tu_get_physical_device_properties_1_1(pdevice, &core_1_1);
1015
1016 VkPhysicalDeviceVulkan12Properties core_1_2 = {
1017 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES,
1018 };
1019 tu_get_physical_device_properties_1_2(pdevice, &core_1_2);
1020
1021 vk_foreach_struct(ext, pProperties->pNext)
1022 {
1023 if (vk_get_physical_device_core_1_1_property_ext(ext, &core_1_1))
1024 continue;
1025 if (vk_get_physical_device_core_1_2_property_ext(ext, &core_1_2))
1026 continue;
1027
1028 switch (ext->sType) {
1029 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
1030 VkPhysicalDevicePushDescriptorPropertiesKHR *properties =
1031 (VkPhysicalDevicePushDescriptorPropertiesKHR *) ext;
1032 properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
1033 break;
1034 }
1035 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT: {
1036 VkPhysicalDeviceTransformFeedbackPropertiesEXT *properties =
1037 (VkPhysicalDeviceTransformFeedbackPropertiesEXT *)ext;
1038
1039 properties->maxTransformFeedbackStreams = IR3_MAX_SO_STREAMS;
1040 properties->maxTransformFeedbackBuffers = IR3_MAX_SO_BUFFERS;
1041 properties->maxTransformFeedbackBufferSize = UINT32_MAX;
1042 properties->maxTransformFeedbackStreamDataSize = 512;
1043 properties->maxTransformFeedbackBufferDataSize = 512;
1044 properties->maxTransformFeedbackBufferDataStride = 512;
1045 properties->transformFeedbackQueries = true;
1046 properties->transformFeedbackStreamsLinesTriangles = true;
1047 properties->transformFeedbackRasterizationStreamSelect = true;
1048 properties->transformFeedbackDraw = true;
1049 break;
1050 }
1051 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT: {
1052 VkPhysicalDeviceSampleLocationsPropertiesEXT *properties =
1053 (VkPhysicalDeviceSampleLocationsPropertiesEXT *)ext;
1054 properties->sampleLocationSampleCounts = 0;
1055 if (pdevice->vk.supported_extensions.EXT_sample_locations) {
1056 properties->sampleLocationSampleCounts =
1057 VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;
1058 }
1059 properties->maxSampleLocationGridSize = (VkExtent2D) { 1 , 1 };
1060 properties->sampleLocationCoordinateRange[0] = 0.0f;
1061 properties->sampleLocationCoordinateRange[1] = 0.9375f;
1062 properties->sampleLocationSubPixelBits = 4;
1063 properties->variableSampleLocations = true;
1064 break;
1065 }
1066 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
1067 VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *props =
1068 (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext;
1069 props->maxVertexAttribDivisor = UINT32_MAX;
1070 break;
1071 }
1072 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: {
1073 VkPhysicalDeviceCustomBorderColorPropertiesEXT *props = (void *)ext;
1074 props->maxCustomBorderColorSamplers = TU_BORDER_COLOR_COUNT;
1075 break;
1076 }
1077 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR: {
1078 VkPhysicalDevicePerformanceQueryPropertiesKHR *properties =
1079 (VkPhysicalDevicePerformanceQueryPropertiesKHR *)ext;
1080 properties->allowCommandBufferQueryCopies = false;
1081 break;
1082 }
1083 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT: {
1084 VkPhysicalDeviceRobustness2PropertiesEXT *props = (void *)ext;
1085 /* see write_buffer_descriptor() */
1086 props->robustStorageBufferAccessSizeAlignment = 4;
1087 /* see write_ubo_descriptor() */
1088 props->robustUniformBufferAccessSizeAlignment = 16;
1089 break;
1090 }
1091
1092 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT: {
1093 VkPhysicalDeviceProvokingVertexPropertiesEXT *properties =
1094 (VkPhysicalDeviceProvokingVertexPropertiesEXT *)ext;
1095 properties->provokingVertexModePerPipeline = true;
1096 properties->transformFeedbackPreservesTriangleFanProvokingVertex = false;
1097 break;
1098 }
1099 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: {
1100 VkPhysicalDeviceLineRasterizationPropertiesEXT *props =
1101 (VkPhysicalDeviceLineRasterizationPropertiesEXT *)ext;
1102 props->lineSubPixelPrecisionBits = 8;
1103 break;
1104 }
1105
1106 default:
1107 break;
1108 }
1109 }
1110 }
1111
1112 static const VkQueueFamilyProperties tu_queue_family_properties = {
1113 .queueFlags =
1114 VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT,
1115 .queueCount = 1,
1116 .timestampValidBits = 48,
1117 .minImageTransferGranularity = { 1, 1, 1 },
1118 };
1119
1120 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,uint32_t * pQueueFamilyPropertyCount,VkQueueFamilyProperties2 * pQueueFamilyProperties)1121 tu_GetPhysicalDeviceQueueFamilyProperties2(
1122 VkPhysicalDevice physicalDevice,
1123 uint32_t *pQueueFamilyPropertyCount,
1124 VkQueueFamilyProperties2 *pQueueFamilyProperties)
1125 {
1126 VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
1127
1128 vk_outarray_append(&out, p)
1129 {
1130 p->queueFamilyProperties = tu_queue_family_properties;
1131 }
1132 }
1133
1134 uint64_t
tu_get_system_heap_size()1135 tu_get_system_heap_size()
1136 {
1137 struct sysinfo info;
1138 sysinfo(&info);
1139
1140 uint64_t total_ram = (uint64_t) info.totalram * (uint64_t) info.mem_unit;
1141
1142 /* We don't want to burn too much ram with the GPU. If the user has 4GiB
1143 * or less, we use at most half. If they have more than 4GiB, we use 3/4.
1144 */
1145 uint64_t available_ram;
1146 if (total_ram <= 4ull * 1024ull * 1024ull * 1024ull)
1147 available_ram = total_ram / 2;
1148 else
1149 available_ram = total_ram * 3 / 4;
1150
1151 return available_ram;
1152 }
1153
1154 static VkDeviceSize
tu_get_budget_memory(struct tu_physical_device * physical_device)1155 tu_get_budget_memory(struct tu_physical_device *physical_device)
1156 {
1157 uint64_t heap_size = physical_device->heap.size;
1158 uint64_t heap_used = physical_device->heap.used;
1159 uint64_t sys_available;
1160 ASSERTED bool has_available_memory =
1161 os_get_available_system_memory(&sys_available);
1162 assert(has_available_memory);
1163
1164 /*
1165 * Let's not incite the app to starve the system: report at most 90% of
1166 * available system memory.
1167 */
1168 uint64_t heap_available = sys_available * 9 / 10;
1169 return MIN2(heap_size, heap_used + heap_available);
1170 }
1171
1172 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice pdev,VkPhysicalDeviceMemoryProperties2 * props2)1173 tu_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice pdev,
1174 VkPhysicalDeviceMemoryProperties2 *props2)
1175 {
1176 TU_FROM_HANDLE(tu_physical_device, physical_device, pdev);
1177
1178 VkPhysicalDeviceMemoryProperties *props = &props2->memoryProperties;
1179 props->memoryHeapCount = 1;
1180 props->memoryHeaps[0].size = physical_device->heap.size;
1181 props->memoryHeaps[0].flags = physical_device->heap.flags;
1182
1183 props->memoryTypeCount = 1;
1184 props->memoryTypes[0].propertyFlags =
1185 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
1186 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
1187 VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
1188 props->memoryTypes[0].heapIndex = 0;
1189
1190 vk_foreach_struct(ext, props2->pNext)
1191 {
1192 switch (ext->sType) {
1193 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: {
1194 VkPhysicalDeviceMemoryBudgetPropertiesEXT *memory_budget_props =
1195 (VkPhysicalDeviceMemoryBudgetPropertiesEXT *) ext;
1196 memory_budget_props->heapUsage[0] = physical_device->heap.used;
1197 memory_budget_props->heapBudget[0] = tu_get_budget_memory(physical_device);
1198
1199 /* The heapBudget and heapUsage values must be zero for array elements
1200 * greater than or equal to VkPhysicalDeviceMemoryProperties::memoryHeapCount
1201 */
1202 for (unsigned i = 1; i < VK_MAX_MEMORY_HEAPS; i++) {
1203 memory_budget_props->heapBudget[i] = 0u;
1204 memory_budget_props->heapUsage[i] = 0u;
1205 }
1206 break;
1207 }
1208 default:
1209 break;
1210 }
1211 }
1212 }
1213
1214 static VkResult
tu_queue_init(struct tu_device * device,struct tu_queue * queue,int idx,const VkDeviceQueueCreateInfo * create_info)1215 tu_queue_init(struct tu_device *device,
1216 struct tu_queue *queue,
1217 int idx,
1218 const VkDeviceQueueCreateInfo *create_info)
1219 {
1220 VkResult result = vk_queue_init(&queue->vk, &device->vk, create_info, idx);
1221 if (result != VK_SUCCESS)
1222 return result;
1223
1224 queue->device = device;
1225
1226 list_inithead(&queue->queued_submits);
1227
1228 int ret = tu_drm_submitqueue_new(device, 0, &queue->msm_queue_id);
1229 if (ret)
1230 return vk_startup_errorf(device->instance, VK_ERROR_INITIALIZATION_FAILED,
1231 "submitqueue create failed");
1232
1233 queue->fence = -1;
1234
1235 return VK_SUCCESS;
1236 }
1237
1238 static void
tu_queue_finish(struct tu_queue * queue)1239 tu_queue_finish(struct tu_queue *queue)
1240 {
1241 vk_queue_finish(&queue->vk);
1242 if (queue->fence >= 0)
1243 close(queue->fence);
1244 tu_drm_submitqueue_close(queue->device, queue->msm_queue_id);
1245 }
1246
1247 uint64_t
tu_device_ticks_to_ns(struct tu_device * dev,uint64_t ts)1248 tu_device_ticks_to_ns(struct tu_device *dev, uint64_t ts)
1249 {
1250 /* This is based on the 19.2MHz always-on rbbm timer.
1251 *
1252 * TODO we should probably query this value from kernel..
1253 */
1254 return ts * (1000000000 / 19200000);
1255 }
1256
1257 static void*
tu_trace_create_ts_buffer(struct u_trace_context * utctx,uint32_t size)1258 tu_trace_create_ts_buffer(struct u_trace_context *utctx, uint32_t size)
1259 {
1260 struct tu_device *device =
1261 container_of(utctx, struct tu_device, trace_context);
1262
1263 struct tu_bo *bo = ralloc(NULL, struct tu_bo);
1264 tu_bo_init_new(device, bo, size, false);
1265
1266 return bo;
1267 }
1268
1269 static void
tu_trace_destroy_ts_buffer(struct u_trace_context * utctx,void * timestamps)1270 tu_trace_destroy_ts_buffer(struct u_trace_context *utctx, void *timestamps)
1271 {
1272 struct tu_device *device =
1273 container_of(utctx, struct tu_device, trace_context);
1274 struct tu_bo *bo = timestamps;
1275
1276 tu_bo_finish(device, bo);
1277 ralloc_free(bo);
1278 }
1279
1280 static void
tu_trace_record_ts(struct u_trace * ut,void * cs,void * timestamps,unsigned idx)1281 tu_trace_record_ts(struct u_trace *ut, void *cs, void *timestamps,
1282 unsigned idx)
1283 {
1284 struct tu_bo *bo = timestamps;
1285 struct tu_cs *ts_cs = cs;
1286
1287 unsigned ts_offset = idx * sizeof(uint64_t);
1288 tu_cs_emit_pkt7(ts_cs, CP_EVENT_WRITE, 4);
1289 tu_cs_emit(ts_cs, CP_EVENT_WRITE_0_EVENT(RB_DONE_TS) | CP_EVENT_WRITE_0_TIMESTAMP);
1290 tu_cs_emit_qw(ts_cs, bo->iova + ts_offset);
1291 tu_cs_emit(ts_cs, 0x00000000);
1292 }
1293
1294 static uint64_t
tu_trace_read_ts(struct u_trace_context * utctx,void * timestamps,unsigned idx,void * flush_data)1295 tu_trace_read_ts(struct u_trace_context *utctx,
1296 void *timestamps, unsigned idx, void *flush_data)
1297 {
1298 struct tu_device *device =
1299 container_of(utctx, struct tu_device, trace_context);
1300 struct tu_bo *bo = timestamps;
1301 struct tu_u_trace_flush_data *trace_flush_data = flush_data;
1302
1303 /* Only need to stall on results for the first entry: */
1304 if (idx == 0) {
1305 tu_device_wait_u_trace(device, trace_flush_data->syncobj);
1306 }
1307
1308 if (tu_bo_map(device, bo) != VK_SUCCESS) {
1309 return U_TRACE_NO_TIMESTAMP;
1310 }
1311
1312 uint64_t *ts = bo->map;
1313
1314 /* Don't translate the no-timestamp marker: */
1315 if (ts[idx] == U_TRACE_NO_TIMESTAMP)
1316 return U_TRACE_NO_TIMESTAMP;
1317
1318 return tu_device_ticks_to_ns(device, ts[idx]);
1319 }
1320
1321 static void
tu_trace_delete_flush_data(struct u_trace_context * utctx,void * flush_data)1322 tu_trace_delete_flush_data(struct u_trace_context *utctx, void *flush_data)
1323 {
1324 struct tu_device *device =
1325 container_of(utctx, struct tu_device, trace_context);
1326 struct tu_u_trace_flush_data *trace_flush_data = flush_data;
1327
1328 tu_u_trace_cmd_data_finish(device, trace_flush_data->cmd_trace_data,
1329 trace_flush_data->trace_count);
1330 vk_free(&device->vk.alloc, trace_flush_data->syncobj);
1331 vk_free(&device->vk.alloc, trace_flush_data);
1332 }
1333
1334 void
tu_copy_timestamp_buffer(struct u_trace_context * utctx,void * cmdstream,void * ts_from,uint32_t from_offset,void * ts_to,uint32_t to_offset,uint32_t count)1335 tu_copy_timestamp_buffer(struct u_trace_context *utctx, void *cmdstream,
1336 void *ts_from, uint32_t from_offset,
1337 void *ts_to, uint32_t to_offset,
1338 uint32_t count)
1339 {
1340 struct tu_cs *cs = cmdstream;
1341 struct tu_bo *bo_from = ts_from;
1342 struct tu_bo *bo_to = ts_to;
1343
1344 tu_cs_emit_pkt7(cs, CP_MEMCPY, 5);
1345 tu_cs_emit(cs, count * sizeof(uint64_t) / sizeof(uint32_t));
1346 tu_cs_emit_qw(cs, bo_from->iova + from_offset * sizeof(uint64_t));
1347 tu_cs_emit_qw(cs, bo_to->iova + to_offset * sizeof(uint64_t));
1348 }
1349
1350 VkResult
tu_create_copy_timestamp_cs(struct tu_cmd_buffer * cmdbuf,struct tu_cs ** cs,struct u_trace ** trace_copy)1351 tu_create_copy_timestamp_cs(struct tu_cmd_buffer *cmdbuf, struct tu_cs** cs,
1352 struct u_trace **trace_copy)
1353 {
1354 *cs = vk_zalloc(&cmdbuf->device->vk.alloc, sizeof(struct tu_cs), 8,
1355 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1356
1357 if (*cs == NULL) {
1358 return VK_ERROR_OUT_OF_HOST_MEMORY;
1359 }
1360
1361 tu_cs_init(*cs, cmdbuf->device, TU_CS_MODE_GROW,
1362 list_length(&cmdbuf->trace.trace_chunks) * 6 + 3);
1363
1364 tu_cs_begin(*cs);
1365
1366 tu_cs_emit_wfi(*cs);
1367 tu_cs_emit_pkt7(*cs, CP_WAIT_FOR_ME, 0);
1368
1369 *trace_copy = vk_zalloc(&cmdbuf->device->vk.alloc, sizeof(struct u_trace), 8,
1370 VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1371
1372 if (*trace_copy == NULL) {
1373 return VK_ERROR_OUT_OF_HOST_MEMORY;
1374 }
1375
1376 u_trace_init(*trace_copy, cmdbuf->trace.utctx);
1377 u_trace_clone_append(u_trace_begin_iterator(&cmdbuf->trace),
1378 u_trace_end_iterator(&cmdbuf->trace),
1379 *trace_copy, *cs,
1380 tu_copy_timestamp_buffer);
1381
1382 tu_cs_emit_wfi(*cs);
1383
1384 tu_cs_end(*cs);
1385
1386 return VK_SUCCESS;
1387 }
1388
1389 void
tu_u_trace_cmd_data_finish(struct tu_device * device,struct tu_u_trace_cmd_data * trace_data,uint32_t entry_count)1390 tu_u_trace_cmd_data_finish(struct tu_device *device,
1391 struct tu_u_trace_cmd_data *trace_data,
1392 uint32_t entry_count)
1393 {
1394 for (uint32_t i = 0; i < entry_count; ++i) {
1395 /* Only if we had to create a copy of trace we should free it */
1396 if (trace_data[i].timestamp_copy_cs != NULL) {
1397 tu_cs_finish(trace_data[i].timestamp_copy_cs);
1398 vk_free(&device->vk.alloc, trace_data[i].timestamp_copy_cs);
1399
1400 u_trace_fini(trace_data[i].trace);
1401 vk_free(&device->vk.alloc, trace_data[i].trace);
1402 }
1403 }
1404
1405 vk_free(&device->vk.alloc, trace_data);
1406 }
1407
1408 VKAPI_ATTR VkResult VKAPI_CALL
tu_CreateDevice(VkPhysicalDevice physicalDevice,const VkDeviceCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDevice * pDevice)1409 tu_CreateDevice(VkPhysicalDevice physicalDevice,
1410 const VkDeviceCreateInfo *pCreateInfo,
1411 const VkAllocationCallbacks *pAllocator,
1412 VkDevice *pDevice)
1413 {
1414 TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
1415 VkResult result;
1416 struct tu_device *device;
1417 bool custom_border_colors = false;
1418 bool perf_query_pools = false;
1419 bool robust_buffer_access2 = false;
1420
1421 vk_foreach_struct_const(ext, pCreateInfo->pNext) {
1422 switch (ext->sType) {
1423 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {
1424 const VkPhysicalDeviceCustomBorderColorFeaturesEXT *border_color_features = (const void *)ext;
1425 custom_border_colors = border_color_features->customBorderColors;
1426 break;
1427 }
1428 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: {
1429 const VkPhysicalDevicePerformanceQueryFeaturesKHR *feature =
1430 (VkPhysicalDevicePerformanceQueryFeaturesKHR *)ext;
1431 perf_query_pools = feature->performanceCounterQueryPools;
1432 break;
1433 }
1434 case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT: {
1435 VkPhysicalDeviceRobustness2FeaturesEXT *features = (void *)ext;
1436 robust_buffer_access2 = features->robustBufferAccess2;
1437 break;
1438 }
1439 default:
1440 break;
1441 }
1442 }
1443
1444 device = vk_zalloc2(&physical_device->instance->vk.alloc, pAllocator,
1445 sizeof(*device), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1446 if (!device)
1447 return vk_startup_errorf(physical_device->instance, VK_ERROR_OUT_OF_HOST_MEMORY, "OOM");
1448
1449 struct vk_device_dispatch_table dispatch_table;
1450 vk_device_dispatch_table_from_entrypoints(
1451 &dispatch_table, &tu_device_entrypoints, true);
1452 vk_device_dispatch_table_from_entrypoints(
1453 &dispatch_table, &wsi_device_entrypoints, false);
1454
1455 result = vk_device_init(&device->vk, &physical_device->vk,
1456 &dispatch_table, pCreateInfo, pAllocator);
1457 if (result != VK_SUCCESS) {
1458 vk_free(&device->vk.alloc, device);
1459 return vk_startup_errorf(physical_device->instance, result,
1460 "vk_device_init failed");
1461 }
1462
1463 device->instance = physical_device->instance;
1464 device->physical_device = physical_device;
1465 device->fd = physical_device->local_fd;
1466 device->_lost = false;
1467
1468 mtx_init(&device->bo_mutex, mtx_plain);
1469 pthread_mutex_init(&device->submit_mutex, NULL);
1470
1471 for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
1472 const VkDeviceQueueCreateInfo *queue_create =
1473 &pCreateInfo->pQueueCreateInfos[i];
1474 uint32_t qfi = queue_create->queueFamilyIndex;
1475 device->queues[qfi] = vk_alloc(
1476 &device->vk.alloc, queue_create->queueCount * sizeof(struct tu_queue),
1477 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1478 if (!device->queues[qfi]) {
1479 result = vk_startup_errorf(physical_device->instance,
1480 VK_ERROR_OUT_OF_HOST_MEMORY,
1481 "OOM");
1482 goto fail_queues;
1483 }
1484
1485 memset(device->queues[qfi], 0,
1486 queue_create->queueCount * sizeof(struct tu_queue));
1487
1488 device->queue_count[qfi] = queue_create->queueCount;
1489
1490 for (unsigned q = 0; q < queue_create->queueCount; q++) {
1491 result = tu_queue_init(device, &device->queues[qfi][q], q,
1492 queue_create);
1493 if (result != VK_SUCCESS)
1494 goto fail_queues;
1495 }
1496 }
1497
1498 device->compiler = ir3_compiler_create(NULL, &physical_device->dev_id,
1499 robust_buffer_access2);
1500 if (!device->compiler) {
1501 result = vk_startup_errorf(physical_device->instance,
1502 VK_ERROR_INITIALIZATION_FAILED,
1503 "failed to initialize ir3 compiler");
1504 goto fail_queues;
1505 }
1506
1507 /* initial sizes, these will increase if there is overflow */
1508 device->vsc_draw_strm_pitch = 0x1000 + VSC_PAD;
1509 device->vsc_prim_strm_pitch = 0x4000 + VSC_PAD;
1510
1511 uint32_t global_size = sizeof(struct tu6_global);
1512 if (custom_border_colors)
1513 global_size += TU_BORDER_COLOR_COUNT * sizeof(struct bcolor_entry);
1514
1515 result = tu_bo_init_new(device, &device->global_bo, global_size,
1516 TU_BO_ALLOC_ALLOW_DUMP);
1517 if (result != VK_SUCCESS) {
1518 vk_startup_errorf(device->instance, result, "BO init");
1519 goto fail_global_bo;
1520 }
1521
1522 result = tu_bo_map(device, &device->global_bo);
1523 if (result != VK_SUCCESS) {
1524 vk_startup_errorf(device->instance, result, "BO map");
1525 goto fail_global_bo_map;
1526 }
1527
1528 struct tu6_global *global = device->global_bo.map;
1529 tu_init_clear_blit_shaders(device);
1530 global->predicate = 0;
1531 tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK],
1532 &(VkClearColorValue) {}, false);
1533 tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_INT_TRANSPARENT_BLACK],
1534 &(VkClearColorValue) {}, true);
1535 tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK],
1536 &(VkClearColorValue) { .float32[3] = 1.0f }, false);
1537 tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_INT_OPAQUE_BLACK],
1538 &(VkClearColorValue) { .int32[3] = 1 }, true);
1539 tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE],
1540 &(VkClearColorValue) { .float32[0 ... 3] = 1.0f }, false);
1541 tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_INT_OPAQUE_WHITE],
1542 &(VkClearColorValue) { .int32[0 ... 3] = 1 }, true);
1543
1544 /* initialize to ones so ffs can be used to find unused slots */
1545 BITSET_ONES(device->custom_border_color);
1546
1547 VkPipelineCacheCreateInfo ci;
1548 ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
1549 ci.pNext = NULL;
1550 ci.flags = 0;
1551 ci.pInitialData = NULL;
1552 ci.initialDataSize = 0;
1553 VkPipelineCache pc;
1554 result =
1555 tu_CreatePipelineCache(tu_device_to_handle(device), &ci, NULL, &pc);
1556 if (result != VK_SUCCESS) {
1557 vk_startup_errorf(device->instance, result, "create pipeline cache failed");
1558 goto fail_pipeline_cache;
1559 }
1560
1561 if (perf_query_pools) {
1562 /* Prepare command streams setting pass index to the PERF_CNTRS_REG
1563 * from 0 to 31. One of these will be picked up at cmd submit time
1564 * when the perf query is executed.
1565 */
1566 struct tu_cs *cs;
1567
1568 if (!(device->perfcntrs_pass_cs = calloc(1, sizeof(struct tu_cs)))) {
1569 result = vk_startup_errorf(device->instance,
1570 VK_ERROR_OUT_OF_HOST_MEMORY, "OOM");
1571 goto fail_perfcntrs_pass_alloc;
1572 }
1573
1574 device->perfcntrs_pass_cs_entries = calloc(32, sizeof(struct tu_cs_entry));
1575 if (!device->perfcntrs_pass_cs_entries) {
1576 result = vk_startup_errorf(device->instance,
1577 VK_ERROR_OUT_OF_HOST_MEMORY, "OOM");
1578 goto fail_perfcntrs_pass_entries_alloc;
1579 }
1580
1581 cs = device->perfcntrs_pass_cs;
1582 tu_cs_init(cs, device, TU_CS_MODE_SUB_STREAM, 96);
1583
1584 for (unsigned i = 0; i < 32; i++) {
1585 struct tu_cs sub_cs;
1586
1587 result = tu_cs_begin_sub_stream(cs, 3, &sub_cs);
1588 if (result != VK_SUCCESS) {
1589 vk_startup_errorf(device->instance, result,
1590 "failed to allocate commands streams");
1591 goto fail_prepare_perfcntrs_pass_cs;
1592 }
1593
1594 tu_cs_emit_regs(&sub_cs, A6XX_CP_SCRATCH_REG(PERF_CNTRS_REG, 1 << i));
1595 tu_cs_emit_pkt7(&sub_cs, CP_WAIT_FOR_ME, 0);
1596
1597 device->perfcntrs_pass_cs_entries[i] = tu_cs_end_sub_stream(cs, &sub_cs);
1598 }
1599 }
1600
1601 /* Initialize a condition variable for timeline semaphore */
1602 pthread_condattr_t condattr;
1603 if (pthread_condattr_init(&condattr) != 0) {
1604 result = vk_startup_errorf(physical_device->instance,
1605 VK_ERROR_INITIALIZATION_FAILED,
1606 "pthread condattr init");
1607 goto fail_timeline_cond;
1608 }
1609 if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC) != 0) {
1610 pthread_condattr_destroy(&condattr);
1611 result = vk_startup_errorf(physical_device->instance,
1612 VK_ERROR_INITIALIZATION_FAILED,
1613 "pthread condattr clock setup");
1614 goto fail_timeline_cond;
1615 }
1616 if (pthread_cond_init(&device->timeline_cond, &condattr) != 0) {
1617 pthread_condattr_destroy(&condattr);
1618 result = vk_startup_errorf(physical_device->instance,
1619 VK_ERROR_INITIALIZATION_FAILED,
1620 "pthread cond init");
1621 goto fail_timeline_cond;
1622 }
1623 pthread_condattr_destroy(&condattr);
1624
1625 device->mem_cache = tu_pipeline_cache_from_handle(pc);
1626
1627 for (unsigned i = 0; i < ARRAY_SIZE(device->scratch_bos); i++)
1628 mtx_init(&device->scratch_bos[i].construct_mtx, mtx_plain);
1629
1630 mtx_init(&device->mutex, mtx_plain);
1631
1632 device->submit_count = 0;
1633 u_trace_context_init(&device->trace_context, device,
1634 tu_trace_create_ts_buffer,
1635 tu_trace_destroy_ts_buffer,
1636 tu_trace_record_ts,
1637 tu_trace_read_ts,
1638 tu_trace_delete_flush_data);
1639
1640 *pDevice = tu_device_to_handle(device);
1641 return VK_SUCCESS;
1642
1643 fail_timeline_cond:
1644 fail_prepare_perfcntrs_pass_cs:
1645 free(device->perfcntrs_pass_cs_entries);
1646 tu_cs_finish(device->perfcntrs_pass_cs);
1647 fail_perfcntrs_pass_entries_alloc:
1648 free(device->perfcntrs_pass_cs);
1649 fail_perfcntrs_pass_alloc:
1650 tu_DestroyPipelineCache(tu_device_to_handle(device), pc, NULL);
1651 fail_pipeline_cache:
1652 tu_destroy_clear_blit_shaders(device);
1653 fail_global_bo_map:
1654 tu_bo_finish(device, &device->global_bo);
1655 vk_free(&device->vk.alloc, device->bo_idx);
1656 vk_free(&device->vk.alloc, device->bo_list);
1657 fail_global_bo:
1658 ir3_compiler_destroy(device->compiler);
1659
1660 fail_queues:
1661 for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {
1662 for (unsigned q = 0; q < device->queue_count[i]; q++)
1663 tu_queue_finish(&device->queues[i][q]);
1664 if (device->queue_count[i])
1665 vk_free(&device->vk.alloc, device->queues[i]);
1666 }
1667
1668 vk_device_finish(&device->vk);
1669 vk_free(&device->vk.alloc, device);
1670 return result;
1671 }
1672
1673 VKAPI_ATTR void VKAPI_CALL
tu_DestroyDevice(VkDevice _device,const VkAllocationCallbacks * pAllocator)1674 tu_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator)
1675 {
1676 TU_FROM_HANDLE(tu_device, device, _device);
1677
1678 if (!device)
1679 return;
1680
1681 u_trace_context_fini(&device->trace_context);
1682
1683 for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {
1684 for (unsigned q = 0; q < device->queue_count[i]; q++)
1685 tu_queue_finish(&device->queues[i][q]);
1686 if (device->queue_count[i])
1687 vk_free(&device->vk.alloc, device->queues[i]);
1688 }
1689
1690 for (unsigned i = 0; i < ARRAY_SIZE(device->scratch_bos); i++) {
1691 if (device->scratch_bos[i].initialized)
1692 tu_bo_finish(device, &device->scratch_bos[i].bo);
1693 }
1694
1695 tu_destroy_clear_blit_shaders(device);
1696
1697 ir3_compiler_destroy(device->compiler);
1698
1699 VkPipelineCache pc = tu_pipeline_cache_to_handle(device->mem_cache);
1700 tu_DestroyPipelineCache(tu_device_to_handle(device), pc, NULL);
1701
1702 if (device->perfcntrs_pass_cs) {
1703 free(device->perfcntrs_pass_cs_entries);
1704 tu_cs_finish(device->perfcntrs_pass_cs);
1705 free(device->perfcntrs_pass_cs);
1706 }
1707
1708 pthread_cond_destroy(&device->timeline_cond);
1709 vk_free(&device->vk.alloc, device->bo_list);
1710 vk_free(&device->vk.alloc, device->bo_idx);
1711 vk_device_finish(&device->vk);
1712 vk_free(&device->vk.alloc, device);
1713 }
1714
1715 VkResult
_tu_device_set_lost(struct tu_device * device,const char * msg,...)1716 _tu_device_set_lost(struct tu_device *device,
1717 const char *msg, ...)
1718 {
1719 /* Set the flag indicating that waits should return in finite time even
1720 * after device loss.
1721 */
1722 p_atomic_inc(&device->_lost);
1723
1724 /* TODO: Report the log message through VkDebugReportCallbackEXT instead */
1725 va_list ap;
1726 va_start(ap, msg);
1727 mesa_loge_v(msg, ap);
1728 va_end(ap);
1729
1730 if (env_var_as_boolean("TU_ABORT_ON_DEVICE_LOSS", false))
1731 abort();
1732
1733 return VK_ERROR_DEVICE_LOST;
1734 }
1735
1736 VkResult
tu_get_scratch_bo(struct tu_device * dev,uint64_t size,struct tu_bo ** bo)1737 tu_get_scratch_bo(struct tu_device *dev, uint64_t size, struct tu_bo **bo)
1738 {
1739 unsigned size_log2 = MAX2(util_logbase2_ceil64(size), MIN_SCRATCH_BO_SIZE_LOG2);
1740 unsigned index = size_log2 - MIN_SCRATCH_BO_SIZE_LOG2;
1741 assert(index < ARRAY_SIZE(dev->scratch_bos));
1742
1743 for (unsigned i = index; i < ARRAY_SIZE(dev->scratch_bos); i++) {
1744 if (p_atomic_read(&dev->scratch_bos[i].initialized)) {
1745 /* Fast path: just return the already-allocated BO. */
1746 *bo = &dev->scratch_bos[i].bo;
1747 return VK_SUCCESS;
1748 }
1749 }
1750
1751 /* Slow path: actually allocate the BO. We take a lock because the process
1752 * of allocating it is slow, and we don't want to block the CPU while it
1753 * finishes.
1754 */
1755 mtx_lock(&dev->scratch_bos[index].construct_mtx);
1756
1757 /* Another thread may have allocated it already while we were waiting on
1758 * the lock. We need to check this in order to avoid double-allocating.
1759 */
1760 if (dev->scratch_bos[index].initialized) {
1761 mtx_unlock(&dev->scratch_bos[index].construct_mtx);
1762 *bo = &dev->scratch_bos[index].bo;
1763 return VK_SUCCESS;
1764 }
1765
1766 unsigned bo_size = 1ull << size_log2;
1767 VkResult result = tu_bo_init_new(dev, &dev->scratch_bos[index].bo, bo_size,
1768 TU_BO_ALLOC_NO_FLAGS);
1769 if (result != VK_SUCCESS) {
1770 mtx_unlock(&dev->scratch_bos[index].construct_mtx);
1771 return result;
1772 }
1773
1774 p_atomic_set(&dev->scratch_bos[index].initialized, true);
1775
1776 mtx_unlock(&dev->scratch_bos[index].construct_mtx);
1777
1778 *bo = &dev->scratch_bos[index].bo;
1779 return VK_SUCCESS;
1780 }
1781
1782 VKAPI_ATTR VkResult VKAPI_CALL
tu_EnumerateInstanceLayerProperties(uint32_t * pPropertyCount,VkLayerProperties * pProperties)1783 tu_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
1784 VkLayerProperties *pProperties)
1785 {
1786 *pPropertyCount = 0;
1787 return VK_SUCCESS;
1788 }
1789
1790 VKAPI_ATTR VkResult VKAPI_CALL
tu_QueueWaitIdle(VkQueue _queue)1791 tu_QueueWaitIdle(VkQueue _queue)
1792 {
1793 TU_FROM_HANDLE(tu_queue, queue, _queue);
1794
1795 if (tu_device_is_lost(queue->device))
1796 return VK_ERROR_DEVICE_LOST;
1797
1798 if (queue->fence < 0)
1799 return VK_SUCCESS;
1800
1801 pthread_mutex_lock(&queue->device->submit_mutex);
1802
1803 do {
1804 tu_device_submit_deferred_locked(queue->device);
1805
1806 if (list_is_empty(&queue->queued_submits))
1807 break;
1808
1809 pthread_cond_wait(&queue->device->timeline_cond,
1810 &queue->device->submit_mutex);
1811 } while (!list_is_empty(&queue->queued_submits));
1812
1813 pthread_mutex_unlock(&queue->device->submit_mutex);
1814
1815 struct pollfd fds = { .fd = queue->fence, .events = POLLIN };
1816 int ret;
1817 do {
1818 ret = poll(&fds, 1, -1);
1819 } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
1820
1821 /* TODO: otherwise set device lost ? */
1822 assert(ret == 1 && !(fds.revents & (POLLERR | POLLNVAL)));
1823
1824 close(queue->fence);
1825 queue->fence = -1;
1826 return VK_SUCCESS;
1827 }
1828
1829 VKAPI_ATTR VkResult VKAPI_CALL
tu_EnumerateInstanceExtensionProperties(const char * pLayerName,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)1830 tu_EnumerateInstanceExtensionProperties(const char *pLayerName,
1831 uint32_t *pPropertyCount,
1832 VkExtensionProperties *pProperties)
1833 {
1834 if (pLayerName)
1835 return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1836
1837 return vk_enumerate_instance_extension_properties(
1838 &tu_instance_extensions_supported, pPropertyCount, pProperties);
1839 }
1840
1841 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
tu_GetInstanceProcAddr(VkInstance _instance,const char * pName)1842 tu_GetInstanceProcAddr(VkInstance _instance, const char *pName)
1843 {
1844 TU_FROM_HANDLE(tu_instance, instance, _instance);
1845 return vk_instance_get_proc_addr(&instance->vk,
1846 &tu_instance_entrypoints,
1847 pName);
1848 }
1849
1850 /* The loader wants us to expose a second GetInstanceProcAddr function
1851 * to work around certain LD_PRELOAD issues seen in apps.
1852 */
1853 PUBLIC
1854 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1855 vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName);
1856
1857 PUBLIC
1858 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
vk_icdGetInstanceProcAddr(VkInstance instance,const char * pName)1859 vk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)
1860 {
1861 return tu_GetInstanceProcAddr(instance, pName);
1862 }
1863
1864 VKAPI_ATTR VkResult VKAPI_CALL
tu_AllocateMemory(VkDevice _device,const VkMemoryAllocateInfo * pAllocateInfo,const VkAllocationCallbacks * pAllocator,VkDeviceMemory * pMem)1865 tu_AllocateMemory(VkDevice _device,
1866 const VkMemoryAllocateInfo *pAllocateInfo,
1867 const VkAllocationCallbacks *pAllocator,
1868 VkDeviceMemory *pMem)
1869 {
1870 TU_FROM_HANDLE(tu_device, device, _device);
1871 struct tu_device_memory *mem;
1872 VkResult result;
1873
1874 assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
1875
1876 if (pAllocateInfo->allocationSize == 0) {
1877 /* Apparently, this is allowed */
1878 *pMem = VK_NULL_HANDLE;
1879 return VK_SUCCESS;
1880 }
1881
1882 struct tu_memory_heap *mem_heap = &device->physical_device->heap;
1883 uint64_t mem_heap_used = p_atomic_read(&mem_heap->used);
1884 if (mem_heap_used > mem_heap->size)
1885 return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
1886
1887 mem = vk_object_alloc(&device->vk, pAllocator, sizeof(*mem),
1888 VK_OBJECT_TYPE_DEVICE_MEMORY);
1889 if (mem == NULL)
1890 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1891
1892 const VkImportMemoryFdInfoKHR *fd_info =
1893 vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
1894 if (fd_info && !fd_info->handleType)
1895 fd_info = NULL;
1896
1897 if (fd_info) {
1898 assert(fd_info->handleType ==
1899 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
1900 fd_info->handleType ==
1901 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
1902
1903 /*
1904 * TODO Importing the same fd twice gives us the same handle without
1905 * reference counting. We need to maintain a per-instance handle-to-bo
1906 * table and add reference count to tu_bo.
1907 */
1908 result = tu_bo_init_dmabuf(device, &mem->bo,
1909 pAllocateInfo->allocationSize, fd_info->fd);
1910 if (result == VK_SUCCESS) {
1911 /* take ownership and close the fd */
1912 close(fd_info->fd);
1913 }
1914 } else {
1915 result =
1916 tu_bo_init_new(device, &mem->bo, pAllocateInfo->allocationSize,
1917 TU_BO_ALLOC_NO_FLAGS);
1918 }
1919
1920
1921 if (result == VK_SUCCESS) {
1922 mem_heap_used = p_atomic_add_return(&mem_heap->used, mem->bo.size);
1923 if (mem_heap_used > mem_heap->size) {
1924 p_atomic_add(&mem_heap->used, -mem->bo.size);
1925 tu_bo_finish(device, &mem->bo);
1926 result = vk_errorf(device, VK_ERROR_OUT_OF_DEVICE_MEMORY,
1927 "Out of heap memory");
1928 }
1929 }
1930
1931 if (result != VK_SUCCESS) {
1932 vk_object_free(&device->vk, pAllocator, mem);
1933 return result;
1934 }
1935
1936 *pMem = tu_device_memory_to_handle(mem);
1937
1938 return VK_SUCCESS;
1939 }
1940
1941 VKAPI_ATTR void VKAPI_CALL
tu_FreeMemory(VkDevice _device,VkDeviceMemory _mem,const VkAllocationCallbacks * pAllocator)1942 tu_FreeMemory(VkDevice _device,
1943 VkDeviceMemory _mem,
1944 const VkAllocationCallbacks *pAllocator)
1945 {
1946 TU_FROM_HANDLE(tu_device, device, _device);
1947 TU_FROM_HANDLE(tu_device_memory, mem, _mem);
1948
1949 if (mem == NULL)
1950 return;
1951
1952 p_atomic_add(&device->physical_device->heap.used, -mem->bo.size);
1953 tu_bo_finish(device, &mem->bo);
1954 vk_object_free(&device->vk, pAllocator, mem);
1955 }
1956
1957 VKAPI_ATTR VkResult VKAPI_CALL
tu_MapMemory(VkDevice _device,VkDeviceMemory _memory,VkDeviceSize offset,VkDeviceSize size,VkMemoryMapFlags flags,void ** ppData)1958 tu_MapMemory(VkDevice _device,
1959 VkDeviceMemory _memory,
1960 VkDeviceSize offset,
1961 VkDeviceSize size,
1962 VkMemoryMapFlags flags,
1963 void **ppData)
1964 {
1965 TU_FROM_HANDLE(tu_device, device, _device);
1966 TU_FROM_HANDLE(tu_device_memory, mem, _memory);
1967 VkResult result;
1968
1969 if (mem == NULL) {
1970 *ppData = NULL;
1971 return VK_SUCCESS;
1972 }
1973
1974 if (!mem->bo.map) {
1975 result = tu_bo_map(device, &mem->bo);
1976 if (result != VK_SUCCESS)
1977 return result;
1978 }
1979
1980 *ppData = mem->bo.map + offset;
1981 return VK_SUCCESS;
1982 }
1983
1984 VKAPI_ATTR void VKAPI_CALL
tu_UnmapMemory(VkDevice _device,VkDeviceMemory _memory)1985 tu_UnmapMemory(VkDevice _device, VkDeviceMemory _memory)
1986 {
1987 /* TODO: unmap here instead of waiting for FreeMemory */
1988 }
1989
1990 VKAPI_ATTR VkResult VKAPI_CALL
tu_FlushMappedMemoryRanges(VkDevice _device,uint32_t memoryRangeCount,const VkMappedMemoryRange * pMemoryRanges)1991 tu_FlushMappedMemoryRanges(VkDevice _device,
1992 uint32_t memoryRangeCount,
1993 const VkMappedMemoryRange *pMemoryRanges)
1994 {
1995 return VK_SUCCESS;
1996 }
1997
1998 VKAPI_ATTR VkResult VKAPI_CALL
tu_InvalidateMappedMemoryRanges(VkDevice _device,uint32_t memoryRangeCount,const VkMappedMemoryRange * pMemoryRanges)1999 tu_InvalidateMappedMemoryRanges(VkDevice _device,
2000 uint32_t memoryRangeCount,
2001 const VkMappedMemoryRange *pMemoryRanges)
2002 {
2003 return VK_SUCCESS;
2004 }
2005
2006 VKAPI_ATTR void VKAPI_CALL
tu_GetBufferMemoryRequirements2(VkDevice device,const VkBufferMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)2007 tu_GetBufferMemoryRequirements2(
2008 VkDevice device,
2009 const VkBufferMemoryRequirementsInfo2 *pInfo,
2010 VkMemoryRequirements2 *pMemoryRequirements)
2011 {
2012 TU_FROM_HANDLE(tu_buffer, buffer, pInfo->buffer);
2013
2014 pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
2015 .memoryTypeBits = 1,
2016 .alignment = 64,
2017 .size = MAX2(align64(buffer->size, 64), buffer->size),
2018 };
2019
2020 vk_foreach_struct(ext, pMemoryRequirements->pNext) {
2021 switch (ext->sType) {
2022 case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
2023 VkMemoryDedicatedRequirements *req =
2024 (VkMemoryDedicatedRequirements *) ext;
2025 req->requiresDedicatedAllocation = false;
2026 req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;
2027 break;
2028 }
2029 default:
2030 break;
2031 }
2032 }
2033 }
2034
2035 VKAPI_ATTR void VKAPI_CALL
tu_GetImageMemoryRequirements2(VkDevice device,const VkImageMemoryRequirementsInfo2 * pInfo,VkMemoryRequirements2 * pMemoryRequirements)2036 tu_GetImageMemoryRequirements2(VkDevice device,
2037 const VkImageMemoryRequirementsInfo2 *pInfo,
2038 VkMemoryRequirements2 *pMemoryRequirements)
2039 {
2040 TU_FROM_HANDLE(tu_image, image, pInfo->image);
2041
2042 pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
2043 .memoryTypeBits = 1,
2044 .alignment = image->layout[0].base_align,
2045 .size = image->total_size
2046 };
2047
2048 vk_foreach_struct(ext, pMemoryRequirements->pNext) {
2049 switch (ext->sType) {
2050 case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
2051 VkMemoryDedicatedRequirements *req =
2052 (VkMemoryDedicatedRequirements *) ext;
2053 req->requiresDedicatedAllocation = image->shareable;
2054 req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;
2055 break;
2056 }
2057 default:
2058 break;
2059 }
2060 }
2061 }
2062
2063 VKAPI_ATTR void VKAPI_CALL
tu_GetImageSparseMemoryRequirements2(VkDevice device,const VkImageSparseMemoryRequirementsInfo2 * pInfo,uint32_t * pSparseMemoryRequirementCount,VkSparseImageMemoryRequirements2 * pSparseMemoryRequirements)2064 tu_GetImageSparseMemoryRequirements2(
2065 VkDevice device,
2066 const VkImageSparseMemoryRequirementsInfo2 *pInfo,
2067 uint32_t *pSparseMemoryRequirementCount,
2068 VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
2069 {
2070 tu_stub();
2071 }
2072
2073 VKAPI_ATTR void VKAPI_CALL
tu_GetDeviceMemoryCommitment(VkDevice device,VkDeviceMemory memory,VkDeviceSize * pCommittedMemoryInBytes)2074 tu_GetDeviceMemoryCommitment(VkDevice device,
2075 VkDeviceMemory memory,
2076 VkDeviceSize *pCommittedMemoryInBytes)
2077 {
2078 *pCommittedMemoryInBytes = 0;
2079 }
2080
2081 VKAPI_ATTR VkResult VKAPI_CALL
tu_BindBufferMemory2(VkDevice device,uint32_t bindInfoCount,const VkBindBufferMemoryInfo * pBindInfos)2082 tu_BindBufferMemory2(VkDevice device,
2083 uint32_t bindInfoCount,
2084 const VkBindBufferMemoryInfo *pBindInfos)
2085 {
2086 for (uint32_t i = 0; i < bindInfoCount; ++i) {
2087 TU_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);
2088 TU_FROM_HANDLE(tu_buffer, buffer, pBindInfos[i].buffer);
2089
2090 if (mem) {
2091 buffer->bo = &mem->bo;
2092 buffer->bo_offset = pBindInfos[i].memoryOffset;
2093 } else {
2094 buffer->bo = NULL;
2095 }
2096 }
2097 return VK_SUCCESS;
2098 }
2099
2100 VKAPI_ATTR VkResult VKAPI_CALL
tu_BindImageMemory2(VkDevice device,uint32_t bindInfoCount,const VkBindImageMemoryInfo * pBindInfos)2101 tu_BindImageMemory2(VkDevice device,
2102 uint32_t bindInfoCount,
2103 const VkBindImageMemoryInfo *pBindInfos)
2104 {
2105 for (uint32_t i = 0; i < bindInfoCount; ++i) {
2106 TU_FROM_HANDLE(tu_image, image, pBindInfos[i].image);
2107 TU_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);
2108
2109 if (mem) {
2110 image->bo = &mem->bo;
2111 image->bo_offset = pBindInfos[i].memoryOffset;
2112 } else {
2113 image->bo = NULL;
2114 image->bo_offset = 0;
2115 }
2116 }
2117
2118 return VK_SUCCESS;
2119 }
2120
2121 VKAPI_ATTR VkResult VKAPI_CALL
tu_QueueBindSparse(VkQueue _queue,uint32_t bindInfoCount,const VkBindSparseInfo * pBindInfo,VkFence _fence)2122 tu_QueueBindSparse(VkQueue _queue,
2123 uint32_t bindInfoCount,
2124 const VkBindSparseInfo *pBindInfo,
2125 VkFence _fence)
2126 {
2127 return VK_SUCCESS;
2128 }
2129
2130 VKAPI_ATTR VkResult VKAPI_CALL
tu_CreateEvent(VkDevice _device,const VkEventCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkEvent * pEvent)2131 tu_CreateEvent(VkDevice _device,
2132 const VkEventCreateInfo *pCreateInfo,
2133 const VkAllocationCallbacks *pAllocator,
2134 VkEvent *pEvent)
2135 {
2136 TU_FROM_HANDLE(tu_device, device, _device);
2137
2138 struct tu_event *event =
2139 vk_object_alloc(&device->vk, pAllocator, sizeof(*event),
2140 VK_OBJECT_TYPE_EVENT);
2141 if (!event)
2142 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2143
2144 VkResult result = tu_bo_init_new(device, &event->bo, 0x1000,
2145 TU_BO_ALLOC_NO_FLAGS);
2146 if (result != VK_SUCCESS)
2147 goto fail_alloc;
2148
2149 result = tu_bo_map(device, &event->bo);
2150 if (result != VK_SUCCESS)
2151 goto fail_map;
2152
2153 *pEvent = tu_event_to_handle(event);
2154
2155 return VK_SUCCESS;
2156
2157 fail_map:
2158 tu_bo_finish(device, &event->bo);
2159 fail_alloc:
2160 vk_object_free(&device->vk, pAllocator, event);
2161 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2162 }
2163
2164 VKAPI_ATTR void VKAPI_CALL
tu_DestroyEvent(VkDevice _device,VkEvent _event,const VkAllocationCallbacks * pAllocator)2165 tu_DestroyEvent(VkDevice _device,
2166 VkEvent _event,
2167 const VkAllocationCallbacks *pAllocator)
2168 {
2169 TU_FROM_HANDLE(tu_device, device, _device);
2170 TU_FROM_HANDLE(tu_event, event, _event);
2171
2172 if (!event)
2173 return;
2174
2175 tu_bo_finish(device, &event->bo);
2176 vk_object_free(&device->vk, pAllocator, event);
2177 }
2178
2179 VKAPI_ATTR VkResult VKAPI_CALL
tu_GetEventStatus(VkDevice _device,VkEvent _event)2180 tu_GetEventStatus(VkDevice _device, VkEvent _event)
2181 {
2182 TU_FROM_HANDLE(tu_event, event, _event);
2183
2184 if (*(uint64_t*) event->bo.map == 1)
2185 return VK_EVENT_SET;
2186 return VK_EVENT_RESET;
2187 }
2188
2189 VKAPI_ATTR VkResult VKAPI_CALL
tu_SetEvent(VkDevice _device,VkEvent _event)2190 tu_SetEvent(VkDevice _device, VkEvent _event)
2191 {
2192 TU_FROM_HANDLE(tu_event, event, _event);
2193 *(uint64_t*) event->bo.map = 1;
2194
2195 return VK_SUCCESS;
2196 }
2197
2198 VKAPI_ATTR VkResult VKAPI_CALL
tu_ResetEvent(VkDevice _device,VkEvent _event)2199 tu_ResetEvent(VkDevice _device, VkEvent _event)
2200 {
2201 TU_FROM_HANDLE(tu_event, event, _event);
2202 *(uint64_t*) event->bo.map = 0;
2203
2204 return VK_SUCCESS;
2205 }
2206
2207 VKAPI_ATTR VkResult VKAPI_CALL
tu_CreateBuffer(VkDevice _device,const VkBufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkBuffer * pBuffer)2208 tu_CreateBuffer(VkDevice _device,
2209 const VkBufferCreateInfo *pCreateInfo,
2210 const VkAllocationCallbacks *pAllocator,
2211 VkBuffer *pBuffer)
2212 {
2213 TU_FROM_HANDLE(tu_device, device, _device);
2214 struct tu_buffer *buffer;
2215
2216 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
2217
2218 buffer = vk_object_alloc(&device->vk, pAllocator, sizeof(*buffer),
2219 VK_OBJECT_TYPE_BUFFER);
2220 if (buffer == NULL)
2221 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2222
2223 buffer->size = pCreateInfo->size;
2224 buffer->usage = pCreateInfo->usage;
2225 buffer->flags = pCreateInfo->flags;
2226
2227 *pBuffer = tu_buffer_to_handle(buffer);
2228
2229 return VK_SUCCESS;
2230 }
2231
2232 VKAPI_ATTR void VKAPI_CALL
tu_DestroyBuffer(VkDevice _device,VkBuffer _buffer,const VkAllocationCallbacks * pAllocator)2233 tu_DestroyBuffer(VkDevice _device,
2234 VkBuffer _buffer,
2235 const VkAllocationCallbacks *pAllocator)
2236 {
2237 TU_FROM_HANDLE(tu_device, device, _device);
2238 TU_FROM_HANDLE(tu_buffer, buffer, _buffer);
2239
2240 if (!buffer)
2241 return;
2242
2243 vk_object_free(&device->vk, pAllocator, buffer);
2244 }
2245
2246 VKAPI_ATTR VkResult VKAPI_CALL
tu_CreateFramebuffer(VkDevice _device,const VkFramebufferCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkFramebuffer * pFramebuffer)2247 tu_CreateFramebuffer(VkDevice _device,
2248 const VkFramebufferCreateInfo *pCreateInfo,
2249 const VkAllocationCallbacks *pAllocator,
2250 VkFramebuffer *pFramebuffer)
2251 {
2252 TU_FROM_HANDLE(tu_device, device, _device);
2253 TU_FROM_HANDLE(tu_render_pass, pass, pCreateInfo->renderPass);
2254 struct tu_framebuffer *framebuffer;
2255
2256 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
2257
2258 bool imageless = pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
2259
2260 size_t size = sizeof(*framebuffer);
2261 if (!imageless)
2262 size += sizeof(struct tu_attachment_info) * pCreateInfo->attachmentCount;
2263 framebuffer = vk_object_alloc(&device->vk, pAllocator, size,
2264 VK_OBJECT_TYPE_FRAMEBUFFER);
2265 if (framebuffer == NULL)
2266 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2267
2268 framebuffer->attachment_count = pCreateInfo->attachmentCount;
2269 framebuffer->width = pCreateInfo->width;
2270 framebuffer->height = pCreateInfo->height;
2271 framebuffer->layers = pCreateInfo->layers;
2272
2273 if (!imageless) {
2274 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
2275 VkImageView _iview = pCreateInfo->pAttachments[i];
2276 struct tu_image_view *iview = tu_image_view_from_handle(_iview);
2277 framebuffer->attachments[i].attachment = iview;
2278 }
2279 }
2280
2281 tu_framebuffer_tiling_config(framebuffer, device, pass);
2282
2283 *pFramebuffer = tu_framebuffer_to_handle(framebuffer);
2284 return VK_SUCCESS;
2285 }
2286
2287 VKAPI_ATTR void VKAPI_CALL
tu_DestroyFramebuffer(VkDevice _device,VkFramebuffer _fb,const VkAllocationCallbacks * pAllocator)2288 tu_DestroyFramebuffer(VkDevice _device,
2289 VkFramebuffer _fb,
2290 const VkAllocationCallbacks *pAllocator)
2291 {
2292 TU_FROM_HANDLE(tu_device, device, _device);
2293 TU_FROM_HANDLE(tu_framebuffer, fb, _fb);
2294
2295 if (!fb)
2296 return;
2297
2298 vk_object_free(&device->vk, pAllocator, fb);
2299 }
2300
2301 static void
tu_init_sampler(struct tu_device * device,struct tu_sampler * sampler,const VkSamplerCreateInfo * pCreateInfo)2302 tu_init_sampler(struct tu_device *device,
2303 struct tu_sampler *sampler,
2304 const VkSamplerCreateInfo *pCreateInfo)
2305 {
2306 const struct VkSamplerReductionModeCreateInfo *reduction =
2307 vk_find_struct_const(pCreateInfo->pNext, SAMPLER_REDUCTION_MODE_CREATE_INFO);
2308 const struct VkSamplerYcbcrConversionInfo *ycbcr_conversion =
2309 vk_find_struct_const(pCreateInfo->pNext, SAMPLER_YCBCR_CONVERSION_INFO);
2310 const VkSamplerCustomBorderColorCreateInfoEXT *custom_border_color =
2311 vk_find_struct_const(pCreateInfo->pNext, SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT);
2312 /* for non-custom border colors, the VK enum is translated directly to an offset in
2313 * the border color buffer. custom border colors are located immediately after the
2314 * builtin colors, and thus an offset of TU_BORDER_COLOR_BUILTIN is added.
2315 */
2316 uint32_t border_color = (unsigned) pCreateInfo->borderColor;
2317 if (pCreateInfo->borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT ||
2318 pCreateInfo->borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT) {
2319 mtx_lock(&device->mutex);
2320 border_color = BITSET_FFS(device->custom_border_color);
2321 BITSET_CLEAR(device->custom_border_color, border_color);
2322 mtx_unlock(&device->mutex);
2323 tu6_pack_border_color(device->global_bo.map + gb_offset(bcolor[border_color]),
2324 &custom_border_color->customBorderColor,
2325 pCreateInfo->borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT);
2326 border_color += TU_BORDER_COLOR_BUILTIN;
2327 }
2328
2329 unsigned aniso = pCreateInfo->anisotropyEnable ?
2330 util_last_bit(MIN2((uint32_t)pCreateInfo->maxAnisotropy >> 1, 8)) : 0;
2331 bool miplinear = (pCreateInfo->mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR);
2332 float min_lod = CLAMP(pCreateInfo->minLod, 0.0f, 4095.0f / 256.0f);
2333 float max_lod = CLAMP(pCreateInfo->maxLod, 0.0f, 4095.0f / 256.0f);
2334
2335 sampler->descriptor[0] =
2336 COND(miplinear, A6XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR) |
2337 A6XX_TEX_SAMP_0_XY_MAG(tu6_tex_filter(pCreateInfo->magFilter, aniso)) |
2338 A6XX_TEX_SAMP_0_XY_MIN(tu6_tex_filter(pCreateInfo->minFilter, aniso)) |
2339 A6XX_TEX_SAMP_0_ANISO(aniso) |
2340 A6XX_TEX_SAMP_0_WRAP_S(tu6_tex_wrap(pCreateInfo->addressModeU)) |
2341 A6XX_TEX_SAMP_0_WRAP_T(tu6_tex_wrap(pCreateInfo->addressModeV)) |
2342 A6XX_TEX_SAMP_0_WRAP_R(tu6_tex_wrap(pCreateInfo->addressModeW)) |
2343 A6XX_TEX_SAMP_0_LOD_BIAS(pCreateInfo->mipLodBias);
2344 sampler->descriptor[1] =
2345 /* COND(!cso->seamless_cube_map, A6XX_TEX_SAMP_1_CUBEMAPSEAMLESSFILTOFF) | */
2346 COND(pCreateInfo->unnormalizedCoordinates, A6XX_TEX_SAMP_1_UNNORM_COORDS) |
2347 A6XX_TEX_SAMP_1_MIN_LOD(min_lod) |
2348 A6XX_TEX_SAMP_1_MAX_LOD(max_lod) |
2349 COND(pCreateInfo->compareEnable,
2350 A6XX_TEX_SAMP_1_COMPARE_FUNC(tu6_compare_func(pCreateInfo->compareOp)));
2351 sampler->descriptor[2] = A6XX_TEX_SAMP_2_BCOLOR(border_color);
2352 sampler->descriptor[3] = 0;
2353
2354 if (reduction) {
2355 sampler->descriptor[2] |= A6XX_TEX_SAMP_2_REDUCTION_MODE(
2356 tu6_reduction_mode(reduction->reductionMode));
2357 }
2358
2359 sampler->ycbcr_sampler = ycbcr_conversion ?
2360 tu_sampler_ycbcr_conversion_from_handle(ycbcr_conversion->conversion) : NULL;
2361
2362 if (sampler->ycbcr_sampler &&
2363 sampler->ycbcr_sampler->chroma_filter == VK_FILTER_LINEAR) {
2364 sampler->descriptor[2] |= A6XX_TEX_SAMP_2_CHROMA_LINEAR;
2365 }
2366
2367 /* TODO:
2368 * A6XX_TEX_SAMP_1_MIPFILTER_LINEAR_FAR disables mipmapping, but vk has no NONE mipfilter?
2369 */
2370 }
2371
2372 VKAPI_ATTR VkResult VKAPI_CALL
tu_CreateSampler(VkDevice _device,const VkSamplerCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSampler * pSampler)2373 tu_CreateSampler(VkDevice _device,
2374 const VkSamplerCreateInfo *pCreateInfo,
2375 const VkAllocationCallbacks *pAllocator,
2376 VkSampler *pSampler)
2377 {
2378 TU_FROM_HANDLE(tu_device, device, _device);
2379 struct tu_sampler *sampler;
2380
2381 assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
2382
2383 sampler = vk_object_alloc(&device->vk, pAllocator, sizeof(*sampler),
2384 VK_OBJECT_TYPE_SAMPLER);
2385 if (!sampler)
2386 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2387
2388 tu_init_sampler(device, sampler, pCreateInfo);
2389 *pSampler = tu_sampler_to_handle(sampler);
2390
2391 return VK_SUCCESS;
2392 }
2393
2394 VKAPI_ATTR void VKAPI_CALL
tu_DestroySampler(VkDevice _device,VkSampler _sampler,const VkAllocationCallbacks * pAllocator)2395 tu_DestroySampler(VkDevice _device,
2396 VkSampler _sampler,
2397 const VkAllocationCallbacks *pAllocator)
2398 {
2399 TU_FROM_HANDLE(tu_device, device, _device);
2400 TU_FROM_HANDLE(tu_sampler, sampler, _sampler);
2401 uint32_t border_color;
2402
2403 if (!sampler)
2404 return;
2405
2406 border_color = (sampler->descriptor[2] & A6XX_TEX_SAMP_2_BCOLOR__MASK) >> A6XX_TEX_SAMP_2_BCOLOR__SHIFT;
2407 if (border_color >= TU_BORDER_COLOR_BUILTIN) {
2408 border_color -= TU_BORDER_COLOR_BUILTIN;
2409 /* if the sampler had a custom border color, free it. TODO: no lock */
2410 mtx_lock(&device->mutex);
2411 assert(!BITSET_TEST(device->custom_border_color, border_color));
2412 BITSET_SET(device->custom_border_color, border_color);
2413 mtx_unlock(&device->mutex);
2414 }
2415
2416 vk_object_free(&device->vk, pAllocator, sampler);
2417 }
2418
2419 /* vk_icd.h does not declare this function, so we declare it here to
2420 * suppress Wmissing-prototypes.
2421 */
2422 PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
2423 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion);
2424
2425 PUBLIC VKAPI_ATTR VkResult VKAPI_CALL
vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t * pSupportedVersion)2426 vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion)
2427 {
2428 /* For the full details on loader interface versioning, see
2429 * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
2430 * What follows is a condensed summary, to help you navigate the large and
2431 * confusing official doc.
2432 *
2433 * - Loader interface v0 is incompatible with later versions. We don't
2434 * support it.
2435 *
2436 * - In loader interface v1:
2437 * - The first ICD entrypoint called by the loader is
2438 * vk_icdGetInstanceProcAddr(). The ICD must statically expose this
2439 * entrypoint.
2440 * - The ICD must statically expose no other Vulkan symbol unless it
2441 * is linked with -Bsymbolic.
2442 * - Each dispatchable Vulkan handle created by the ICD must be
2443 * a pointer to a struct whose first member is VK_LOADER_DATA. The
2444 * ICD must initialize VK_LOADER_DATA.loadMagic to
2445 * ICD_LOADER_MAGIC.
2446 * - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
2447 * vkDestroySurfaceKHR(). The ICD must be capable of working with
2448 * such loader-managed surfaces.
2449 *
2450 * - Loader interface v2 differs from v1 in:
2451 * - The first ICD entrypoint called by the loader is
2452 * vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
2453 * statically expose this entrypoint.
2454 *
2455 * - Loader interface v3 differs from v2 in:
2456 * - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
2457 * vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
2458 * because the loader no longer does so.
2459 */
2460 *pSupportedVersion = MIN2(*pSupportedVersion, 3u);
2461 return VK_SUCCESS;
2462 }
2463
2464 VKAPI_ATTR VkResult VKAPI_CALL
tu_GetMemoryFdKHR(VkDevice _device,const VkMemoryGetFdInfoKHR * pGetFdInfo,int * pFd)2465 tu_GetMemoryFdKHR(VkDevice _device,
2466 const VkMemoryGetFdInfoKHR *pGetFdInfo,
2467 int *pFd)
2468 {
2469 TU_FROM_HANDLE(tu_device, device, _device);
2470 TU_FROM_HANDLE(tu_device_memory, memory, pGetFdInfo->memory);
2471
2472 assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
2473
2474 /* At the moment, we support only the below handle types. */
2475 assert(pGetFdInfo->handleType ==
2476 VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
2477 pGetFdInfo->handleType ==
2478 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
2479
2480 int prime_fd = tu_bo_export_dmabuf(device, &memory->bo);
2481 if (prime_fd < 0)
2482 return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
2483
2484 *pFd = prime_fd;
2485 return VK_SUCCESS;
2486 }
2487
2488 VKAPI_ATTR VkResult VKAPI_CALL
tu_GetMemoryFdPropertiesKHR(VkDevice _device,VkExternalMemoryHandleTypeFlagBits handleType,int fd,VkMemoryFdPropertiesKHR * pMemoryFdProperties)2489 tu_GetMemoryFdPropertiesKHR(VkDevice _device,
2490 VkExternalMemoryHandleTypeFlagBits handleType,
2491 int fd,
2492 VkMemoryFdPropertiesKHR *pMemoryFdProperties)
2493 {
2494 assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
2495 pMemoryFdProperties->memoryTypeBits = 1;
2496 return VK_SUCCESS;
2497 }
2498
2499 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceExternalFenceProperties(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceExternalFenceInfo * pExternalFenceInfo,VkExternalFenceProperties * pExternalFenceProperties)2500 tu_GetPhysicalDeviceExternalFenceProperties(
2501 VkPhysicalDevice physicalDevice,
2502 const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
2503 VkExternalFenceProperties *pExternalFenceProperties)
2504 {
2505 pExternalFenceProperties->exportFromImportedHandleTypes = 0;
2506 pExternalFenceProperties->compatibleHandleTypes = 0;
2507 pExternalFenceProperties->externalFenceFeatures = 0;
2508 }
2509
2510 VKAPI_ATTR void VKAPI_CALL
tu_GetDeviceGroupPeerMemoryFeatures(VkDevice device,uint32_t heapIndex,uint32_t localDeviceIndex,uint32_t remoteDeviceIndex,VkPeerMemoryFeatureFlags * pPeerMemoryFeatures)2511 tu_GetDeviceGroupPeerMemoryFeatures(
2512 VkDevice device,
2513 uint32_t heapIndex,
2514 uint32_t localDeviceIndex,
2515 uint32_t remoteDeviceIndex,
2516 VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)
2517 {
2518 assert(localDeviceIndex == remoteDeviceIndex);
2519
2520 *pPeerMemoryFeatures = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT |
2521 VK_PEER_MEMORY_FEATURE_COPY_DST_BIT |
2522 VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT |
2523 VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT;
2524 }
2525
2526 VKAPI_ATTR void VKAPI_CALL
tu_GetPhysicalDeviceMultisamplePropertiesEXT(VkPhysicalDevice physicalDevice,VkSampleCountFlagBits samples,VkMultisamplePropertiesEXT * pMultisampleProperties)2527 tu_GetPhysicalDeviceMultisamplePropertiesEXT(
2528 VkPhysicalDevice physicalDevice,
2529 VkSampleCountFlagBits samples,
2530 VkMultisamplePropertiesEXT* pMultisampleProperties)
2531 {
2532 TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
2533
2534 if (samples <= VK_SAMPLE_COUNT_4_BIT && pdevice->vk.supported_extensions.EXT_sample_locations)
2535 pMultisampleProperties->maxSampleLocationGridSize = (VkExtent2D){ 1, 1 };
2536 else
2537 pMultisampleProperties->maxSampleLocationGridSize = (VkExtent2D){ 0, 0 };
2538 }
2539