1361fc4cbSmaya/*
2361fc4cbSmaya * Copyright © 2016 Red Hat.
3361fc4cbSmaya * Copyright © 2016 Bas Nieuwenhuizen
4361fc4cbSmaya *
5361fc4cbSmaya * based in part on anv driver which is:
6361fc4cbSmaya * Copyright © 2015 Intel Corporation
7361fc4cbSmaya *
8361fc4cbSmaya * Permission is hereby granted, free of charge, to any person obtaining a
9361fc4cbSmaya * copy of this software and associated documentation files (the "Software"),
10361fc4cbSmaya * to deal in the Software without restriction, including without limitation
11361fc4cbSmaya * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12361fc4cbSmaya * and/or sell copies of the Software, and to permit persons to whom the
13361fc4cbSmaya * Software is furnished to do so, subject to the following conditions:
14361fc4cbSmaya *
15361fc4cbSmaya * The above copyright notice and this permission notice (including the next
16361fc4cbSmaya * paragraph) shall be included in all copies or substantial portions of the
17361fc4cbSmaya * Software.
18361fc4cbSmaya *
19361fc4cbSmaya * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20361fc4cbSmaya * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21361fc4cbSmaya * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22361fc4cbSmaya * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23361fc4cbSmaya * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24361fc4cbSmaya * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25361fc4cbSmaya * DEALINGS IN THE SOFTWARE.
26361fc4cbSmaya */
27361fc4cbSmaya
28361fc4cbSmaya#include "tu_private.h"
297ec681f3Smrg#include "tu_cs.h"
307ec681f3Smrg#include "git_sha1.h"
31361fc4cbSmaya
32361fc4cbSmaya#include <fcntl.h>
337ec681f3Smrg#include <poll.h>
34361fc4cbSmaya#include <stdbool.h>
35361fc4cbSmaya#include <string.h>
36361fc4cbSmaya#include <sys/sysinfo.h>
37361fc4cbSmaya#include <unistd.h>
38361fc4cbSmaya
39361fc4cbSmaya#include "util/debug.h"
40361fc4cbSmaya#include "util/disk_cache.h"
417ec681f3Smrg#include "util/u_atomic.h"
42361fc4cbSmaya#include "vk_format.h"
43361fc4cbSmaya#include "vk_util.h"
44361fc4cbSmaya
457ec681f3Smrg/* for fd_get_driver/device_uuid() */
467ec681f3Smrg#include "freedreno/common/freedreno_uuid.h"
477ec681f3Smrg
487ec681f3Smrg#if defined(VK_USE_PLATFORM_WAYLAND_KHR) || \
497ec681f3Smrg     defined(VK_USE_PLATFORM_XCB_KHR) || \
507ec681f3Smrg     defined(VK_USE_PLATFORM_XLIB_KHR) || \
517ec681f3Smrg     defined(VK_USE_PLATFORM_DISPLAY_KHR)
527ec681f3Smrg#define TU_HAS_SURFACE 1
537ec681f3Smrg#else
547ec681f3Smrg#define TU_HAS_SURFACE 0
557ec681f3Smrg#endif
567ec681f3Smrg
57361fc4cbSmaya
58361fc4cbSmayastatic int
59361fc4cbSmayatu_device_get_cache_uuid(uint16_t family, void *uuid)
60361fc4cbSmaya{
61361fc4cbSmaya   uint32_t mesa_timestamp;
62361fc4cbSmaya   uint16_t f = family;
63361fc4cbSmaya   memset(uuid, 0, VK_UUID_SIZE);
64361fc4cbSmaya   if (!disk_cache_get_function_timestamp(tu_device_get_cache_uuid,
65361fc4cbSmaya                                          &mesa_timestamp))
66361fc4cbSmaya      return -1;
67361fc4cbSmaya
68361fc4cbSmaya   memcpy(uuid, &mesa_timestamp, 4);
69361fc4cbSmaya   memcpy((char *) uuid + 4, &f, 2);
70361fc4cbSmaya   snprintf((char *) uuid + 6, VK_UUID_SIZE - 10, "tu");
71361fc4cbSmaya   return 0;
72361fc4cbSmaya}
73361fc4cbSmaya
747ec681f3Smrg#define TU_API_VERSION VK_MAKE_VERSION(1, 1, VK_HEADER_VERSION)
757ec681f3Smrg
767ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
777ec681f3Smrgtu_EnumerateInstanceVersion(uint32_t *pApiVersion)
787ec681f3Smrg{
797ec681f3Smrg    *pApiVersion = TU_API_VERSION;
807ec681f3Smrg    return VK_SUCCESS;
817ec681f3Smrg}
827ec681f3Smrg
837ec681f3Smrgstatic const struct vk_instance_extension_table tu_instance_extensions_supported = {
847ec681f3Smrg   .KHR_device_group_creation           = true,
857ec681f3Smrg   .KHR_external_fence_capabilities     = true,
867ec681f3Smrg   .KHR_external_memory_capabilities    = true,
877ec681f3Smrg   .KHR_external_semaphore_capabilities = true,
887ec681f3Smrg   .KHR_get_physical_device_properties2 = true,
897ec681f3Smrg   .KHR_surface                         = TU_HAS_SURFACE,
907ec681f3Smrg   .KHR_get_surface_capabilities2       = TU_HAS_SURFACE,
917ec681f3Smrg   .EXT_debug_report                    = true,
927ec681f3Smrg#ifdef VK_USE_PLATFORM_WAYLAND_KHR
937ec681f3Smrg   .KHR_wayland_surface                 = true,
947ec681f3Smrg#endif
957ec681f3Smrg#ifdef VK_USE_PLATFORM_XCB_KHR
967ec681f3Smrg   .KHR_xcb_surface                     = true,
977ec681f3Smrg#endif
987ec681f3Smrg#ifdef VK_USE_PLATFORM_XLIB_KHR
997ec681f3Smrg   .KHR_xlib_surface                    = true,
1007ec681f3Smrg#endif
1017ec681f3Smrg#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
1027ec681f3Smrg   .EXT_acquire_xlib_display            = true,
1037ec681f3Smrg#endif
1047ec681f3Smrg#ifdef VK_USE_PLATFORM_DISPLAY_KHR
1057ec681f3Smrg   .KHR_display                         = true,
1067ec681f3Smrg   .KHR_get_display_properties2         = true,
1077ec681f3Smrg   .EXT_direct_mode_display             = true,
1087ec681f3Smrg   .EXT_display_surface_counter         = true,
1097ec681f3Smrg#endif
1107ec681f3Smrg};
111361fc4cbSmaya
112361fc4cbSmayastatic void
1137ec681f3Smrgget_device_extensions(const struct tu_physical_device *device,
1147ec681f3Smrg                      struct vk_device_extension_table *ext)
1157ec681f3Smrg{
1167ec681f3Smrg   *ext = (struct vk_device_extension_table) {
1177ec681f3Smrg      .KHR_16bit_storage = device->info->a6xx.storage_16bit,
1187ec681f3Smrg      .KHR_bind_memory2 = true,
1197ec681f3Smrg      .KHR_create_renderpass2 = true,
1207ec681f3Smrg      .KHR_dedicated_allocation = true,
1217ec681f3Smrg      .KHR_depth_stencil_resolve = true,
1227ec681f3Smrg      .KHR_descriptor_update_template = true,
1237ec681f3Smrg      .KHR_device_group = true,
1247ec681f3Smrg      .KHR_draw_indirect_count = true,
1257ec681f3Smrg      .KHR_external_fence = true,
1267ec681f3Smrg      .KHR_external_fence_fd = true,
1277ec681f3Smrg      .KHR_external_memory = true,
1287ec681f3Smrg      .KHR_external_memory_fd = true,
1297ec681f3Smrg      .KHR_external_semaphore = true,
1307ec681f3Smrg      .KHR_external_semaphore_fd = true,
1317ec681f3Smrg      .KHR_get_memory_requirements2 = true,
1327ec681f3Smrg      .KHR_imageless_framebuffer = true,
1337ec681f3Smrg      .KHR_incremental_present = TU_HAS_SURFACE,
1347ec681f3Smrg      .KHR_image_format_list = true,
1357ec681f3Smrg      .KHR_maintenance1 = true,
1367ec681f3Smrg      .KHR_maintenance2 = true,
1377ec681f3Smrg      .KHR_maintenance3 = true,
1387ec681f3Smrg      .KHR_multiview = true,
1397ec681f3Smrg      .KHR_performance_query = device->instance->debug_flags & TU_DEBUG_PERFC,
1407ec681f3Smrg      .KHR_pipeline_executable_properties = true,
1417ec681f3Smrg      .KHR_push_descriptor = true,
1427ec681f3Smrg      .KHR_relaxed_block_layout = true,
1437ec681f3Smrg      .KHR_sampler_mirror_clamp_to_edge = true,
1447ec681f3Smrg      .KHR_sampler_ycbcr_conversion = true,
1457ec681f3Smrg      .KHR_shader_draw_parameters = true,
1467ec681f3Smrg      .KHR_shader_float_controls = true,
1477ec681f3Smrg      .KHR_shader_float16_int8 = true,
1487ec681f3Smrg      .KHR_shader_subgroup_extended_types = true,
1497ec681f3Smrg      .KHR_shader_terminate_invocation = true,
1507ec681f3Smrg      .KHR_spirv_1_4 = true,
1517ec681f3Smrg      .KHR_storage_buffer_storage_class = true,
1527ec681f3Smrg      .KHR_swapchain = TU_HAS_SURFACE,
1537ec681f3Smrg      .KHR_uniform_buffer_standard_layout = true,
1547ec681f3Smrg      .KHR_variable_pointers = true,
1557ec681f3Smrg      .KHR_vulkan_memory_model = true,
1567ec681f3Smrg#ifndef TU_USE_KGSL
1577ec681f3Smrg      .KHR_timeline_semaphore = true,
1587ec681f3Smrg#endif
1597ec681f3Smrg#ifdef VK_USE_PLATFORM_DISPLAY_KHR
1607ec681f3Smrg      /* This extension is supported by common code across drivers, but it is
1617ec681f3Smrg       * missing some core functionality and fails
1627ec681f3Smrg       * dEQP-VK.wsi.display_control.register_device_event. Once some variant of
1637ec681f3Smrg       * https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12305 lands,
1647ec681f3Smrg       * then we can re-enable it.
1657ec681f3Smrg       */
1667ec681f3Smrg      /* .EXT_display_control = true, */
1677ec681f3Smrg#endif
1687ec681f3Smrg      .EXT_external_memory_dma_buf = true,
1697ec681f3Smrg      .EXT_image_drm_format_modifier = true,
1707ec681f3Smrg      .EXT_sample_locations = device->info->a6xx.has_sample_locations,
1717ec681f3Smrg      .EXT_sampler_filter_minmax = true,
1727ec681f3Smrg      .EXT_transform_feedback = true,
1737ec681f3Smrg      .EXT_4444_formats = true,
1747ec681f3Smrg      .EXT_conditional_rendering = true,
1757ec681f3Smrg      .EXT_custom_border_color = true,
1767ec681f3Smrg      .EXT_depth_clip_enable = true,
1777ec681f3Smrg      .EXT_descriptor_indexing = true,
1787ec681f3Smrg      .EXT_extended_dynamic_state = true,
1797ec681f3Smrg      .EXT_extended_dynamic_state2 = true,
1807ec681f3Smrg      .EXT_filter_cubic = device->info->a6xx.has_tex_filter_cubic,
1817ec681f3Smrg      .EXT_host_query_reset = true,
1827ec681f3Smrg      .EXT_index_type_uint8 = true,
1837ec681f3Smrg      .EXT_memory_budget = true,
1847ec681f3Smrg      .EXT_private_data = true,
1857ec681f3Smrg      .EXT_robustness2 = true,
1867ec681f3Smrg      .EXT_scalar_block_layout = true,
1877ec681f3Smrg      .EXT_separate_stencil_usage = true,
1887ec681f3Smrg      .EXT_shader_demote_to_helper_invocation = true,
1897ec681f3Smrg      .EXT_shader_stencil_export = true,
1907ec681f3Smrg      .EXT_shader_viewport_index_layer = true,
1917ec681f3Smrg      .EXT_vertex_attribute_divisor = true,
1927ec681f3Smrg      .EXT_provoking_vertex = true,
1937ec681f3Smrg      .EXT_line_rasterization = true,
1947ec681f3Smrg#ifdef ANDROID
1957ec681f3Smrg      .ANDROID_native_buffer = true,
1967ec681f3Smrg#endif
1977ec681f3Smrg      .IMG_filter_cubic = device->info->a6xx.has_tex_filter_cubic,
1987ec681f3Smrg      .VALVE_mutable_descriptor_type = true,
199361fc4cbSmaya   };
200361fc4cbSmaya}
201361fc4cbSmaya
202361fc4cbSmayaVkResult
203361fc4cbSmayatu_physical_device_init(struct tu_physical_device *device,
2047ec681f3Smrg                        struct tu_instance *instance)
205361fc4cbSmaya{
206361fc4cbSmaya   VkResult result = VK_SUCCESS;
207361fc4cbSmaya
2087ec681f3Smrg   const char *fd_name = fd_dev_name(&device->dev_id);
2097ec681f3Smrg   if (strncmp(fd_name, "FD", 2) == 0) {
2107ec681f3Smrg      device->name = vk_asprintf(&instance->vk.alloc,
2117ec681f3Smrg                                 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE,
2127ec681f3Smrg                                 "Turnip Adreno (TM) %s", &fd_name[2]);
2137ec681f3Smrg   } else {
2147ec681f3Smrg      device->name = vk_strdup(&instance->vk.alloc, fd_name,
2157ec681f3Smrg                               VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
216361fc4cbSmaya
217361fc4cbSmaya   }
2187ec681f3Smrg   if (!device->name) {
2197ec681f3Smrg      return vk_startup_errorf(instance, VK_ERROR_OUT_OF_HOST_MEMORY,
2207ec681f3Smrg                               "device name alloc fail");
221361fc4cbSmaya   }
222361fc4cbSmaya
2237ec681f3Smrg   const struct fd_dev_info *info = fd_dev_info(&device->dev_id);
2247ec681f3Smrg   if (!info) {
2257ec681f3Smrg      result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
2267ec681f3Smrg                                 "device %s is unsupported", device->name);
2277ec681f3Smrg      goto fail_free_name;
228361fc4cbSmaya   }
2297ec681f3Smrg   switch (fd_dev_gen(&device->dev_id)) {
2307ec681f3Smrg   case 6:
2317ec681f3Smrg      device->info = info;
2327ec681f3Smrg      device->ccu_offset_bypass = device->info->num_ccu * A6XX_CCU_DEPTH_SIZE;
2337ec681f3Smrg      device->ccu_offset_gmem = (device->gmem_size -
2347ec681f3Smrg         device->info->num_ccu * A6XX_CCU_GMEM_COLOR_SIZE);
235361fc4cbSmaya      break;
236361fc4cbSmaya   default:
2377ec681f3Smrg      result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
2387ec681f3Smrg                                 "device %s is unsupported", device->name);
2397ec681f3Smrg      goto fail_free_name;
240361fc4cbSmaya   }
2417ec681f3Smrg   if (tu_device_get_cache_uuid(fd_dev_gpu_id(&device->dev_id), device->cache_uuid)) {
2427ec681f3Smrg      result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
2437ec681f3Smrg                                 "cannot generate UUID");
2447ec681f3Smrg      goto fail_free_name;
245361fc4cbSmaya   }
246361fc4cbSmaya
247361fc4cbSmaya   /* The gpu id is already embedded in the uuid so we just pass "tu"
248361fc4cbSmaya    * when creating the cache.
249361fc4cbSmaya    */
250361fc4cbSmaya   char buf[VK_UUID_SIZE * 2 + 1];
251361fc4cbSmaya   disk_cache_format_hex_id(buf, device->cache_uuid, VK_UUID_SIZE * 2);
252361fc4cbSmaya   device->disk_cache = disk_cache_create(device->name, buf, 0);
253361fc4cbSmaya
2547ec681f3Smrg   vk_warn_non_conformant_implementation("tu");
255361fc4cbSmaya
2567ec681f3Smrg   fd_get_driver_uuid(device->driver_uuid);
2577ec681f3Smrg   fd_get_device_uuid(device->device_uuid, &device->dev_id);
258361fc4cbSmaya
2597ec681f3Smrg   struct vk_device_extension_table supported_extensions;
2607ec681f3Smrg   get_device_extensions(device, &supported_extensions);
261361fc4cbSmaya
2627ec681f3Smrg   struct vk_physical_device_dispatch_table dispatch_table;
2637ec681f3Smrg   vk_physical_device_dispatch_table_from_entrypoints(
2647ec681f3Smrg      &dispatch_table, &tu_physical_device_entrypoints, true);
2657ec681f3Smrg   vk_physical_device_dispatch_table_from_entrypoints(
2667ec681f3Smrg      &dispatch_table, &wsi_physical_device_entrypoints, false);
2677ec681f3Smrg
2687ec681f3Smrg   result = vk_physical_device_init(&device->vk, &instance->vk,
2697ec681f3Smrg                                    &supported_extensions,
2707ec681f3Smrg                                    &dispatch_table);
2717ec681f3Smrg   if (result != VK_SUCCESS)
2727ec681f3Smrg      goto fail_free_cache;
273361fc4cbSmaya
2747ec681f3Smrg#if TU_HAS_SURFACE
275361fc4cbSmaya   result = tu_wsi_init(device);
276361fc4cbSmaya   if (result != VK_SUCCESS) {
2777ec681f3Smrg      vk_startup_errorf(instance, result, "WSI init failure");
2787ec681f3Smrg      vk_physical_device_finish(&device->vk);
2797ec681f3Smrg      goto fail_free_cache;
280361fc4cbSmaya   }
2817ec681f3Smrg#endif
282361fc4cbSmaya
283361fc4cbSmaya   return VK_SUCCESS;
284361fc4cbSmaya
2857ec681f3Smrgfail_free_cache:
2867ec681f3Smrg   disk_cache_destroy(device->disk_cache);
2877ec681f3Smrgfail_free_name:
2887ec681f3Smrg   vk_free(&instance->vk.alloc, (void *)device->name);
289361fc4cbSmaya   return result;
290361fc4cbSmaya}
291361fc4cbSmaya
292361fc4cbSmayastatic void
293361fc4cbSmayatu_physical_device_finish(struct tu_physical_device *device)
294361fc4cbSmaya{
2957ec681f3Smrg#if TU_HAS_SURFACE
296361fc4cbSmaya   tu_wsi_finish(device);
2977ec681f3Smrg#endif
298361fc4cbSmaya
299361fc4cbSmaya   disk_cache_destroy(device->disk_cache);
300361fc4cbSmaya   close(device->local_fd);
301361fc4cbSmaya   if (device->master_fd != -1)
302361fc4cbSmaya      close(device->master_fd);
303361fc4cbSmaya
3047ec681f3Smrg   vk_free(&device->instance->vk.alloc, (void *)device->name);
305361fc4cbSmaya
3067ec681f3Smrg   vk_physical_device_finish(&device->vk);
307361fc4cbSmaya}
308361fc4cbSmaya
309361fc4cbSmayastatic const struct debug_control tu_debug_options[] = {
310361fc4cbSmaya   { "startup", TU_DEBUG_STARTUP },
311361fc4cbSmaya   { "nir", TU_DEBUG_NIR },
3127ec681f3Smrg   { "nobin", TU_DEBUG_NOBIN },
3137ec681f3Smrg   { "sysmem", TU_DEBUG_SYSMEM },
3147ec681f3Smrg   { "forcebin", TU_DEBUG_FORCEBIN },
3157ec681f3Smrg   { "noubwc", TU_DEBUG_NOUBWC },
3167ec681f3Smrg   { "nomultipos", TU_DEBUG_NOMULTIPOS },
3177ec681f3Smrg   { "nolrz", TU_DEBUG_NOLRZ },
3187ec681f3Smrg   { "perfc", TU_DEBUG_PERFC },
3197ec681f3Smrg   { "flushall", TU_DEBUG_FLUSHALL },
3207ec681f3Smrg   { "syncdraw", TU_DEBUG_SYNCDRAW },
321361fc4cbSmaya   { NULL, 0 }
322361fc4cbSmaya};
323361fc4cbSmaya
324361fc4cbSmayaconst char *
325361fc4cbSmayatu_get_debug_option_name(int id)
326361fc4cbSmaya{
327361fc4cbSmaya   assert(id < ARRAY_SIZE(tu_debug_options) - 1);
328361fc4cbSmaya   return tu_debug_options[id].string;
329361fc4cbSmaya}
330361fc4cbSmaya
3317ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
332361fc4cbSmayatu_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
333361fc4cbSmaya                  const VkAllocationCallbacks *pAllocator,
334361fc4cbSmaya                  VkInstance *pInstance)
335361fc4cbSmaya{
336361fc4cbSmaya   struct tu_instance *instance;
337361fc4cbSmaya   VkResult result;
338361fc4cbSmaya
339361fc4cbSmaya   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
340361fc4cbSmaya
3417ec681f3Smrg   if (pAllocator == NULL)
3427ec681f3Smrg      pAllocator = vk_default_allocator();
3437ec681f3Smrg
3447ec681f3Smrg   instance = vk_zalloc(pAllocator, sizeof(*instance), 8,
3457ec681f3Smrg                        VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
346361fc4cbSmaya
347361fc4cbSmaya   if (!instance)
348361fc4cbSmaya      return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY);
349361fc4cbSmaya
3507ec681f3Smrg   struct vk_instance_dispatch_table dispatch_table;
3517ec681f3Smrg   vk_instance_dispatch_table_from_entrypoints(
3527ec681f3Smrg      &dispatch_table, &tu_instance_entrypoints, true);
3537ec681f3Smrg   vk_instance_dispatch_table_from_entrypoints(
3547ec681f3Smrg      &dispatch_table, &wsi_instance_entrypoints, false);
355361fc4cbSmaya
3567ec681f3Smrg   result = vk_instance_init(&instance->vk,
3577ec681f3Smrg                             &tu_instance_extensions_supported,
3587ec681f3Smrg                             &dispatch_table,
3597ec681f3Smrg                             pCreateInfo, pAllocator);
3607ec681f3Smrg   if (result != VK_SUCCESS) {
3617ec681f3Smrg      vk_free(pAllocator, instance);
3627ec681f3Smrg      return vk_error(NULL, result);
3637ec681f3Smrg   }
364361fc4cbSmaya
365361fc4cbSmaya   instance->physical_device_count = -1;
366361fc4cbSmaya
367361fc4cbSmaya   instance->debug_flags =
368361fc4cbSmaya      parse_debug_string(getenv("TU_DEBUG"), tu_debug_options);
369361fc4cbSmaya
3707ec681f3Smrg#ifdef DEBUG
3717ec681f3Smrg   /* Enable startup debugging by default on debug drivers.  You almost always
3727ec681f3Smrg    * want to see your startup failures in that case, and it's hard to set
3737ec681f3Smrg    * this env var on android.
3747ec681f3Smrg    */
3757ec681f3Smrg   instance->debug_flags |= TU_DEBUG_STARTUP;
3767ec681f3Smrg#endif
377361fc4cbSmaya
3787ec681f3Smrg   if (instance->debug_flags & TU_DEBUG_STARTUP)
3797ec681f3Smrg      mesa_logi("Created an instance");
380361fc4cbSmaya
381361fc4cbSmaya   VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false));
382361fc4cbSmaya
383361fc4cbSmaya   *pInstance = tu_instance_to_handle(instance);
384361fc4cbSmaya
3857ec681f3Smrg#ifdef HAVE_PERFETTO
3867ec681f3Smrg   tu_perfetto_init();
3877ec681f3Smrg#endif
3887ec681f3Smrg
389361fc4cbSmaya   return VK_SUCCESS;
390361fc4cbSmaya}
391361fc4cbSmaya
3927ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
393361fc4cbSmayatu_DestroyInstance(VkInstance _instance,
394361fc4cbSmaya                   const VkAllocationCallbacks *pAllocator)
395361fc4cbSmaya{
396361fc4cbSmaya   TU_FROM_HANDLE(tu_instance, instance, _instance);
397361fc4cbSmaya
398361fc4cbSmaya   if (!instance)
399361fc4cbSmaya      return;
400361fc4cbSmaya
401361fc4cbSmaya   for (int i = 0; i < instance->physical_device_count; ++i) {
402361fc4cbSmaya      tu_physical_device_finish(instance->physical_devices + i);
403361fc4cbSmaya   }
404361fc4cbSmaya
405361fc4cbSmaya   VG(VALGRIND_DESTROY_MEMPOOL(instance));
406361fc4cbSmaya
4077ec681f3Smrg   vk_instance_finish(&instance->vk);
4087ec681f3Smrg   vk_free(&instance->vk.alloc, instance);
409361fc4cbSmaya}
410361fc4cbSmaya
4117ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
412361fc4cbSmayatu_EnumeratePhysicalDevices(VkInstance _instance,
413361fc4cbSmaya                            uint32_t *pPhysicalDeviceCount,
414361fc4cbSmaya                            VkPhysicalDevice *pPhysicalDevices)
415361fc4cbSmaya{
416361fc4cbSmaya   TU_FROM_HANDLE(tu_instance, instance, _instance);
417361fc4cbSmaya   VK_OUTARRAY_MAKE(out, pPhysicalDevices, pPhysicalDeviceCount);
418361fc4cbSmaya
419361fc4cbSmaya   VkResult result;
420361fc4cbSmaya
421361fc4cbSmaya   if (instance->physical_device_count < 0) {
422361fc4cbSmaya      result = tu_enumerate_devices(instance);
423361fc4cbSmaya      if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)
424361fc4cbSmaya         return result;
425361fc4cbSmaya   }
426361fc4cbSmaya
427361fc4cbSmaya   for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
428361fc4cbSmaya      vk_outarray_append(&out, p)
429361fc4cbSmaya      {
430361fc4cbSmaya         *p = tu_physical_device_to_handle(instance->physical_devices + i);
431361fc4cbSmaya      }
432361fc4cbSmaya   }
433361fc4cbSmaya
434361fc4cbSmaya   return vk_outarray_status(&out);
435361fc4cbSmaya}
436361fc4cbSmaya
4377ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
438361fc4cbSmayatu_EnumeratePhysicalDeviceGroups(
439361fc4cbSmaya   VkInstance _instance,
440361fc4cbSmaya   uint32_t *pPhysicalDeviceGroupCount,
441361fc4cbSmaya   VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties)
442361fc4cbSmaya{
443361fc4cbSmaya   TU_FROM_HANDLE(tu_instance, instance, _instance);
444361fc4cbSmaya   VK_OUTARRAY_MAKE(out, pPhysicalDeviceGroupProperties,
445361fc4cbSmaya                    pPhysicalDeviceGroupCount);
446361fc4cbSmaya   VkResult result;
447361fc4cbSmaya
448361fc4cbSmaya   if (instance->physical_device_count < 0) {
449361fc4cbSmaya      result = tu_enumerate_devices(instance);
450361fc4cbSmaya      if (result != VK_SUCCESS && result != VK_ERROR_INCOMPATIBLE_DRIVER)
451361fc4cbSmaya         return result;
452361fc4cbSmaya   }
453361fc4cbSmaya
454361fc4cbSmaya   for (uint32_t i = 0; i < instance->physical_device_count; ++i) {
455361fc4cbSmaya      vk_outarray_append(&out, p)
456361fc4cbSmaya      {
457361fc4cbSmaya         p->physicalDeviceCount = 1;
458361fc4cbSmaya         p->physicalDevices[0] =
459361fc4cbSmaya            tu_physical_device_to_handle(instance->physical_devices + i);
460361fc4cbSmaya         p->subsetAllocation = false;
461361fc4cbSmaya      }
462361fc4cbSmaya   }
463361fc4cbSmaya
464361fc4cbSmaya   return vk_outarray_status(&out);
465361fc4cbSmaya}
466361fc4cbSmaya
4677ec681f3Smrgstatic void
4687ec681f3Smrgtu_get_physical_device_features_1_1(struct tu_physical_device *pdevice,
4697ec681f3Smrg                                    VkPhysicalDeviceVulkan11Features *features)
4707ec681f3Smrg{
4717ec681f3Smrg   features->storageBuffer16BitAccess            = pdevice->info->a6xx.storage_16bit;
4727ec681f3Smrg   features->uniformAndStorageBuffer16BitAccess  = false;
4737ec681f3Smrg   features->storagePushConstant16               = false;
4747ec681f3Smrg   features->storageInputOutput16                = false;
4757ec681f3Smrg   features->multiview                           = true;
4767ec681f3Smrg   features->multiviewGeometryShader             = false;
4777ec681f3Smrg   features->multiviewTessellationShader         = false;
4787ec681f3Smrg   features->variablePointersStorageBuffer       = true;
4797ec681f3Smrg   features->variablePointers                    = true;
4807ec681f3Smrg   features->protectedMemory                     = false;
4817ec681f3Smrg   features->samplerYcbcrConversion              = true;
4827ec681f3Smrg   features->shaderDrawParameters                = true;
4837ec681f3Smrg}
4847ec681f3Smrg
4857ec681f3Smrgstatic void
4867ec681f3Smrgtu_get_physical_device_features_1_2(struct tu_physical_device *pdevice,
4877ec681f3Smrg                                    VkPhysicalDeviceVulkan12Features *features)
4887ec681f3Smrg{
4897ec681f3Smrg   features->samplerMirrorClampToEdge            = true;
4907ec681f3Smrg   features->drawIndirectCount                   = true;
4917ec681f3Smrg   features->storageBuffer8BitAccess             = false;
4927ec681f3Smrg   features->uniformAndStorageBuffer8BitAccess   = false;
4937ec681f3Smrg   features->storagePushConstant8                = false;
4947ec681f3Smrg   features->shaderBufferInt64Atomics            = false;
4957ec681f3Smrg   features->shaderSharedInt64Atomics            = false;
4967ec681f3Smrg   features->shaderFloat16                       = true;
4977ec681f3Smrg   features->shaderInt8                          = false;
4987ec681f3Smrg
4997ec681f3Smrg   features->descriptorIndexing                                 = true;
5007ec681f3Smrg   features->shaderInputAttachmentArrayDynamicIndexing          = false;
5017ec681f3Smrg   features->shaderUniformTexelBufferArrayDynamicIndexing       = true;
5027ec681f3Smrg   features->shaderStorageTexelBufferArrayDynamicIndexing       = true;
5037ec681f3Smrg   features->shaderUniformBufferArrayNonUniformIndexing         = true;
5047ec681f3Smrg   features->shaderSampledImageArrayNonUniformIndexing          = true;
5057ec681f3Smrg   features->shaderStorageBufferArrayNonUniformIndexing         = true;
5067ec681f3Smrg   features->shaderStorageImageArrayNonUniformIndexing          = true;
5077ec681f3Smrg   features->shaderInputAttachmentArrayNonUniformIndexing       = false;
5087ec681f3Smrg   features->shaderUniformTexelBufferArrayNonUniformIndexing    = true;
5097ec681f3Smrg   features->shaderStorageTexelBufferArrayNonUniformIndexing    = true;
5107ec681f3Smrg   features->descriptorBindingUniformBufferUpdateAfterBind      = false;
5117ec681f3Smrg   features->descriptorBindingSampledImageUpdateAfterBind       = true;
5127ec681f3Smrg   features->descriptorBindingStorageImageUpdateAfterBind       = true;
5137ec681f3Smrg   features->descriptorBindingStorageBufferUpdateAfterBind      = true;
5147ec681f3Smrg   features->descriptorBindingUniformTexelBufferUpdateAfterBind = true;
5157ec681f3Smrg   features->descriptorBindingStorageTexelBufferUpdateAfterBind = true;
5167ec681f3Smrg   features->descriptorBindingUpdateUnusedWhilePending          = true;
5177ec681f3Smrg   features->descriptorBindingPartiallyBound                    = true;
5187ec681f3Smrg   features->descriptorBindingVariableDescriptorCount           = true;
5197ec681f3Smrg   features->runtimeDescriptorArray                             = true;
5207ec681f3Smrg
5217ec681f3Smrg   features->samplerFilterMinmax                 = true;
5227ec681f3Smrg   features->scalarBlockLayout                   = true;
5237ec681f3Smrg   features->imagelessFramebuffer                = true;
5247ec681f3Smrg   features->uniformBufferStandardLayout         = true;
5257ec681f3Smrg   features->shaderSubgroupExtendedTypes         = true;
5267ec681f3Smrg   features->separateDepthStencilLayouts         = false;
5277ec681f3Smrg   features->hostQueryReset                      = true;
5287ec681f3Smrg   features->timelineSemaphore                   = true;
5297ec681f3Smrg   features->bufferDeviceAddress                 = false;
5307ec681f3Smrg   features->bufferDeviceAddressCaptureReplay    = false;
5317ec681f3Smrg   features->bufferDeviceAddressMultiDevice      = false;
5327ec681f3Smrg   features->vulkanMemoryModel                   = true;
5337ec681f3Smrg   features->vulkanMemoryModelDeviceScope        = true;
5347ec681f3Smrg   features->vulkanMemoryModelAvailabilityVisibilityChains = true;
5357ec681f3Smrg   features->shaderOutputViewportIndex           = true;
5367ec681f3Smrg   features->shaderOutputLayer                   = true;
5377ec681f3Smrg   features->subgroupBroadcastDynamicId          = false;
5387ec681f3Smrg}
5397ec681f3Smrg
540361fc4cbSmayavoid
5417ec681f3Smrgtu_GetPhysicalDeviceFeatures2(VkPhysicalDevice physicalDevice,
5427ec681f3Smrg                              VkPhysicalDeviceFeatures2 *pFeatures)
5437ec681f3Smrg{
5447ec681f3Smrg   TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
5457ec681f3Smrg
5467ec681f3Smrg   pFeatures->features = (VkPhysicalDeviceFeatures) {
5477ec681f3Smrg      .robustBufferAccess = true,
5487ec681f3Smrg      .fullDrawIndexUint32 = true,
5497ec681f3Smrg      .imageCubeArray = true,
5507ec681f3Smrg      .independentBlend = true,
5517ec681f3Smrg      .geometryShader = true,
5527ec681f3Smrg      .tessellationShader = true,
5537ec681f3Smrg      .sampleRateShading = true,
5547ec681f3Smrg      .dualSrcBlend = true,
5557ec681f3Smrg      .logicOp = true,
5567ec681f3Smrg      .multiDrawIndirect = true,
5577ec681f3Smrg      .drawIndirectFirstInstance = true,
5587ec681f3Smrg      .depthClamp = true,
5597ec681f3Smrg      .depthBiasClamp = true,
5607ec681f3Smrg      .fillModeNonSolid = true,
5617ec681f3Smrg      .depthBounds = true,
562361fc4cbSmaya      .wideLines = false,
5637ec681f3Smrg      .largePoints = true,
5647ec681f3Smrg      .alphaToOne = true,
5657ec681f3Smrg      .multiViewport = true,
5667ec681f3Smrg      .samplerAnisotropy = true,
5677ec681f3Smrg      .textureCompressionETC2 = true,
5687ec681f3Smrg      .textureCompressionASTC_LDR = true,
5697ec681f3Smrg      .textureCompressionBC = true,
5707ec681f3Smrg      .occlusionQueryPrecise = true,
5717ec681f3Smrg      .pipelineStatisticsQuery = true,
5727ec681f3Smrg      .vertexPipelineStoresAndAtomics = true,
5737ec681f3Smrg      .fragmentStoresAndAtomics = true,
574361fc4cbSmaya      .shaderTessellationAndGeometryPointSize = false,
5757ec681f3Smrg      .shaderImageGatherExtended = true,
5767ec681f3Smrg      .shaderStorageImageExtendedFormats = true,
577361fc4cbSmaya      .shaderStorageImageMultisample = false,
5787ec681f3Smrg      .shaderUniformBufferArrayDynamicIndexing = true,
5797ec681f3Smrg      .shaderSampledImageArrayDynamicIndexing = true,
5807ec681f3Smrg      .shaderStorageBufferArrayDynamicIndexing = true,
5817ec681f3Smrg      .shaderStorageImageArrayDynamicIndexing = true,
5827ec681f3Smrg      .shaderStorageImageReadWithoutFormat = true,
5837ec681f3Smrg      .shaderStorageImageWriteWithoutFormat = true,
5847ec681f3Smrg      .shaderClipDistance = true,
5857ec681f3Smrg      .shaderCullDistance = true,
586361fc4cbSmaya      .shaderFloat64 = false,
587361fc4cbSmaya      .shaderInt64 = false,
5887ec681f3Smrg      .shaderInt16 = true,
589361fc4cbSmaya      .sparseBinding = false,
5907ec681f3Smrg      .variableMultisampleRate = true,
5917ec681f3Smrg      .inheritedQueries = true,
592361fc4cbSmaya   };
593361fc4cbSmaya
5947ec681f3Smrg   VkPhysicalDeviceVulkan11Features core_1_1 = {
5957ec681f3Smrg      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
5967ec681f3Smrg   };
5977ec681f3Smrg   tu_get_physical_device_features_1_1(pdevice, &core_1_1);
5987ec681f3Smrg
5997ec681f3Smrg   VkPhysicalDeviceVulkan12Features core_1_2 = {
6007ec681f3Smrg      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
6017ec681f3Smrg   };
6027ec681f3Smrg   tu_get_physical_device_features_1_2(pdevice, &core_1_2);
6037ec681f3Smrg
604361fc4cbSmaya   vk_foreach_struct(ext, pFeatures->pNext)
605361fc4cbSmaya   {
6067ec681f3Smrg      if (vk_get_physical_device_core_1_1_feature_ext(ext, &core_1_1))
6077ec681f3Smrg         continue;
6087ec681f3Smrg      if (vk_get_physical_device_core_1_2_feature_ext(ext, &core_1_2))
6097ec681f3Smrg         continue;
6107ec681f3Smrg
611361fc4cbSmaya      switch (ext->sType) {
6127ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: {
6137ec681f3Smrg         VkPhysicalDeviceConditionalRenderingFeaturesEXT *features =
6147ec681f3Smrg            (VkPhysicalDeviceConditionalRenderingFeaturesEXT *) ext;
6157ec681f3Smrg         features->conditionalRendering = true;
6167ec681f3Smrg         features->inheritedConditionalRendering = true;
617361fc4cbSmaya         break;
618361fc4cbSmaya      }
6197ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: {
6207ec681f3Smrg         VkPhysicalDeviceTransformFeedbackFeaturesEXT *features =
6217ec681f3Smrg            (VkPhysicalDeviceTransformFeedbackFeaturesEXT *) ext;
6227ec681f3Smrg         features->transformFeedback = true;
6237ec681f3Smrg         features->geometryStreams = true;
624361fc4cbSmaya         break;
625361fc4cbSmaya      }
6267ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: {
6277ec681f3Smrg         VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features =
6287ec681f3Smrg            (VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext;
6297ec681f3Smrg         features->indexTypeUint8 = true;
630361fc4cbSmaya         break;
631361fc4cbSmaya      }
6327ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
6337ec681f3Smrg         VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features =
6347ec681f3Smrg            (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext;
6357ec681f3Smrg         features->vertexAttributeInstanceRateDivisor = true;
6367ec681f3Smrg         features->vertexAttributeInstanceRateZeroDivisor = true;
637361fc4cbSmaya         break;
638361fc4cbSmaya      }
6397ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: {
6407ec681f3Smrg         VkPhysicalDevicePrivateDataFeaturesEXT *features =
6417ec681f3Smrg            (VkPhysicalDevicePrivateDataFeaturesEXT *)ext;
6427ec681f3Smrg         features->privateData = true;
643361fc4cbSmaya         break;
644361fc4cbSmaya      }
6457ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: {
6467ec681f3Smrg         VkPhysicalDeviceDepthClipEnableFeaturesEXT *features =
6477ec681f3Smrg            (VkPhysicalDeviceDepthClipEnableFeaturesEXT *)ext;
6487ec681f3Smrg         features->depthClipEnable = true;
649361fc4cbSmaya         break;
650361fc4cbSmaya      }
6517ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: {
6527ec681f3Smrg         VkPhysicalDevice4444FormatsFeaturesEXT *features = (void *)ext;
6537ec681f3Smrg         features->formatA4R4G4B4 = true;
6547ec681f3Smrg         features->formatA4B4G4R4 = true;
655361fc4cbSmaya         break;
656361fc4cbSmaya      }
6577ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {
6587ec681f3Smrg         VkPhysicalDeviceCustomBorderColorFeaturesEXT *features = (void *) ext;
6597ec681f3Smrg         features->customBorderColors = true;
6607ec681f3Smrg         features->customBorderColorWithoutFormat = true;
6617ec681f3Smrg         break;
6627ec681f3Smrg      }
6637ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT: {
6647ec681f3Smrg         VkPhysicalDeviceExtendedDynamicStateFeaturesEXT *features = (void *)ext;
6657ec681f3Smrg         features->extendedDynamicState = true;
6667ec681f3Smrg         break;
6677ec681f3Smrg      }
6687ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT: {
6697ec681f3Smrg         VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *features =
6707ec681f3Smrg            (VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *)ext;
6717ec681f3Smrg         features->extendedDynamicState2 = true;
6727ec681f3Smrg         features->extendedDynamicState2LogicOp = false;
6737ec681f3Smrg         features->extendedDynamicState2PatchControlPoints = false;
6747ec681f3Smrg         break;
6757ec681f3Smrg      }
6767ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: {
6777ec681f3Smrg         VkPhysicalDevicePerformanceQueryFeaturesKHR *feature =
6787ec681f3Smrg            (VkPhysicalDevicePerformanceQueryFeaturesKHR *)ext;
6797ec681f3Smrg         feature->performanceCounterQueryPools = true;
6807ec681f3Smrg         feature->performanceCounterMultipleQueryPools = false;
6817ec681f3Smrg         break;
6827ec681f3Smrg      }
6837ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_EXECUTABLE_PROPERTIES_FEATURES_KHR: {
6847ec681f3Smrg         VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *features =
6857ec681f3Smrg            (VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR *)ext;
6867ec681f3Smrg         features->pipelineExecutableInfo = true;
687361fc4cbSmaya         break;
688361fc4cbSmaya      }
6897ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_FLOAT16_INT8_FEATURES: {
6907ec681f3Smrg         VkPhysicalDeviceShaderFloat16Int8Features *features =
6917ec681f3Smrg            (VkPhysicalDeviceShaderFloat16Int8Features *) ext;
6927ec681f3Smrg         features->shaderFloat16 = true;
6937ec681f3Smrg         features->shaderInt8 = false;
6947ec681f3Smrg         break;
6957ec681f3Smrg      }
6967ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT: {
6977ec681f3Smrg         VkPhysicalDeviceScalarBlockLayoutFeaturesEXT *features = (void *)ext;
6987ec681f3Smrg         features->scalarBlockLayout = true;
6997ec681f3Smrg         break;
7007ec681f3Smrg      }
7017ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT: {
7027ec681f3Smrg         VkPhysicalDeviceRobustness2FeaturesEXT *features = (void *)ext;
7037ec681f3Smrg         features->robustBufferAccess2 = true;
7047ec681f3Smrg         features->robustImageAccess2 = true;
7057ec681f3Smrg         features->nullDescriptor = true;
7067ec681f3Smrg         break;
7077ec681f3Smrg      }
7087ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT: {
7097ec681f3Smrg         VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *features =
7107ec681f3Smrg            (VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT *)ext;
7117ec681f3Smrg         features->shaderDemoteToHelperInvocation = true;
7127ec681f3Smrg         break;
7137ec681f3Smrg      }
7147ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TERMINATE_INVOCATION_FEATURES_KHR: {
7157ec681f3Smrg         VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR *features =
7167ec681f3Smrg            (VkPhysicalDeviceShaderTerminateInvocationFeaturesKHR *)ext;
7177ec681f3Smrg         features->shaderTerminateInvocation = true;
7187ec681f3Smrg         break;
7197ec681f3Smrg      }
7207ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_FEATURES: {
7217ec681f3Smrg         VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *features =
7227ec681f3Smrg            (VkPhysicalDeviceTimelineSemaphoreFeaturesKHR *) ext;
7237ec681f3Smrg         features->timelineSemaphore = true;
7247ec681f3Smrg         break;
7257ec681f3Smrg      }
7267ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: {
7277ec681f3Smrg         VkPhysicalDeviceProvokingVertexFeaturesEXT *features =
7287ec681f3Smrg            (VkPhysicalDeviceProvokingVertexFeaturesEXT *)ext;
7297ec681f3Smrg         features->provokingVertexLast = true;
7307ec681f3Smrg         features->transformFeedbackPreservesProvokingVertex = true;
7317ec681f3Smrg         break;
7327ec681f3Smrg      }
7337ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_VALVE: {
7347ec681f3Smrg         VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE *features =
7357ec681f3Smrg            (VkPhysicalDeviceMutableDescriptorTypeFeaturesVALVE *)ext;
7367ec681f3Smrg         features->mutableDescriptorType = true;
7377ec681f3Smrg         break;
7387ec681f3Smrg      }
7397ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: {
7407ec681f3Smrg         VkPhysicalDeviceLineRasterizationFeaturesEXT *features =
7417ec681f3Smrg            (VkPhysicalDeviceLineRasterizationFeaturesEXT *)ext;
7427ec681f3Smrg         features->rectangularLines = true;
7437ec681f3Smrg         features->bresenhamLines = true;
7447ec681f3Smrg         features->smoothLines = false;
7457ec681f3Smrg         features->stippledRectangularLines = false;
7467ec681f3Smrg         features->stippledBresenhamLines = false;
7477ec681f3Smrg         features->stippledSmoothLines = false;
7487ec681f3Smrg         break;
7497ec681f3Smrg      }
7507ec681f3Smrg
751361fc4cbSmaya      default:
752361fc4cbSmaya         break;
753361fc4cbSmaya      }
754361fc4cbSmaya   }
755361fc4cbSmaya}
756361fc4cbSmaya
7577ec681f3Smrg
7587ec681f3Smrgstatic void
7597ec681f3Smrgtu_get_physical_device_properties_1_1(struct tu_physical_device *pdevice,
7607ec681f3Smrg                                       VkPhysicalDeviceVulkan11Properties *p)
7617ec681f3Smrg{
7627ec681f3Smrg   assert(p->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES);
7637ec681f3Smrg
7647ec681f3Smrg   memcpy(p->deviceUUID, pdevice->device_uuid, VK_UUID_SIZE);
7657ec681f3Smrg   memcpy(p->driverUUID, pdevice->driver_uuid, VK_UUID_SIZE);
7667ec681f3Smrg   memset(p->deviceLUID, 0, VK_LUID_SIZE);
7677ec681f3Smrg   p->deviceNodeMask = 0;
7687ec681f3Smrg   p->deviceLUIDValid = false;
7697ec681f3Smrg
7707ec681f3Smrg   p->subgroupSize = 128;
7717ec681f3Smrg   p->subgroupSupportedStages = VK_SHADER_STAGE_COMPUTE_BIT;
7727ec681f3Smrg   p->subgroupSupportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT |
7737ec681f3Smrg                                    VK_SUBGROUP_FEATURE_VOTE_BIT |
7747ec681f3Smrg                                    VK_SUBGROUP_FEATURE_BALLOT_BIT;
7757ec681f3Smrg   p->subgroupQuadOperationsInAllStages = false;
7767ec681f3Smrg
7777ec681f3Smrg   p->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
7787ec681f3Smrg   p->maxMultiviewViewCount = MAX_VIEWS;
7797ec681f3Smrg   p->maxMultiviewInstanceIndex = INT_MAX;
7807ec681f3Smrg   p->protectedNoFault = false;
7817ec681f3Smrg   /* Make sure everything is addressable by a signed 32-bit int, and
7827ec681f3Smrg    * our largest descriptors are 96 bytes.
7837ec681f3Smrg    */
7847ec681f3Smrg   p->maxPerSetDescriptors = (1ull << 31) / 96;
7857ec681f3Smrg   /* Our buffer size fields allow only this much */
7867ec681f3Smrg   p->maxMemoryAllocationSize = 0xFFFFFFFFull;
7877ec681f3Smrg
7887ec681f3Smrg}
7897ec681f3Smrg
7907ec681f3Smrg
7917ec681f3Smrg/* I have no idea what the maximum size is, but the hardware supports very
7927ec681f3Smrg * large numbers of descriptors (at least 2^16). This limit is based on
7937ec681f3Smrg * CP_LOAD_STATE6, which has a 28-bit field for the DWORD offset, so that
7947ec681f3Smrg * we don't have to think about what to do if that overflows, but really
7957ec681f3Smrg * nothing is likely to get close to this.
7967ec681f3Smrg */
7977ec681f3Smrgstatic const size_t max_descriptor_set_size = (1 << 28) / A6XX_TEX_CONST_DWORDS;
7987ec681f3Smrgstatic const VkSampleCountFlags sample_counts =
7997ec681f3Smrg   VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;
8007ec681f3Smrg
8017ec681f3Smrgstatic void
8027ec681f3Smrgtu_get_physical_device_properties_1_2(struct tu_physical_device *pdevice,
8037ec681f3Smrg                                       VkPhysicalDeviceVulkan12Properties *p)
8047ec681f3Smrg{
8057ec681f3Smrg   assert(p->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES);
8067ec681f3Smrg
8077ec681f3Smrg   p->driverID = VK_DRIVER_ID_MESA_TURNIP;
8087ec681f3Smrg   memset(p->driverName, 0, sizeof(p->driverName));
8097ec681f3Smrg   snprintf(p->driverName, VK_MAX_DRIVER_NAME_SIZE_KHR,
8107ec681f3Smrg            "turnip Mesa driver");
8117ec681f3Smrg   memset(p->driverInfo, 0, sizeof(p->driverInfo));
8127ec681f3Smrg   snprintf(p->driverInfo, VK_MAX_DRIVER_INFO_SIZE_KHR,
8137ec681f3Smrg            "Mesa " PACKAGE_VERSION MESA_GIT_SHA1);
8147ec681f3Smrg   /* XXX: VK 1.2: Need to pass conformance. */
8157ec681f3Smrg   p->conformanceVersion = (VkConformanceVersionKHR) {
8167ec681f3Smrg      .major = 0,
8177ec681f3Smrg      .minor = 0,
8187ec681f3Smrg      .subminor = 0,
8197ec681f3Smrg      .patch = 0,
8207ec681f3Smrg   };
8217ec681f3Smrg
8227ec681f3Smrg   p->denormBehaviorIndependence =
8237ec681f3Smrg      VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;
8247ec681f3Smrg   p->roundingModeIndependence =
8257ec681f3Smrg      VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL;
8267ec681f3Smrg
8277ec681f3Smrg   p->shaderDenormFlushToZeroFloat16         = true;
8287ec681f3Smrg   p->shaderDenormPreserveFloat16            = false;
8297ec681f3Smrg   p->shaderRoundingModeRTEFloat16           = true;
8307ec681f3Smrg   p->shaderRoundingModeRTZFloat16           = false;
8317ec681f3Smrg   p->shaderSignedZeroInfNanPreserveFloat16  = true;
8327ec681f3Smrg
8337ec681f3Smrg   p->shaderDenormFlushToZeroFloat32         = true;
8347ec681f3Smrg   p->shaderDenormPreserveFloat32            = false;
8357ec681f3Smrg   p->shaderRoundingModeRTEFloat32           = true;
8367ec681f3Smrg   p->shaderRoundingModeRTZFloat32           = false;
8377ec681f3Smrg   p->shaderSignedZeroInfNanPreserveFloat32  = true;
8387ec681f3Smrg
8397ec681f3Smrg   p->shaderDenormFlushToZeroFloat64         = false;
8407ec681f3Smrg   p->shaderDenormPreserveFloat64            = false;
8417ec681f3Smrg   p->shaderRoundingModeRTEFloat64           = false;
8427ec681f3Smrg   p->shaderRoundingModeRTZFloat64           = false;
8437ec681f3Smrg   p->shaderSignedZeroInfNanPreserveFloat64  = false;
8447ec681f3Smrg
8457ec681f3Smrg   p->shaderUniformBufferArrayNonUniformIndexingNative   = true;
8467ec681f3Smrg   p->shaderSampledImageArrayNonUniformIndexingNative    = true;
8477ec681f3Smrg   p->shaderStorageBufferArrayNonUniformIndexingNative   = true;
8487ec681f3Smrg   p->shaderStorageImageArrayNonUniformIndexingNative    = true;
8497ec681f3Smrg   p->shaderInputAttachmentArrayNonUniformIndexingNative = false;
8507ec681f3Smrg   p->robustBufferAccessUpdateAfterBind                  = false;
8517ec681f3Smrg   p->quadDivergentImplicitLod                           = false;
8527ec681f3Smrg
8537ec681f3Smrg   p->maxUpdateAfterBindDescriptorsInAllPools            = max_descriptor_set_size;
8547ec681f3Smrg   p->maxPerStageDescriptorUpdateAfterBindSamplers       = max_descriptor_set_size;
8557ec681f3Smrg   p->maxPerStageDescriptorUpdateAfterBindUniformBuffers = max_descriptor_set_size;
8567ec681f3Smrg   p->maxPerStageDescriptorUpdateAfterBindStorageBuffers = max_descriptor_set_size;
8577ec681f3Smrg   p->maxPerStageDescriptorUpdateAfterBindSampledImages  = max_descriptor_set_size;
8587ec681f3Smrg   p->maxPerStageDescriptorUpdateAfterBindStorageImages  = max_descriptor_set_size;
8597ec681f3Smrg   p->maxPerStageDescriptorUpdateAfterBindInputAttachments = max_descriptor_set_size;
8607ec681f3Smrg   p->maxPerStageUpdateAfterBindResources                = max_descriptor_set_size;
8617ec681f3Smrg   p->maxDescriptorSetUpdateAfterBindSamplers            = max_descriptor_set_size;
8627ec681f3Smrg   p->maxDescriptorSetUpdateAfterBindUniformBuffers      = max_descriptor_set_size;
8637ec681f3Smrg   p->maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS;
8647ec681f3Smrg   p->maxDescriptorSetUpdateAfterBindStorageBuffers      = max_descriptor_set_size;
8657ec681f3Smrg   p->maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS;
8667ec681f3Smrg   p->maxDescriptorSetUpdateAfterBindSampledImages       = max_descriptor_set_size;
8677ec681f3Smrg   p->maxDescriptorSetUpdateAfterBindStorageImages       = max_descriptor_set_size;
8687ec681f3Smrg   p->maxDescriptorSetUpdateAfterBindInputAttachments    = max_descriptor_set_size;
8697ec681f3Smrg
8707ec681f3Smrg   p->supportedDepthResolveModes    = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
8717ec681f3Smrg   p->supportedStencilResolveModes  = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT;
8727ec681f3Smrg   p->independentResolveNone  = false;
8737ec681f3Smrg   p->independentResolve      = false;
8747ec681f3Smrg
8757ec681f3Smrg   p->filterMinmaxSingleComponentFormats  = true;
8767ec681f3Smrg   p->filterMinmaxImageComponentMapping   = true;
8777ec681f3Smrg
8787ec681f3Smrg   p->maxTimelineSemaphoreValueDifference = UINT64_MAX;
8797ec681f3Smrg
8807ec681f3Smrg   p->framebufferIntegerColorSampleCounts = sample_counts;
8817ec681f3Smrg}
8827ec681f3Smrg
8837ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
8847ec681f3Smrgtu_GetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice,
8857ec681f3Smrg                                VkPhysicalDeviceProperties2 *pProperties)
886361fc4cbSmaya{
887361fc4cbSmaya   TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
888361fc4cbSmaya
889361fc4cbSmaya   VkPhysicalDeviceLimits limits = {
890361fc4cbSmaya      .maxImageDimension1D = (1 << 14),
891361fc4cbSmaya      .maxImageDimension2D = (1 << 14),
892361fc4cbSmaya      .maxImageDimension3D = (1 << 11),
893361fc4cbSmaya      .maxImageDimensionCube = (1 << 14),
894361fc4cbSmaya      .maxImageArrayLayers = (1 << 11),
895361fc4cbSmaya      .maxTexelBufferElements = 128 * 1024 * 1024,
8967ec681f3Smrg      .maxUniformBufferRange = MAX_UNIFORM_BUFFER_RANGE,
8977ec681f3Smrg      .maxStorageBufferRange = MAX_STORAGE_BUFFER_RANGE,
898361fc4cbSmaya      .maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE,
899361fc4cbSmaya      .maxMemoryAllocationCount = UINT32_MAX,
900361fc4cbSmaya      .maxSamplerAllocationCount = 64 * 1024,
901361fc4cbSmaya      .bufferImageGranularity = 64,          /* A cache line */
9027ec681f3Smrg      .sparseAddressSpaceSize = 0,
903361fc4cbSmaya      .maxBoundDescriptorSets = MAX_SETS,
904361fc4cbSmaya      .maxPerStageDescriptorSamplers = max_descriptor_set_size,
905361fc4cbSmaya      .maxPerStageDescriptorUniformBuffers = max_descriptor_set_size,
906361fc4cbSmaya      .maxPerStageDescriptorStorageBuffers = max_descriptor_set_size,
907361fc4cbSmaya      .maxPerStageDescriptorSampledImages = max_descriptor_set_size,
908361fc4cbSmaya      .maxPerStageDescriptorStorageImages = max_descriptor_set_size,
9097ec681f3Smrg      .maxPerStageDescriptorInputAttachments = MAX_RTS,
910361fc4cbSmaya      .maxPerStageResources = max_descriptor_set_size,
911361fc4cbSmaya      .maxDescriptorSetSamplers = max_descriptor_set_size,
912361fc4cbSmaya      .maxDescriptorSetUniformBuffers = max_descriptor_set_size,
913361fc4cbSmaya      .maxDescriptorSetUniformBuffersDynamic = MAX_DYNAMIC_UNIFORM_BUFFERS,
914361fc4cbSmaya      .maxDescriptorSetStorageBuffers = max_descriptor_set_size,
915361fc4cbSmaya      .maxDescriptorSetStorageBuffersDynamic = MAX_DYNAMIC_STORAGE_BUFFERS,
916361fc4cbSmaya      .maxDescriptorSetSampledImages = max_descriptor_set_size,
917361fc4cbSmaya      .maxDescriptorSetStorageImages = max_descriptor_set_size,
9187ec681f3Smrg      .maxDescriptorSetInputAttachments = MAX_RTS,
919361fc4cbSmaya      .maxVertexInputAttributes = 32,
920361fc4cbSmaya      .maxVertexInputBindings = 32,
9217ec681f3Smrg      .maxVertexInputAttributeOffset = 4095,
922361fc4cbSmaya      .maxVertexInputBindingStride = 2048,
923361fc4cbSmaya      .maxVertexOutputComponents = 128,
924361fc4cbSmaya      .maxTessellationGenerationLevel = 64,
925361fc4cbSmaya      .maxTessellationPatchSize = 32,
926361fc4cbSmaya      .maxTessellationControlPerVertexInputComponents = 128,
927361fc4cbSmaya      .maxTessellationControlPerVertexOutputComponents = 128,
928361fc4cbSmaya      .maxTessellationControlPerPatchOutputComponents = 120,
929361fc4cbSmaya      .maxTessellationControlTotalOutputComponents = 4096,
930361fc4cbSmaya      .maxTessellationEvaluationInputComponents = 128,
931361fc4cbSmaya      .maxTessellationEvaluationOutputComponents = 128,
9327ec681f3Smrg      .maxGeometryShaderInvocations = 32,
933361fc4cbSmaya      .maxGeometryInputComponents = 64,
934361fc4cbSmaya      .maxGeometryOutputComponents = 128,
935361fc4cbSmaya      .maxGeometryOutputVertices = 256,
936361fc4cbSmaya      .maxGeometryTotalOutputComponents = 1024,
9377ec681f3Smrg      .maxFragmentInputComponents = 124,
938361fc4cbSmaya      .maxFragmentOutputAttachments = 8,
939361fc4cbSmaya      .maxFragmentDualSrcAttachments = 1,
940361fc4cbSmaya      .maxFragmentCombinedOutputResources = 8,
941361fc4cbSmaya      .maxComputeSharedMemorySize = 32768,
942361fc4cbSmaya      .maxComputeWorkGroupCount = { 65535, 65535, 65535 },
943361fc4cbSmaya      .maxComputeWorkGroupInvocations = 2048,
9447ec681f3Smrg      .maxComputeWorkGroupSize = { 1024, 1024, 1024 },
9457ec681f3Smrg      .subPixelPrecisionBits = 8,
9467ec681f3Smrg      .subTexelPrecisionBits = 8,
9477ec681f3Smrg      .mipmapPrecisionBits = 8,
948361fc4cbSmaya      .maxDrawIndexedIndexValue = UINT32_MAX,
949361fc4cbSmaya      .maxDrawIndirectCount = UINT32_MAX,
9507ec681f3Smrg      .maxSamplerLodBias = 4095.0 / 256.0, /* [-16, 15.99609375] */
951361fc4cbSmaya      .maxSamplerAnisotropy = 16,
952361fc4cbSmaya      .maxViewports = MAX_VIEWPORTS,
9537ec681f3Smrg      .maxViewportDimensions = { MAX_VIEWPORT_SIZE, MAX_VIEWPORT_SIZE },
954361fc4cbSmaya      .viewportBoundsRange = { INT16_MIN, INT16_MAX },
955361fc4cbSmaya      .viewportSubPixelBits = 8,
956361fc4cbSmaya      .minMemoryMapAlignment = 4096, /* A page */
9577ec681f3Smrg      .minTexelBufferOffsetAlignment = 64,
9587ec681f3Smrg      .minUniformBufferOffsetAlignment = 64,
9597ec681f3Smrg      .minStorageBufferOffsetAlignment = 64,
9607ec681f3Smrg      .minTexelOffset = -16,
9617ec681f3Smrg      .maxTexelOffset = 15,
962361fc4cbSmaya      .minTexelGatherOffset = -32,
963361fc4cbSmaya      .maxTexelGatherOffset = 31,
9647ec681f3Smrg      .minInterpolationOffset = -0.5,
9657ec681f3Smrg      .maxInterpolationOffset = 0.4375,
9667ec681f3Smrg      .subPixelInterpolationOffsetBits = 4,
967361fc4cbSmaya      .maxFramebufferWidth = (1 << 14),
968361fc4cbSmaya      .maxFramebufferHeight = (1 << 14),
969361fc4cbSmaya      .maxFramebufferLayers = (1 << 10),
970361fc4cbSmaya      .framebufferColorSampleCounts = sample_counts,
971361fc4cbSmaya      .framebufferDepthSampleCounts = sample_counts,
972361fc4cbSmaya      .framebufferStencilSampleCounts = sample_counts,
973361fc4cbSmaya      .framebufferNoAttachmentsSampleCounts = sample_counts,
974361fc4cbSmaya      .maxColorAttachments = MAX_RTS,
975361fc4cbSmaya      .sampledImageColorSampleCounts = sample_counts,
976361fc4cbSmaya      .sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT,
977361fc4cbSmaya      .sampledImageDepthSampleCounts = sample_counts,
978361fc4cbSmaya      .sampledImageStencilSampleCounts = sample_counts,
979361fc4cbSmaya      .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT,
980361fc4cbSmaya      .maxSampleMaskWords = 1,
981361fc4cbSmaya      .timestampComputeAndGraphics = true,
9827ec681f3Smrg      .timestampPeriod = 1000000000.0 / 19200000.0, /* CP_ALWAYS_ON_COUNTER is fixed 19.2MHz */
983361fc4cbSmaya      .maxClipDistances = 8,
984361fc4cbSmaya      .maxCullDistances = 8,
985361fc4cbSmaya      .maxCombinedClipAndCullDistances = 8,
9867ec681f3Smrg      .discreteQueuePriorities = 2,
9877ec681f3Smrg      .pointSizeRange = { 1, 4092 },
9887ec681f3Smrg      .lineWidthRange = { 1.0, 1.0 },
9897ec681f3Smrg      .pointSizeGranularity = 	0.0625,
9907ec681f3Smrg      .lineWidthGranularity = 0.0,
9917ec681f3Smrg      .strictLines = true,
992361fc4cbSmaya      .standardSampleLocations = true,
993361fc4cbSmaya      .optimalBufferCopyOffsetAlignment = 128,
994361fc4cbSmaya      .optimalBufferCopyRowPitchAlignment = 128,
995361fc4cbSmaya      .nonCoherentAtomSize = 64,
996361fc4cbSmaya   };
997361fc4cbSmaya
9987ec681f3Smrg   pProperties->properties = (VkPhysicalDeviceProperties) {
9997ec681f3Smrg      .apiVersion = TU_API_VERSION,
1000361fc4cbSmaya      .driverVersion = vk_get_driver_version(),
10017ec681f3Smrg      .vendorID = 0x5143,
10027ec681f3Smrg      .deviceID = pdevice->dev_id.chip_id,
1003361fc4cbSmaya      .deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU,
1004361fc4cbSmaya      .limits = limits,
1005361fc4cbSmaya      .sparseProperties = { 0 },
1006361fc4cbSmaya   };
1007361fc4cbSmaya
10087ec681f3Smrg   strcpy(pProperties->properties.deviceName, pdevice->name);
10097ec681f3Smrg   memcpy(pProperties->properties.pipelineCacheUUID, pdevice->cache_uuid, VK_UUID_SIZE);
1010361fc4cbSmaya
10117ec681f3Smrg   VkPhysicalDeviceVulkan11Properties core_1_1 = {
10127ec681f3Smrg      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES,
10137ec681f3Smrg   };
10147ec681f3Smrg   tu_get_physical_device_properties_1_1(pdevice, &core_1_1);
10157ec681f3Smrg
10167ec681f3Smrg   VkPhysicalDeviceVulkan12Properties core_1_2 = {
10177ec681f3Smrg      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES,
10187ec681f3Smrg   };
10197ec681f3Smrg   tu_get_physical_device_properties_1_2(pdevice, &core_1_2);
1020361fc4cbSmaya
1021361fc4cbSmaya   vk_foreach_struct(ext, pProperties->pNext)
1022361fc4cbSmaya   {
10237ec681f3Smrg      if (vk_get_physical_device_core_1_1_property_ext(ext, &core_1_1))
10247ec681f3Smrg         continue;
10257ec681f3Smrg      if (vk_get_physical_device_core_1_2_property_ext(ext, &core_1_2))
10267ec681f3Smrg         continue;
10277ec681f3Smrg
1028361fc4cbSmaya      switch (ext->sType) {
1029361fc4cbSmaya      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
1030361fc4cbSmaya         VkPhysicalDevicePushDescriptorPropertiesKHR *properties =
1031361fc4cbSmaya            (VkPhysicalDevicePushDescriptorPropertiesKHR *) ext;
1032361fc4cbSmaya         properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS;
1033361fc4cbSmaya         break;
1034361fc4cbSmaya      }
10357ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT: {
10367ec681f3Smrg         VkPhysicalDeviceTransformFeedbackPropertiesEXT *properties =
10377ec681f3Smrg            (VkPhysicalDeviceTransformFeedbackPropertiesEXT *)ext;
10387ec681f3Smrg
10397ec681f3Smrg         properties->maxTransformFeedbackStreams = IR3_MAX_SO_STREAMS;
10407ec681f3Smrg         properties->maxTransformFeedbackBuffers = IR3_MAX_SO_BUFFERS;
10417ec681f3Smrg         properties->maxTransformFeedbackBufferSize = UINT32_MAX;
10427ec681f3Smrg         properties->maxTransformFeedbackStreamDataSize = 512;
10437ec681f3Smrg         properties->maxTransformFeedbackBufferDataSize = 512;
10447ec681f3Smrg         properties->maxTransformFeedbackBufferDataStride = 512;
10457ec681f3Smrg         properties->transformFeedbackQueries = true;
10467ec681f3Smrg         properties->transformFeedbackStreamsLinesTriangles = true;
10477ec681f3Smrg         properties->transformFeedbackRasterizationStreamSelect = true;
10487ec681f3Smrg         properties->transformFeedbackDraw = true;
10497ec681f3Smrg         break;
10507ec681f3Smrg      }
10517ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT: {
10527ec681f3Smrg         VkPhysicalDeviceSampleLocationsPropertiesEXT *properties =
10537ec681f3Smrg            (VkPhysicalDeviceSampleLocationsPropertiesEXT *)ext;
10547ec681f3Smrg         properties->sampleLocationSampleCounts = 0;
10557ec681f3Smrg         if (pdevice->vk.supported_extensions.EXT_sample_locations) {
10567ec681f3Smrg            properties->sampleLocationSampleCounts =
10577ec681f3Smrg               VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_2_BIT | VK_SAMPLE_COUNT_4_BIT;
10587ec681f3Smrg         }
10597ec681f3Smrg         properties->maxSampleLocationGridSize = (VkExtent2D) { 1 , 1 };
10607ec681f3Smrg         properties->sampleLocationCoordinateRange[0] = 0.0f;
10617ec681f3Smrg         properties->sampleLocationCoordinateRange[1] = 0.9375f;
10627ec681f3Smrg         properties->sampleLocationSubPixelBits = 4;
10637ec681f3Smrg         properties->variableSampleLocations = true;
10647ec681f3Smrg         break;
10657ec681f3Smrg      }
10667ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
10677ec681f3Smrg         VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *props =
10687ec681f3Smrg            (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext;
10697ec681f3Smrg         props->maxVertexAttribDivisor = UINT32_MAX;
10707ec681f3Smrg         break;
10717ec681f3Smrg      }
10727ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: {
10737ec681f3Smrg         VkPhysicalDeviceCustomBorderColorPropertiesEXT *props = (void *)ext;
10747ec681f3Smrg         props->maxCustomBorderColorSamplers = TU_BORDER_COLOR_COUNT;
1075361fc4cbSmaya         break;
1076361fc4cbSmaya      }
10777ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_PROPERTIES_KHR: {
10787ec681f3Smrg         VkPhysicalDevicePerformanceQueryPropertiesKHR *properties =
10797ec681f3Smrg            (VkPhysicalDevicePerformanceQueryPropertiesKHR *)ext;
10807ec681f3Smrg         properties->allowCommandBufferQueryCopies = false;
1081361fc4cbSmaya         break;
1082361fc4cbSmaya      }
10837ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_PROPERTIES_EXT: {
10847ec681f3Smrg         VkPhysicalDeviceRobustness2PropertiesEXT *props = (void *)ext;
10857ec681f3Smrg         /* see write_buffer_descriptor() */
10867ec681f3Smrg         props->robustStorageBufferAccessSizeAlignment = 4;
10877ec681f3Smrg         /* see write_ubo_descriptor() */
10887ec681f3Smrg         props->robustUniformBufferAccessSizeAlignment = 16;
1089361fc4cbSmaya         break;
1090361fc4cbSmaya      }
10917ec681f3Smrg
10927ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT: {
10937ec681f3Smrg         VkPhysicalDeviceProvokingVertexPropertiesEXT *properties =
10947ec681f3Smrg            (VkPhysicalDeviceProvokingVertexPropertiesEXT *)ext;
10957ec681f3Smrg         properties->provokingVertexModePerPipeline = true;
10967ec681f3Smrg         properties->transformFeedbackPreservesTriangleFanProvokingVertex = false;
10977ec681f3Smrg         break;
10987ec681f3Smrg      }
10997ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: {
11007ec681f3Smrg         VkPhysicalDeviceLineRasterizationPropertiesEXT *props =
11017ec681f3Smrg            (VkPhysicalDeviceLineRasterizationPropertiesEXT *)ext;
11027ec681f3Smrg         props->lineSubPixelPrecisionBits = 8;
1103361fc4cbSmaya         break;
1104361fc4cbSmaya      }
11057ec681f3Smrg
1106361fc4cbSmaya      default:
1107361fc4cbSmaya         break;
1108361fc4cbSmaya      }
1109361fc4cbSmaya   }
1110361fc4cbSmaya}
1111361fc4cbSmaya
1112361fc4cbSmayastatic const VkQueueFamilyProperties tu_queue_family_properties = {
1113361fc4cbSmaya   .queueFlags =
1114361fc4cbSmaya      VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT,
1115361fc4cbSmaya   .queueCount = 1,
11167ec681f3Smrg   .timestampValidBits = 48,
1117361fc4cbSmaya   .minImageTransferGranularity = { 1, 1, 1 },
1118361fc4cbSmaya};
1119361fc4cbSmaya
11207ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
1121361fc4cbSmayatu_GetPhysicalDeviceQueueFamilyProperties2(
1122361fc4cbSmaya   VkPhysicalDevice physicalDevice,
1123361fc4cbSmaya   uint32_t *pQueueFamilyPropertyCount,
1124361fc4cbSmaya   VkQueueFamilyProperties2 *pQueueFamilyProperties)
1125361fc4cbSmaya{
1126361fc4cbSmaya   VK_OUTARRAY_MAKE(out, pQueueFamilyProperties, pQueueFamilyPropertyCount);
1127361fc4cbSmaya
1128361fc4cbSmaya   vk_outarray_append(&out, p)
1129361fc4cbSmaya   {
1130361fc4cbSmaya      p->queueFamilyProperties = tu_queue_family_properties;
1131361fc4cbSmaya   }
1132361fc4cbSmaya}
1133361fc4cbSmaya
11347ec681f3Smrguint64_t
1135361fc4cbSmayatu_get_system_heap_size()
1136361fc4cbSmaya{
1137361fc4cbSmaya   struct sysinfo info;
1138361fc4cbSmaya   sysinfo(&info);
1139361fc4cbSmaya
1140361fc4cbSmaya   uint64_t total_ram = (uint64_t) info.totalram * (uint64_t) info.mem_unit;
1141361fc4cbSmaya
1142361fc4cbSmaya   /* We don't want to burn too much ram with the GPU.  If the user has 4GiB
1143361fc4cbSmaya    * or less, we use at most half.  If they have more than 4GiB, we use 3/4.
1144361fc4cbSmaya    */
1145361fc4cbSmaya   uint64_t available_ram;
1146361fc4cbSmaya   if (total_ram <= 4ull * 1024ull * 1024ull * 1024ull)
1147361fc4cbSmaya      available_ram = total_ram / 2;
1148361fc4cbSmaya   else
1149361fc4cbSmaya      available_ram = total_ram * 3 / 4;
1150361fc4cbSmaya
1151361fc4cbSmaya   return available_ram;
1152361fc4cbSmaya}
1153361fc4cbSmaya
11547ec681f3Smrgstatic VkDeviceSize
11557ec681f3Smrgtu_get_budget_memory(struct tu_physical_device *physical_device)
1156361fc4cbSmaya{
11577ec681f3Smrg   uint64_t heap_size = physical_device->heap.size;
11587ec681f3Smrg   uint64_t heap_used = physical_device->heap.used;
11597ec681f3Smrg   uint64_t sys_available;
11607ec681f3Smrg   ASSERTED bool has_available_memory =
11617ec681f3Smrg      os_get_available_system_memory(&sys_available);
11627ec681f3Smrg   assert(has_available_memory);
1163361fc4cbSmaya
11647ec681f3Smrg   /*
11657ec681f3Smrg    * Let's not incite the app to starve the system: report at most 90% of
11667ec681f3Smrg    * available system memory.
11677ec681f3Smrg    */
11687ec681f3Smrg   uint64_t heap_available = sys_available * 9 / 10;
11697ec681f3Smrg   return MIN2(heap_size, heap_used + heap_available);
11707ec681f3Smrg}
11717ec681f3Smrg
11727ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
11737ec681f3Smrgtu_GetPhysicalDeviceMemoryProperties2(VkPhysicalDevice pdev,
11747ec681f3Smrg                                      VkPhysicalDeviceMemoryProperties2 *props2)
11757ec681f3Smrg{
11767ec681f3Smrg   TU_FROM_HANDLE(tu_physical_device, physical_device, pdev);
11777ec681f3Smrg
11787ec681f3Smrg   VkPhysicalDeviceMemoryProperties *props = &props2->memoryProperties;
11797ec681f3Smrg   props->memoryHeapCount = 1;
11807ec681f3Smrg   props->memoryHeaps[0].size = physical_device->heap.size;
11817ec681f3Smrg   props->memoryHeaps[0].flags = physical_device->heap.flags;
11827ec681f3Smrg
11837ec681f3Smrg   props->memoryTypeCount = 1;
11847ec681f3Smrg   props->memoryTypes[0].propertyFlags =
1185361fc4cbSmaya      VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
1186361fc4cbSmaya      VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
1187361fc4cbSmaya      VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
11887ec681f3Smrg   props->memoryTypes[0].heapIndex = 0;
1189361fc4cbSmaya
11907ec681f3Smrg   vk_foreach_struct(ext, props2->pNext)
11917ec681f3Smrg   {
11927ec681f3Smrg      switch (ext->sType) {
11937ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT: {
11947ec681f3Smrg         VkPhysicalDeviceMemoryBudgetPropertiesEXT *memory_budget_props =
11957ec681f3Smrg            (VkPhysicalDeviceMemoryBudgetPropertiesEXT *) ext;
11967ec681f3Smrg         memory_budget_props->heapUsage[0] = physical_device->heap.used;
11977ec681f3Smrg         memory_budget_props->heapBudget[0] = tu_get_budget_memory(physical_device);
11987ec681f3Smrg
11997ec681f3Smrg         /* The heapBudget and heapUsage values must be zero for array elements
12007ec681f3Smrg          * greater than or equal to VkPhysicalDeviceMemoryProperties::memoryHeapCount
12017ec681f3Smrg          */
12027ec681f3Smrg         for (unsigned i = 1; i < VK_MAX_MEMORY_HEAPS; i++) {
12037ec681f3Smrg            memory_budget_props->heapBudget[i] = 0u;
12047ec681f3Smrg            memory_budget_props->heapUsage[i] = 0u;
12057ec681f3Smrg         }
12067ec681f3Smrg         break;
12077ec681f3Smrg      }
12087ec681f3Smrg      default:
12097ec681f3Smrg         break;
12107ec681f3Smrg      }
12117ec681f3Smrg   }
1212361fc4cbSmaya}
1213361fc4cbSmaya
1214361fc4cbSmayastatic VkResult
1215361fc4cbSmayatu_queue_init(struct tu_device *device,
1216361fc4cbSmaya              struct tu_queue *queue,
1217361fc4cbSmaya              int idx,
12187ec681f3Smrg              const VkDeviceQueueCreateInfo *create_info)
1219361fc4cbSmaya{
12207ec681f3Smrg   VkResult result = vk_queue_init(&queue->vk, &device->vk, create_info, idx);
12217ec681f3Smrg   if (result != VK_SUCCESS)
12227ec681f3Smrg      return result;
12237ec681f3Smrg
1224361fc4cbSmaya   queue->device = device;
12257ec681f3Smrg
12267ec681f3Smrg   list_inithead(&queue->queued_submits);
1227361fc4cbSmaya
1228361fc4cbSmaya   int ret = tu_drm_submitqueue_new(device, 0, &queue->msm_queue_id);
1229361fc4cbSmaya   if (ret)
12307ec681f3Smrg      return vk_startup_errorf(device->instance, VK_ERROR_INITIALIZATION_FAILED,
12317ec681f3Smrg                               "submitqueue create failed");
1232361fc4cbSmaya
12337ec681f3Smrg   queue->fence = -1;
1234361fc4cbSmaya
1235361fc4cbSmaya   return VK_SUCCESS;
1236361fc4cbSmaya}
1237361fc4cbSmaya
1238361fc4cbSmayastatic void
1239361fc4cbSmayatu_queue_finish(struct tu_queue *queue)
1240361fc4cbSmaya{
12417ec681f3Smrg   vk_queue_finish(&queue->vk);
12427ec681f3Smrg   if (queue->fence >= 0)
12437ec681f3Smrg      close(queue->fence);
1244361fc4cbSmaya   tu_drm_submitqueue_close(queue->device, queue->msm_queue_id);
1245361fc4cbSmaya}
1246361fc4cbSmaya
12477ec681f3Smrguint64_t
12487ec681f3Smrgtu_device_ticks_to_ns(struct tu_device *dev, uint64_t ts)
1249361fc4cbSmaya{
12507ec681f3Smrg   /* This is based on the 19.2MHz always-on rbbm timer.
12517ec681f3Smrg    *
12527ec681f3Smrg    * TODO we should probably query this value from kernel..
12537ec681f3Smrg    */
12547ec681f3Smrg   return ts * (1000000000 / 19200000);
12557ec681f3Smrg}
12567ec681f3Smrg
12577ec681f3Smrgstatic void*
12587ec681f3Smrgtu_trace_create_ts_buffer(struct u_trace_context *utctx, uint32_t size)
12597ec681f3Smrg{
12607ec681f3Smrg   struct tu_device *device =
12617ec681f3Smrg      container_of(utctx, struct tu_device, trace_context);
12627ec681f3Smrg
12637ec681f3Smrg   struct tu_bo *bo = ralloc(NULL, struct tu_bo);
12647ec681f3Smrg   tu_bo_init_new(device, bo, size, false);
12657ec681f3Smrg
12667ec681f3Smrg   return bo;
12677ec681f3Smrg}
12687ec681f3Smrg
12697ec681f3Smrgstatic void
12707ec681f3Smrgtu_trace_destroy_ts_buffer(struct u_trace_context *utctx, void *timestamps)
12717ec681f3Smrg{
12727ec681f3Smrg   struct tu_device *device =
12737ec681f3Smrg      container_of(utctx, struct tu_device, trace_context);
12747ec681f3Smrg   struct tu_bo *bo = timestamps;
12757ec681f3Smrg
12767ec681f3Smrg   tu_bo_finish(device, bo);
12777ec681f3Smrg   ralloc_free(bo);
12787ec681f3Smrg}
12797ec681f3Smrg
12807ec681f3Smrgstatic void
12817ec681f3Smrgtu_trace_record_ts(struct u_trace *ut, void *cs, void *timestamps,
12827ec681f3Smrg                   unsigned idx)
12837ec681f3Smrg{
12847ec681f3Smrg   struct tu_bo *bo = timestamps;
12857ec681f3Smrg   struct tu_cs *ts_cs = cs;
12867ec681f3Smrg
12877ec681f3Smrg   unsigned ts_offset = idx * sizeof(uint64_t);
12887ec681f3Smrg   tu_cs_emit_pkt7(ts_cs, CP_EVENT_WRITE, 4);
12897ec681f3Smrg   tu_cs_emit(ts_cs, CP_EVENT_WRITE_0_EVENT(RB_DONE_TS) | CP_EVENT_WRITE_0_TIMESTAMP);
12907ec681f3Smrg   tu_cs_emit_qw(ts_cs, bo->iova + ts_offset);
12917ec681f3Smrg   tu_cs_emit(ts_cs, 0x00000000);
12927ec681f3Smrg}
12937ec681f3Smrg
12947ec681f3Smrgstatic uint64_t
12957ec681f3Smrgtu_trace_read_ts(struct u_trace_context *utctx,
12967ec681f3Smrg                 void *timestamps, unsigned idx, void *flush_data)
12977ec681f3Smrg{
12987ec681f3Smrg   struct tu_device *device =
12997ec681f3Smrg      container_of(utctx, struct tu_device, trace_context);
13007ec681f3Smrg   struct tu_bo *bo = timestamps;
13017ec681f3Smrg   struct tu_u_trace_flush_data *trace_flush_data = flush_data;
13027ec681f3Smrg
13037ec681f3Smrg   /* Only need to stall on results for the first entry: */
13047ec681f3Smrg   if (idx == 0) {
13057ec681f3Smrg      tu_device_wait_u_trace(device, trace_flush_data->syncobj);
1306361fc4cbSmaya   }
13077ec681f3Smrg
13087ec681f3Smrg   if (tu_bo_map(device, bo) != VK_SUCCESS) {
13097ec681f3Smrg      return U_TRACE_NO_TIMESTAMP;
13107ec681f3Smrg   }
13117ec681f3Smrg
13127ec681f3Smrg   uint64_t *ts = bo->map;
13137ec681f3Smrg
13147ec681f3Smrg   /* Don't translate the no-timestamp marker: */
13157ec681f3Smrg   if (ts[idx] == U_TRACE_NO_TIMESTAMP)
13167ec681f3Smrg      return U_TRACE_NO_TIMESTAMP;
13177ec681f3Smrg
13187ec681f3Smrg   return tu_device_ticks_to_ns(device, ts[idx]);
13197ec681f3Smrg}
13207ec681f3Smrg
13217ec681f3Smrgstatic void
13227ec681f3Smrgtu_trace_delete_flush_data(struct u_trace_context *utctx, void *flush_data)
13237ec681f3Smrg{
13247ec681f3Smrg   struct tu_device *device =
13257ec681f3Smrg      container_of(utctx, struct tu_device, trace_context);
13267ec681f3Smrg   struct tu_u_trace_flush_data *trace_flush_data = flush_data;
13277ec681f3Smrg
13287ec681f3Smrg   tu_u_trace_cmd_data_finish(device, trace_flush_data->cmd_trace_data,
13297ec681f3Smrg                              trace_flush_data->trace_count);
13307ec681f3Smrg   vk_free(&device->vk.alloc, trace_flush_data->syncobj);
13317ec681f3Smrg   vk_free(&device->vk.alloc, trace_flush_data);
13327ec681f3Smrg}
13337ec681f3Smrg
13347ec681f3Smrgvoid
13357ec681f3Smrgtu_copy_timestamp_buffer(struct u_trace_context *utctx, void *cmdstream,
13367ec681f3Smrg                         void *ts_from, uint32_t from_offset,
13377ec681f3Smrg                         void *ts_to, uint32_t to_offset,
13387ec681f3Smrg                         uint32_t count)
13397ec681f3Smrg{
13407ec681f3Smrg   struct tu_cs *cs = cmdstream;
13417ec681f3Smrg   struct tu_bo *bo_from = ts_from;
13427ec681f3Smrg   struct tu_bo *bo_to = ts_to;
13437ec681f3Smrg
13447ec681f3Smrg   tu_cs_emit_pkt7(cs, CP_MEMCPY, 5);
13457ec681f3Smrg   tu_cs_emit(cs, count * sizeof(uint64_t) / sizeof(uint32_t));
13467ec681f3Smrg   tu_cs_emit_qw(cs, bo_from->iova + from_offset * sizeof(uint64_t));
13477ec681f3Smrg   tu_cs_emit_qw(cs, bo_to->iova + to_offset * sizeof(uint64_t));
1348361fc4cbSmaya}
1349361fc4cbSmaya
1350361fc4cbSmayaVkResult
13517ec681f3Smrgtu_create_copy_timestamp_cs(struct tu_cmd_buffer *cmdbuf, struct tu_cs** cs,
13527ec681f3Smrg                            struct u_trace **trace_copy)
13537ec681f3Smrg{
13547ec681f3Smrg   *cs = vk_zalloc(&cmdbuf->device->vk.alloc, sizeof(struct tu_cs), 8,
13557ec681f3Smrg                   VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
13567ec681f3Smrg
13577ec681f3Smrg   if (*cs == NULL) {
13587ec681f3Smrg      return VK_ERROR_OUT_OF_HOST_MEMORY;
13597ec681f3Smrg   }
13607ec681f3Smrg
13617ec681f3Smrg   tu_cs_init(*cs, cmdbuf->device, TU_CS_MODE_GROW,
13627ec681f3Smrg              list_length(&cmdbuf->trace.trace_chunks) * 6 + 3);
13637ec681f3Smrg
13647ec681f3Smrg   tu_cs_begin(*cs);
13657ec681f3Smrg
13667ec681f3Smrg   tu_cs_emit_wfi(*cs);
13677ec681f3Smrg   tu_cs_emit_pkt7(*cs, CP_WAIT_FOR_ME, 0);
13687ec681f3Smrg
13697ec681f3Smrg   *trace_copy = vk_zalloc(&cmdbuf->device->vk.alloc, sizeof(struct u_trace), 8,
13707ec681f3Smrg                           VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
13717ec681f3Smrg
13727ec681f3Smrg   if (*trace_copy == NULL) {
13737ec681f3Smrg      return VK_ERROR_OUT_OF_HOST_MEMORY;
13747ec681f3Smrg   }
13757ec681f3Smrg
13767ec681f3Smrg   u_trace_init(*trace_copy, cmdbuf->trace.utctx);
13777ec681f3Smrg   u_trace_clone_append(u_trace_begin_iterator(&cmdbuf->trace),
13787ec681f3Smrg                        u_trace_end_iterator(&cmdbuf->trace),
13797ec681f3Smrg                        *trace_copy, *cs,
13807ec681f3Smrg                        tu_copy_timestamp_buffer);
13817ec681f3Smrg
13827ec681f3Smrg   tu_cs_emit_wfi(*cs);
13837ec681f3Smrg
13847ec681f3Smrg   tu_cs_end(*cs);
13857ec681f3Smrg
13867ec681f3Smrg   return VK_SUCCESS;
13877ec681f3Smrg}
13887ec681f3Smrg
13897ec681f3Smrgvoid
13907ec681f3Smrgtu_u_trace_cmd_data_finish(struct tu_device *device,
13917ec681f3Smrg                           struct tu_u_trace_cmd_data *trace_data,
13927ec681f3Smrg                           uint32_t entry_count)
13937ec681f3Smrg{
13947ec681f3Smrg   for (uint32_t i = 0; i < entry_count; ++i) {
13957ec681f3Smrg      /* Only if we had to create a copy of trace we should free it */
13967ec681f3Smrg      if (trace_data[i].timestamp_copy_cs != NULL) {
13977ec681f3Smrg         tu_cs_finish(trace_data[i].timestamp_copy_cs);
13987ec681f3Smrg         vk_free(&device->vk.alloc, trace_data[i].timestamp_copy_cs);
13997ec681f3Smrg
14007ec681f3Smrg         u_trace_fini(trace_data[i].trace);
14017ec681f3Smrg         vk_free(&device->vk.alloc, trace_data[i].trace);
14027ec681f3Smrg      }
14037ec681f3Smrg   }
14047ec681f3Smrg
14057ec681f3Smrg   vk_free(&device->vk.alloc, trace_data);
14067ec681f3Smrg}
14077ec681f3Smrg
14087ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
1409361fc4cbSmayatu_CreateDevice(VkPhysicalDevice physicalDevice,
1410361fc4cbSmaya                const VkDeviceCreateInfo *pCreateInfo,
1411361fc4cbSmaya                const VkAllocationCallbacks *pAllocator,
1412361fc4cbSmaya                VkDevice *pDevice)
1413361fc4cbSmaya{
1414361fc4cbSmaya   TU_FROM_HANDLE(tu_physical_device, physical_device, physicalDevice);
1415361fc4cbSmaya   VkResult result;
1416361fc4cbSmaya   struct tu_device *device;
14177ec681f3Smrg   bool custom_border_colors = false;
14187ec681f3Smrg   bool perf_query_pools = false;
14197ec681f3Smrg   bool robust_buffer_access2 = false;
1420361fc4cbSmaya
14217ec681f3Smrg   vk_foreach_struct_const(ext, pCreateInfo->pNext) {
14227ec681f3Smrg      switch (ext->sType) {
14237ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: {
14247ec681f3Smrg         const VkPhysicalDeviceCustomBorderColorFeaturesEXT *border_color_features = (const void *)ext;
14257ec681f3Smrg         custom_border_colors = border_color_features->customBorderColors;
14267ec681f3Smrg         break;
14277ec681f3Smrg      }
14287ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PERFORMANCE_QUERY_FEATURES_KHR: {
14297ec681f3Smrg         const VkPhysicalDevicePerformanceQueryFeaturesKHR *feature =
14307ec681f3Smrg            (VkPhysicalDevicePerformanceQueryFeaturesKHR *)ext;
14317ec681f3Smrg         perf_query_pools = feature->performanceCounterQueryPools;
14327ec681f3Smrg         break;
14337ec681f3Smrg      }
14347ec681f3Smrg      case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT: {
14357ec681f3Smrg         VkPhysicalDeviceRobustness2FeaturesEXT *features = (void *)ext;
14367ec681f3Smrg         robust_buffer_access2 = features->robustBufferAccess2;
14377ec681f3Smrg         break;
14387ec681f3Smrg      }
14397ec681f3Smrg      default:
14407ec681f3Smrg         break;
1441361fc4cbSmaya      }
1442361fc4cbSmaya   }
1443361fc4cbSmaya
14447ec681f3Smrg   device = vk_zalloc2(&physical_device->instance->vk.alloc, pAllocator,
1445361fc4cbSmaya                       sizeof(*device), 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1446361fc4cbSmaya   if (!device)
14477ec681f3Smrg      return vk_startup_errorf(physical_device->instance, VK_ERROR_OUT_OF_HOST_MEMORY, "OOM");
14487ec681f3Smrg
14497ec681f3Smrg   struct vk_device_dispatch_table dispatch_table;
14507ec681f3Smrg   vk_device_dispatch_table_from_entrypoints(
14517ec681f3Smrg      &dispatch_table, &tu_device_entrypoints, true);
14527ec681f3Smrg   vk_device_dispatch_table_from_entrypoints(
14537ec681f3Smrg      &dispatch_table, &wsi_device_entrypoints, false);
14547ec681f3Smrg
14557ec681f3Smrg   result = vk_device_init(&device->vk, &physical_device->vk,
14567ec681f3Smrg                           &dispatch_table, pCreateInfo, pAllocator);
14577ec681f3Smrg   if (result != VK_SUCCESS) {
14587ec681f3Smrg      vk_free(&device->vk.alloc, device);
14597ec681f3Smrg      return vk_startup_errorf(physical_device->instance, result,
14607ec681f3Smrg                               "vk_device_init failed");
14617ec681f3Smrg   }
1462361fc4cbSmaya
1463361fc4cbSmaya   device->instance = physical_device->instance;
1464361fc4cbSmaya   device->physical_device = physical_device;
14657ec681f3Smrg   device->fd = physical_device->local_fd;
14667ec681f3Smrg   device->_lost = false;
1467361fc4cbSmaya
14687ec681f3Smrg   mtx_init(&device->bo_mutex, mtx_plain);
14697ec681f3Smrg   pthread_mutex_init(&device->submit_mutex, NULL);
1470361fc4cbSmaya
1471361fc4cbSmaya   for (unsigned i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
1472361fc4cbSmaya      const VkDeviceQueueCreateInfo *queue_create =
1473361fc4cbSmaya         &pCreateInfo->pQueueCreateInfos[i];
1474361fc4cbSmaya      uint32_t qfi = queue_create->queueFamilyIndex;
1475361fc4cbSmaya      device->queues[qfi] = vk_alloc(
14767ec681f3Smrg         &device->vk.alloc, queue_create->queueCount * sizeof(struct tu_queue),
1477361fc4cbSmaya         8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
1478361fc4cbSmaya      if (!device->queues[qfi]) {
14797ec681f3Smrg         result = vk_startup_errorf(physical_device->instance,
14807ec681f3Smrg                                    VK_ERROR_OUT_OF_HOST_MEMORY,
14817ec681f3Smrg                                    "OOM");
14827ec681f3Smrg         goto fail_queues;
1483361fc4cbSmaya      }
1484361fc4cbSmaya
1485361fc4cbSmaya      memset(device->queues[qfi], 0,
1486361fc4cbSmaya             queue_create->queueCount * sizeof(struct tu_queue));
1487361fc4cbSmaya
1488361fc4cbSmaya      device->queue_count[qfi] = queue_create->queueCount;
1489361fc4cbSmaya
1490361fc4cbSmaya      for (unsigned q = 0; q < queue_create->queueCount; q++) {
14917ec681f3Smrg         result = tu_queue_init(device, &device->queues[qfi][q], q,
14927ec681f3Smrg                                queue_create);
1493361fc4cbSmaya         if (result != VK_SUCCESS)
14947ec681f3Smrg            goto fail_queues;
1495361fc4cbSmaya      }
1496361fc4cbSmaya   }
1497361fc4cbSmaya
14987ec681f3Smrg   device->compiler = ir3_compiler_create(NULL, &physical_device->dev_id,
14997ec681f3Smrg                                          robust_buffer_access2);
15007ec681f3Smrg   if (!device->compiler) {
15017ec681f3Smrg      result = vk_startup_errorf(physical_device->instance,
15027ec681f3Smrg                                 VK_ERROR_INITIALIZATION_FAILED,
15037ec681f3Smrg                                 "failed to initialize ir3 compiler");
15047ec681f3Smrg      goto fail_queues;
15057ec681f3Smrg   }
15067ec681f3Smrg
15077ec681f3Smrg   /* initial sizes, these will increase if there is overflow */
15087ec681f3Smrg   device->vsc_draw_strm_pitch = 0x1000 + VSC_PAD;
15097ec681f3Smrg   device->vsc_prim_strm_pitch = 0x4000 + VSC_PAD;
15107ec681f3Smrg
15117ec681f3Smrg   uint32_t global_size = sizeof(struct tu6_global);
15127ec681f3Smrg   if (custom_border_colors)
15137ec681f3Smrg      global_size += TU_BORDER_COLOR_COUNT * sizeof(struct bcolor_entry);
15147ec681f3Smrg
15157ec681f3Smrg   result = tu_bo_init_new(device, &device->global_bo, global_size,
15167ec681f3Smrg                           TU_BO_ALLOC_ALLOW_DUMP);
15177ec681f3Smrg   if (result != VK_SUCCESS) {
15187ec681f3Smrg      vk_startup_errorf(device->instance, result, "BO init");
15197ec681f3Smrg      goto fail_global_bo;
15207ec681f3Smrg   }
15217ec681f3Smrg
15227ec681f3Smrg   result = tu_bo_map(device, &device->global_bo);
15237ec681f3Smrg   if (result != VK_SUCCESS) {
15247ec681f3Smrg      vk_startup_errorf(device->instance, result, "BO map");
15257ec681f3Smrg      goto fail_global_bo_map;
15267ec681f3Smrg   }
15277ec681f3Smrg
15287ec681f3Smrg   struct tu6_global *global = device->global_bo.map;
15297ec681f3Smrg   tu_init_clear_blit_shaders(device);
15307ec681f3Smrg   global->predicate = 0;
15317ec681f3Smrg   tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK],
15327ec681f3Smrg                         &(VkClearColorValue) {}, false);
15337ec681f3Smrg   tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_INT_TRANSPARENT_BLACK],
15347ec681f3Smrg                         &(VkClearColorValue) {}, true);
15357ec681f3Smrg   tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK],
15367ec681f3Smrg                         &(VkClearColorValue) { .float32[3] = 1.0f }, false);
15377ec681f3Smrg   tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_INT_OPAQUE_BLACK],
15387ec681f3Smrg                         &(VkClearColorValue) { .int32[3] = 1 }, true);
15397ec681f3Smrg   tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE],
15407ec681f3Smrg                         &(VkClearColorValue) { .float32[0 ... 3] = 1.0f }, false);
15417ec681f3Smrg   tu6_pack_border_color(&global->bcolor_builtin[VK_BORDER_COLOR_INT_OPAQUE_WHITE],
15427ec681f3Smrg                         &(VkClearColorValue) { .int32[0 ... 3] = 1 }, true);
15437ec681f3Smrg
15447ec681f3Smrg   /* initialize to ones so ffs can be used to find unused slots */
15457ec681f3Smrg   BITSET_ONES(device->custom_border_color);
1546361fc4cbSmaya
1547361fc4cbSmaya   VkPipelineCacheCreateInfo ci;
1548361fc4cbSmaya   ci.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
1549361fc4cbSmaya   ci.pNext = NULL;
1550361fc4cbSmaya   ci.flags = 0;
1551361fc4cbSmaya   ci.pInitialData = NULL;
1552361fc4cbSmaya   ci.initialDataSize = 0;
1553361fc4cbSmaya   VkPipelineCache pc;
1554361fc4cbSmaya   result =
1555361fc4cbSmaya      tu_CreatePipelineCache(tu_device_to_handle(device), &ci, NULL, &pc);
15567ec681f3Smrg   if (result != VK_SUCCESS) {
15577ec681f3Smrg      vk_startup_errorf(device->instance, result, "create pipeline cache failed");
15587ec681f3Smrg      goto fail_pipeline_cache;
15597ec681f3Smrg   }
15607ec681f3Smrg
15617ec681f3Smrg   if (perf_query_pools) {
15627ec681f3Smrg      /* Prepare command streams setting pass index to the PERF_CNTRS_REG
15637ec681f3Smrg       * from 0 to 31. One of these will be picked up at cmd submit time
15647ec681f3Smrg       * when the perf query is executed.
15657ec681f3Smrg       */
15667ec681f3Smrg      struct tu_cs *cs;
15677ec681f3Smrg
15687ec681f3Smrg      if (!(device->perfcntrs_pass_cs = calloc(1, sizeof(struct tu_cs)))) {
15697ec681f3Smrg         result = vk_startup_errorf(device->instance,
15707ec681f3Smrg               VK_ERROR_OUT_OF_HOST_MEMORY, "OOM");
15717ec681f3Smrg         goto fail_perfcntrs_pass_alloc;
15727ec681f3Smrg      }
15737ec681f3Smrg
15747ec681f3Smrg      device->perfcntrs_pass_cs_entries = calloc(32, sizeof(struct tu_cs_entry));
15757ec681f3Smrg      if (!device->perfcntrs_pass_cs_entries) {
15767ec681f3Smrg         result = vk_startup_errorf(device->instance,
15777ec681f3Smrg               VK_ERROR_OUT_OF_HOST_MEMORY, "OOM");
15787ec681f3Smrg         goto fail_perfcntrs_pass_entries_alloc;
15797ec681f3Smrg      }
15807ec681f3Smrg
15817ec681f3Smrg      cs = device->perfcntrs_pass_cs;
15827ec681f3Smrg      tu_cs_init(cs, device, TU_CS_MODE_SUB_STREAM, 96);
15837ec681f3Smrg
15847ec681f3Smrg      for (unsigned i = 0; i < 32; i++) {
15857ec681f3Smrg         struct tu_cs sub_cs;
15867ec681f3Smrg
15877ec681f3Smrg         result = tu_cs_begin_sub_stream(cs, 3, &sub_cs);
15887ec681f3Smrg         if (result != VK_SUCCESS) {
15897ec681f3Smrg            vk_startup_errorf(device->instance, result,
15907ec681f3Smrg                  "failed to allocate commands streams");
15917ec681f3Smrg            goto fail_prepare_perfcntrs_pass_cs;
15927ec681f3Smrg         }
15937ec681f3Smrg
15947ec681f3Smrg         tu_cs_emit_regs(&sub_cs, A6XX_CP_SCRATCH_REG(PERF_CNTRS_REG, 1 << i));
15957ec681f3Smrg         tu_cs_emit_pkt7(&sub_cs, CP_WAIT_FOR_ME, 0);
15967ec681f3Smrg
15977ec681f3Smrg         device->perfcntrs_pass_cs_entries[i] = tu_cs_end_sub_stream(cs, &sub_cs);
15987ec681f3Smrg      }
15997ec681f3Smrg   }
16007ec681f3Smrg
16017ec681f3Smrg   /* Initialize a condition variable for timeline semaphore */
16027ec681f3Smrg   pthread_condattr_t condattr;
16037ec681f3Smrg   if (pthread_condattr_init(&condattr) != 0) {
16047ec681f3Smrg      result = vk_startup_errorf(physical_device->instance,
16057ec681f3Smrg                                 VK_ERROR_INITIALIZATION_FAILED,
16067ec681f3Smrg                                 "pthread condattr init");
16077ec681f3Smrg      goto fail_timeline_cond;
16087ec681f3Smrg   }
16097ec681f3Smrg   if (pthread_condattr_setclock(&condattr, CLOCK_MONOTONIC) != 0) {
16107ec681f3Smrg      pthread_condattr_destroy(&condattr);
16117ec681f3Smrg      result = vk_startup_errorf(physical_device->instance,
16127ec681f3Smrg                                 VK_ERROR_INITIALIZATION_FAILED,
16137ec681f3Smrg                                 "pthread condattr clock setup");
16147ec681f3Smrg      goto fail_timeline_cond;
16157ec681f3Smrg   }
16167ec681f3Smrg   if (pthread_cond_init(&device->timeline_cond, &condattr) != 0) {
16177ec681f3Smrg      pthread_condattr_destroy(&condattr);
16187ec681f3Smrg      result = vk_startup_errorf(physical_device->instance,
16197ec681f3Smrg                                 VK_ERROR_INITIALIZATION_FAILED,
16207ec681f3Smrg                                 "pthread cond init");
16217ec681f3Smrg      goto fail_timeline_cond;
16227ec681f3Smrg   }
16237ec681f3Smrg   pthread_condattr_destroy(&condattr);
1624361fc4cbSmaya
1625361fc4cbSmaya   device->mem_cache = tu_pipeline_cache_from_handle(pc);
1626361fc4cbSmaya
16277ec681f3Smrg   for (unsigned i = 0; i < ARRAY_SIZE(device->scratch_bos); i++)
16287ec681f3Smrg      mtx_init(&device->scratch_bos[i].construct_mtx, mtx_plain);
16297ec681f3Smrg
16307ec681f3Smrg   mtx_init(&device->mutex, mtx_plain);
16317ec681f3Smrg
16327ec681f3Smrg   device->submit_count = 0;
16337ec681f3Smrg   u_trace_context_init(&device->trace_context, device,
16347ec681f3Smrg                     tu_trace_create_ts_buffer,
16357ec681f3Smrg                     tu_trace_destroy_ts_buffer,
16367ec681f3Smrg                     tu_trace_record_ts,
16377ec681f3Smrg                     tu_trace_read_ts,
16387ec681f3Smrg                     tu_trace_delete_flush_data);
16397ec681f3Smrg
1640361fc4cbSmaya   *pDevice = tu_device_to_handle(device);
1641361fc4cbSmaya   return VK_SUCCESS;
1642361fc4cbSmaya
16437ec681f3Smrgfail_timeline_cond:
16447ec681f3Smrgfail_prepare_perfcntrs_pass_cs:
16457ec681f3Smrg   free(device->perfcntrs_pass_cs_entries);
16467ec681f3Smrg   tu_cs_finish(device->perfcntrs_pass_cs);
16477ec681f3Smrgfail_perfcntrs_pass_entries_alloc:
16487ec681f3Smrg   free(device->perfcntrs_pass_cs);
16497ec681f3Smrgfail_perfcntrs_pass_alloc:
16507ec681f3Smrg   tu_DestroyPipelineCache(tu_device_to_handle(device), pc, NULL);
16517ec681f3Smrgfail_pipeline_cache:
16527ec681f3Smrg   tu_destroy_clear_blit_shaders(device);
16537ec681f3Smrgfail_global_bo_map:
16547ec681f3Smrg   tu_bo_finish(device, &device->global_bo);
16557ec681f3Smrg   vk_free(&device->vk.alloc, device->bo_idx);
16567ec681f3Smrg   vk_free(&device->vk.alloc, device->bo_list);
16577ec681f3Smrgfail_global_bo:
16587ec681f3Smrg   ir3_compiler_destroy(device->compiler);
16597ec681f3Smrg
16607ec681f3Smrgfail_queues:
1661361fc4cbSmaya   for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {
1662361fc4cbSmaya      for (unsigned q = 0; q < device->queue_count[i]; q++)
1663361fc4cbSmaya         tu_queue_finish(&device->queues[i][q]);
1664361fc4cbSmaya      if (device->queue_count[i])
16657ec681f3Smrg         vk_free(&device->vk.alloc, device->queues[i]);
1666361fc4cbSmaya   }
1667361fc4cbSmaya
16687ec681f3Smrg   vk_device_finish(&device->vk);
16697ec681f3Smrg   vk_free(&device->vk.alloc, device);
1670361fc4cbSmaya   return result;
1671361fc4cbSmaya}
1672361fc4cbSmaya
16737ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
1674361fc4cbSmayatu_DestroyDevice(VkDevice _device, const VkAllocationCallbacks *pAllocator)
1675361fc4cbSmaya{
1676361fc4cbSmaya   TU_FROM_HANDLE(tu_device, device, _device);
1677361fc4cbSmaya
1678361fc4cbSmaya   if (!device)
1679361fc4cbSmaya      return;
1680361fc4cbSmaya
16817ec681f3Smrg   u_trace_context_fini(&device->trace_context);
16827ec681f3Smrg
1683361fc4cbSmaya   for (unsigned i = 0; i < TU_MAX_QUEUE_FAMILIES; i++) {
1684361fc4cbSmaya      for (unsigned q = 0; q < device->queue_count[i]; q++)
1685361fc4cbSmaya         tu_queue_finish(&device->queues[i][q]);
1686361fc4cbSmaya      if (device->queue_count[i])
16877ec681f3Smrg         vk_free(&device->vk.alloc, device->queues[i]);
16887ec681f3Smrg   }
16897ec681f3Smrg
16907ec681f3Smrg   for (unsigned i = 0; i < ARRAY_SIZE(device->scratch_bos); i++) {
16917ec681f3Smrg      if (device->scratch_bos[i].initialized)
16927ec681f3Smrg         tu_bo_finish(device, &device->scratch_bos[i].bo);
1693361fc4cbSmaya   }
1694361fc4cbSmaya
16957ec681f3Smrg   tu_destroy_clear_blit_shaders(device);
16967ec681f3Smrg
16977ec681f3Smrg   ir3_compiler_destroy(device->compiler);
1698361fc4cbSmaya
1699361fc4cbSmaya   VkPipelineCache pc = tu_pipeline_cache_to_handle(device->mem_cache);
1700361fc4cbSmaya   tu_DestroyPipelineCache(tu_device_to_handle(device), pc, NULL);
1701361fc4cbSmaya
17027ec681f3Smrg   if (device->perfcntrs_pass_cs) {
17037ec681f3Smrg      free(device->perfcntrs_pass_cs_entries);
17047ec681f3Smrg      tu_cs_finish(device->perfcntrs_pass_cs);
17057ec681f3Smrg      free(device->perfcntrs_pass_cs);
17067ec681f3Smrg   }
1707361fc4cbSmaya
17087ec681f3Smrg   pthread_cond_destroy(&device->timeline_cond);
17097ec681f3Smrg   vk_free(&device->vk.alloc, device->bo_list);
17107ec681f3Smrg   vk_free(&device->vk.alloc, device->bo_idx);
17117ec681f3Smrg   vk_device_finish(&device->vk);
17127ec681f3Smrg   vk_free(&device->vk.alloc, device);
1713361fc4cbSmaya}
1714361fc4cbSmaya
1715361fc4cbSmayaVkResult
17167ec681f3Smrg_tu_device_set_lost(struct tu_device *device,
17177ec681f3Smrg                    const char *msg, ...)
1718361fc4cbSmaya{
17197ec681f3Smrg   /* Set the flag indicating that waits should return in finite time even
17207ec681f3Smrg    * after device loss.
17217ec681f3Smrg    */
17227ec681f3Smrg   p_atomic_inc(&device->_lost);
1723361fc4cbSmaya
17247ec681f3Smrg   /* TODO: Report the log message through VkDebugReportCallbackEXT instead */
17257ec681f3Smrg   va_list ap;
17267ec681f3Smrg   va_start(ap, msg);
17277ec681f3Smrg   mesa_loge_v(msg, ap);
17287ec681f3Smrg   va_end(ap);
1729361fc4cbSmaya
17307ec681f3Smrg   if (env_var_as_boolean("TU_ABORT_ON_DEVICE_LOSS", false))
17317ec681f3Smrg      abort();
1732361fc4cbSmaya
17337ec681f3Smrg   return VK_ERROR_DEVICE_LOST;
1734361fc4cbSmaya}
1735361fc4cbSmaya
1736361fc4cbSmayaVkResult
17377ec681f3Smrgtu_get_scratch_bo(struct tu_device *dev, uint64_t size, struct tu_bo **bo)
1738361fc4cbSmaya{
17397ec681f3Smrg   unsigned size_log2 = MAX2(util_logbase2_ceil64(size), MIN_SCRATCH_BO_SIZE_LOG2);
17407ec681f3Smrg   unsigned index = size_log2 - MIN_SCRATCH_BO_SIZE_LOG2;
17417ec681f3Smrg   assert(index < ARRAY_SIZE(dev->scratch_bos));
1742361fc4cbSmaya
17437ec681f3Smrg   for (unsigned i = index; i < ARRAY_SIZE(dev->scratch_bos); i++) {
17447ec681f3Smrg      if (p_atomic_read(&dev->scratch_bos[i].initialized)) {
17457ec681f3Smrg         /* Fast path: just return the already-allocated BO. */
17467ec681f3Smrg         *bo = &dev->scratch_bos[i].bo;
17477ec681f3Smrg         return VK_SUCCESS;
1748361fc4cbSmaya      }
17497ec681f3Smrg   }
1750361fc4cbSmaya
17517ec681f3Smrg   /* Slow path: actually allocate the BO. We take a lock because the process
17527ec681f3Smrg    * of allocating it is slow, and we don't want to block the CPU while it
17537ec681f3Smrg    * finishes.
17547ec681f3Smrg   */
17557ec681f3Smrg   mtx_lock(&dev->scratch_bos[index].construct_mtx);
1756361fc4cbSmaya
17577ec681f3Smrg   /* Another thread may have allocated it already while we were waiting on
17587ec681f3Smrg    * the lock. We need to check this in order to avoid double-allocating.
17597ec681f3Smrg    */
17607ec681f3Smrg   if (dev->scratch_bos[index].initialized) {
17617ec681f3Smrg      mtx_unlock(&dev->scratch_bos[index].construct_mtx);
17627ec681f3Smrg      *bo = &dev->scratch_bos[index].bo;
17637ec681f3Smrg      return VK_SUCCESS;
17647ec681f3Smrg   }
1765361fc4cbSmaya
17667ec681f3Smrg   unsigned bo_size = 1ull << size_log2;
17677ec681f3Smrg   VkResult result = tu_bo_init_new(dev, &dev->scratch_bos[index].bo, bo_size,
17687ec681f3Smrg                                    TU_BO_ALLOC_NO_FLAGS);
17697ec681f3Smrg   if (result != VK_SUCCESS) {
17707ec681f3Smrg      mtx_unlock(&dev->scratch_bos[index].construct_mtx);
17717ec681f3Smrg      return result;
17727ec681f3Smrg   }
1773361fc4cbSmaya
17747ec681f3Smrg   p_atomic_set(&dev->scratch_bos[index].initialized, true);
1775361fc4cbSmaya
17767ec681f3Smrg   mtx_unlock(&dev->scratch_bos[index].construct_mtx);
1777361fc4cbSmaya
17787ec681f3Smrg   *bo = &dev->scratch_bos[index].bo;
17797ec681f3Smrg   return VK_SUCCESS;
17807ec681f3Smrg}
1781361fc4cbSmaya
17827ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
17837ec681f3Smrgtu_EnumerateInstanceLayerProperties(uint32_t *pPropertyCount,
17847ec681f3Smrg                                    VkLayerProperties *pProperties)
17857ec681f3Smrg{
17867ec681f3Smrg   *pPropertyCount = 0;
1787361fc4cbSmaya   return VK_SUCCESS;
1788361fc4cbSmaya}
1789361fc4cbSmaya
17907ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
1791361fc4cbSmayatu_QueueWaitIdle(VkQueue _queue)
1792361fc4cbSmaya{
1793361fc4cbSmaya   TU_FROM_HANDLE(tu_queue, queue, _queue);
1794361fc4cbSmaya
17957ec681f3Smrg   if (tu_device_is_lost(queue->device))
17967ec681f3Smrg      return VK_ERROR_DEVICE_LOST;
1797361fc4cbSmaya
17987ec681f3Smrg   if (queue->fence < 0)
17997ec681f3Smrg      return VK_SUCCESS;
1800361fc4cbSmaya
18017ec681f3Smrg   pthread_mutex_lock(&queue->device->submit_mutex);
1802361fc4cbSmaya
18037ec681f3Smrg   do {
18047ec681f3Smrg      tu_device_submit_deferred_locked(queue->device);
1805361fc4cbSmaya
18067ec681f3Smrg      if (list_is_empty(&queue->queued_submits))
18077ec681f3Smrg         break;
1808361fc4cbSmaya
18097ec681f3Smrg      pthread_cond_wait(&queue->device->timeline_cond,
18107ec681f3Smrg            &queue->device->submit_mutex);
18117ec681f3Smrg   } while (!list_is_empty(&queue->queued_submits));
1812361fc4cbSmaya
18137ec681f3Smrg   pthread_mutex_unlock(&queue->device->submit_mutex);
1814361fc4cbSmaya
18157ec681f3Smrg   struct pollfd fds = { .fd = queue->fence, .events = POLLIN };
18167ec681f3Smrg   int ret;
18177ec681f3Smrg   do {
18187ec681f3Smrg      ret = poll(&fds, 1, -1);
18197ec681f3Smrg   } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
18207ec681f3Smrg
18217ec681f3Smrg   /* TODO: otherwise set device lost ? */
18227ec681f3Smrg   assert(ret == 1 && !(fds.revents & (POLLERR | POLLNVAL)));
18237ec681f3Smrg
18247ec681f3Smrg   close(queue->fence);
18257ec681f3Smrg   queue->fence = -1;
18267ec681f3Smrg   return VK_SUCCESS;
1827361fc4cbSmaya}
1828361fc4cbSmaya
18297ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
18307ec681f3Smrgtu_EnumerateInstanceExtensionProperties(const char *pLayerName,
18317ec681f3Smrg                                        uint32_t *pPropertyCount,
18327ec681f3Smrg                                        VkExtensionProperties *pProperties)
1833361fc4cbSmaya{
1834361fc4cbSmaya   if (pLayerName)
1835361fc4cbSmaya      return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT);
1836361fc4cbSmaya
18377ec681f3Smrg   return vk_enumerate_instance_extension_properties(
18387ec681f3Smrg      &tu_instance_extensions_supported, pPropertyCount, pProperties);
1839361fc4cbSmaya}
1840361fc4cbSmaya
18417ec681f3SmrgVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1842361fc4cbSmayatu_GetInstanceProcAddr(VkInstance _instance, const char *pName)
1843361fc4cbSmaya{
1844361fc4cbSmaya   TU_FROM_HANDLE(tu_instance, instance, _instance);
18457ec681f3Smrg   return vk_instance_get_proc_addr(&instance->vk,
18467ec681f3Smrg                                    &tu_instance_entrypoints,
18477ec681f3Smrg                                    pName);
1848361fc4cbSmaya}
1849361fc4cbSmaya
1850361fc4cbSmaya/* The loader wants us to expose a second GetInstanceProcAddr function
1851361fc4cbSmaya * to work around certain LD_PRELOAD issues seen in apps.
1852361fc4cbSmaya */
1853361fc4cbSmayaPUBLIC
1854361fc4cbSmayaVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1855361fc4cbSmayavk_icdGetInstanceProcAddr(VkInstance instance, const char *pName);
1856361fc4cbSmaya
1857361fc4cbSmayaPUBLIC
1858361fc4cbSmayaVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
1859361fc4cbSmayavk_icdGetInstanceProcAddr(VkInstance instance, const char *pName)
1860361fc4cbSmaya{
1861361fc4cbSmaya   return tu_GetInstanceProcAddr(instance, pName);
1862361fc4cbSmaya}
1863361fc4cbSmaya
18647ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
18657ec681f3Smrgtu_AllocateMemory(VkDevice _device,
18667ec681f3Smrg                  const VkMemoryAllocateInfo *pAllocateInfo,
18677ec681f3Smrg                  const VkAllocationCallbacks *pAllocator,
18687ec681f3Smrg                  VkDeviceMemory *pMem)
1869361fc4cbSmaya{
1870361fc4cbSmaya   TU_FROM_HANDLE(tu_device, device, _device);
1871361fc4cbSmaya   struct tu_device_memory *mem;
1872361fc4cbSmaya   VkResult result;
1873361fc4cbSmaya
1874361fc4cbSmaya   assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO);
1875361fc4cbSmaya
1876361fc4cbSmaya   if (pAllocateInfo->allocationSize == 0) {
1877361fc4cbSmaya      /* Apparently, this is allowed */
1878361fc4cbSmaya      *pMem = VK_NULL_HANDLE;
1879361fc4cbSmaya      return VK_SUCCESS;
1880361fc4cbSmaya   }
1881361fc4cbSmaya
18827ec681f3Smrg   struct tu_memory_heap *mem_heap = &device->physical_device->heap;
18837ec681f3Smrg   uint64_t mem_heap_used = p_atomic_read(&mem_heap->used);
18847ec681f3Smrg   if (mem_heap_used > mem_heap->size)
18857ec681f3Smrg      return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
18867ec681f3Smrg
18877ec681f3Smrg   mem = vk_object_alloc(&device->vk, pAllocator, sizeof(*mem),
18887ec681f3Smrg                         VK_OBJECT_TYPE_DEVICE_MEMORY);
1889361fc4cbSmaya   if (mem == NULL)
18907ec681f3Smrg      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1891361fc4cbSmaya
1892361fc4cbSmaya   const VkImportMemoryFdInfoKHR *fd_info =
1893361fc4cbSmaya      vk_find_struct_const(pAllocateInfo->pNext, IMPORT_MEMORY_FD_INFO_KHR);
1894361fc4cbSmaya   if (fd_info && !fd_info->handleType)
1895361fc4cbSmaya      fd_info = NULL;
1896361fc4cbSmaya
1897361fc4cbSmaya   if (fd_info) {
1898361fc4cbSmaya      assert(fd_info->handleType ==
1899361fc4cbSmaya                VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
1900361fc4cbSmaya             fd_info->handleType ==
1901361fc4cbSmaya                VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
1902361fc4cbSmaya
1903361fc4cbSmaya      /*
1904361fc4cbSmaya       * TODO Importing the same fd twice gives us the same handle without
1905361fc4cbSmaya       * reference counting.  We need to maintain a per-instance handle-to-bo
1906361fc4cbSmaya       * table and add reference count to tu_bo.
1907361fc4cbSmaya       */
1908361fc4cbSmaya      result = tu_bo_init_dmabuf(device, &mem->bo,
1909361fc4cbSmaya                                 pAllocateInfo->allocationSize, fd_info->fd);
1910361fc4cbSmaya      if (result == VK_SUCCESS) {
1911361fc4cbSmaya         /* take ownership and close the fd */
1912361fc4cbSmaya         close(fd_info->fd);
1913361fc4cbSmaya      }
1914361fc4cbSmaya   } else {
1915361fc4cbSmaya      result =
19167ec681f3Smrg         tu_bo_init_new(device, &mem->bo, pAllocateInfo->allocationSize,
19177ec681f3Smrg                        TU_BO_ALLOC_NO_FLAGS);
19187ec681f3Smrg   }
19197ec681f3Smrg
19207ec681f3Smrg
19217ec681f3Smrg   if (result == VK_SUCCESS) {
19227ec681f3Smrg      mem_heap_used = p_atomic_add_return(&mem_heap->used, mem->bo.size);
19237ec681f3Smrg      if (mem_heap_used > mem_heap->size) {
19247ec681f3Smrg         p_atomic_add(&mem_heap->used, -mem->bo.size);
19257ec681f3Smrg         tu_bo_finish(device, &mem->bo);
19267ec681f3Smrg         result = vk_errorf(device, VK_ERROR_OUT_OF_DEVICE_MEMORY,
19277ec681f3Smrg                            "Out of heap memory");
19287ec681f3Smrg      }
1929361fc4cbSmaya   }
1930361fc4cbSmaya
1931361fc4cbSmaya   if (result != VK_SUCCESS) {
19327ec681f3Smrg      vk_object_free(&device->vk, pAllocator, mem);
1933361fc4cbSmaya      return result;
1934361fc4cbSmaya   }
1935361fc4cbSmaya
1936361fc4cbSmaya   *pMem = tu_device_memory_to_handle(mem);
1937361fc4cbSmaya
1938361fc4cbSmaya   return VK_SUCCESS;
1939361fc4cbSmaya}
1940361fc4cbSmaya
19417ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
1942361fc4cbSmayatu_FreeMemory(VkDevice _device,
1943361fc4cbSmaya              VkDeviceMemory _mem,
1944361fc4cbSmaya              const VkAllocationCallbacks *pAllocator)
1945361fc4cbSmaya{
1946361fc4cbSmaya   TU_FROM_HANDLE(tu_device, device, _device);
1947361fc4cbSmaya   TU_FROM_HANDLE(tu_device_memory, mem, _mem);
1948361fc4cbSmaya
1949361fc4cbSmaya   if (mem == NULL)
1950361fc4cbSmaya      return;
1951361fc4cbSmaya
19527ec681f3Smrg   p_atomic_add(&device->physical_device->heap.used, -mem->bo.size);
1953361fc4cbSmaya   tu_bo_finish(device, &mem->bo);
19547ec681f3Smrg   vk_object_free(&device->vk, pAllocator, mem);
1955361fc4cbSmaya}
1956361fc4cbSmaya
19577ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
1958361fc4cbSmayatu_MapMemory(VkDevice _device,
1959361fc4cbSmaya             VkDeviceMemory _memory,
1960361fc4cbSmaya             VkDeviceSize offset,
1961361fc4cbSmaya             VkDeviceSize size,
1962361fc4cbSmaya             VkMemoryMapFlags flags,
1963361fc4cbSmaya             void **ppData)
1964361fc4cbSmaya{
1965361fc4cbSmaya   TU_FROM_HANDLE(tu_device, device, _device);
1966361fc4cbSmaya   TU_FROM_HANDLE(tu_device_memory, mem, _memory);
1967361fc4cbSmaya   VkResult result;
1968361fc4cbSmaya
1969361fc4cbSmaya   if (mem == NULL) {
1970361fc4cbSmaya      *ppData = NULL;
1971361fc4cbSmaya      return VK_SUCCESS;
1972361fc4cbSmaya   }
1973361fc4cbSmaya
19747ec681f3Smrg   if (!mem->bo.map) {
1975361fc4cbSmaya      result = tu_bo_map(device, &mem->bo);
1976361fc4cbSmaya      if (result != VK_SUCCESS)
1977361fc4cbSmaya         return result;
1978361fc4cbSmaya   }
1979361fc4cbSmaya
19807ec681f3Smrg   *ppData = mem->bo.map + offset;
19817ec681f3Smrg   return VK_SUCCESS;
1982361fc4cbSmaya}
1983361fc4cbSmaya
19847ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
1985361fc4cbSmayatu_UnmapMemory(VkDevice _device, VkDeviceMemory _memory)
1986361fc4cbSmaya{
19877ec681f3Smrg   /* TODO: unmap here instead of waiting for FreeMemory */
1988361fc4cbSmaya}
1989361fc4cbSmaya
19907ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
1991361fc4cbSmayatu_FlushMappedMemoryRanges(VkDevice _device,
1992361fc4cbSmaya                           uint32_t memoryRangeCount,
1993361fc4cbSmaya                           const VkMappedMemoryRange *pMemoryRanges)
1994361fc4cbSmaya{
1995361fc4cbSmaya   return VK_SUCCESS;
1996361fc4cbSmaya}
1997361fc4cbSmaya
19987ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
1999361fc4cbSmayatu_InvalidateMappedMemoryRanges(VkDevice _device,
2000361fc4cbSmaya                                uint32_t memoryRangeCount,
2001361fc4cbSmaya                                const VkMappedMemoryRange *pMemoryRanges)
2002361fc4cbSmaya{
2003361fc4cbSmaya   return VK_SUCCESS;
2004361fc4cbSmaya}
2005361fc4cbSmaya
20067ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
2007361fc4cbSmayatu_GetBufferMemoryRequirements2(
2008361fc4cbSmaya   VkDevice device,
2009361fc4cbSmaya   const VkBufferMemoryRequirementsInfo2 *pInfo,
2010361fc4cbSmaya   VkMemoryRequirements2 *pMemoryRequirements)
2011361fc4cbSmaya{
20127ec681f3Smrg   TU_FROM_HANDLE(tu_buffer, buffer, pInfo->buffer);
2013361fc4cbSmaya
20147ec681f3Smrg   pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
20157ec681f3Smrg      .memoryTypeBits = 1,
20167ec681f3Smrg      .alignment = 64,
20177ec681f3Smrg      .size = MAX2(align64(buffer->size, 64), buffer->size),
20187ec681f3Smrg   };
2019361fc4cbSmaya
20207ec681f3Smrg   vk_foreach_struct(ext, pMemoryRequirements->pNext) {
20217ec681f3Smrg      switch (ext->sType) {
20227ec681f3Smrg      case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
20237ec681f3Smrg         VkMemoryDedicatedRequirements *req =
20247ec681f3Smrg            (VkMemoryDedicatedRequirements *) ext;
20257ec681f3Smrg         req->requiresDedicatedAllocation = false;
20267ec681f3Smrg         req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;
20277ec681f3Smrg         break;
20287ec681f3Smrg      }
20297ec681f3Smrg      default:
20307ec681f3Smrg         break;
20317ec681f3Smrg      }
20327ec681f3Smrg   }
2033361fc4cbSmaya}
2034361fc4cbSmaya
20357ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
2036361fc4cbSmayatu_GetImageMemoryRequirements2(VkDevice device,
2037361fc4cbSmaya                               const VkImageMemoryRequirementsInfo2 *pInfo,
2038361fc4cbSmaya                               VkMemoryRequirements2 *pMemoryRequirements)
2039361fc4cbSmaya{
20407ec681f3Smrg   TU_FROM_HANDLE(tu_image, image, pInfo->image);
2041361fc4cbSmaya
20427ec681f3Smrg   pMemoryRequirements->memoryRequirements = (VkMemoryRequirements) {
20437ec681f3Smrg      .memoryTypeBits = 1,
20447ec681f3Smrg      .alignment = image->layout[0].base_align,
20457ec681f3Smrg      .size = image->total_size
20467ec681f3Smrg   };
20477ec681f3Smrg
20487ec681f3Smrg   vk_foreach_struct(ext, pMemoryRequirements->pNext) {
20497ec681f3Smrg      switch (ext->sType) {
20507ec681f3Smrg      case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: {
20517ec681f3Smrg         VkMemoryDedicatedRequirements *req =
20527ec681f3Smrg            (VkMemoryDedicatedRequirements *) ext;
20537ec681f3Smrg         req->requiresDedicatedAllocation = image->shareable;
20547ec681f3Smrg         req->prefersDedicatedAllocation = req->requiresDedicatedAllocation;
20557ec681f3Smrg         break;
20567ec681f3Smrg      }
20577ec681f3Smrg      default:
20587ec681f3Smrg         break;
20597ec681f3Smrg      }
20607ec681f3Smrg   }
2061361fc4cbSmaya}
2062361fc4cbSmaya
20637ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
2064361fc4cbSmayatu_GetImageSparseMemoryRequirements2(
2065361fc4cbSmaya   VkDevice device,
2066361fc4cbSmaya   const VkImageSparseMemoryRequirementsInfo2 *pInfo,
2067361fc4cbSmaya   uint32_t *pSparseMemoryRequirementCount,
2068361fc4cbSmaya   VkSparseImageMemoryRequirements2 *pSparseMemoryRequirements)
2069361fc4cbSmaya{
2070361fc4cbSmaya   tu_stub();
2071361fc4cbSmaya}
2072361fc4cbSmaya
20737ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
2074361fc4cbSmayatu_GetDeviceMemoryCommitment(VkDevice device,
2075361fc4cbSmaya                             VkDeviceMemory memory,
2076361fc4cbSmaya                             VkDeviceSize *pCommittedMemoryInBytes)
2077361fc4cbSmaya{
2078361fc4cbSmaya   *pCommittedMemoryInBytes = 0;
2079361fc4cbSmaya}
2080361fc4cbSmaya
20817ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
2082361fc4cbSmayatu_BindBufferMemory2(VkDevice device,
2083361fc4cbSmaya                     uint32_t bindInfoCount,
2084361fc4cbSmaya                     const VkBindBufferMemoryInfo *pBindInfos)
2085361fc4cbSmaya{
2086361fc4cbSmaya   for (uint32_t i = 0; i < bindInfoCount; ++i) {
2087361fc4cbSmaya      TU_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);
2088361fc4cbSmaya      TU_FROM_HANDLE(tu_buffer, buffer, pBindInfos[i].buffer);
2089361fc4cbSmaya
2090361fc4cbSmaya      if (mem) {
2091361fc4cbSmaya         buffer->bo = &mem->bo;
2092361fc4cbSmaya         buffer->bo_offset = pBindInfos[i].memoryOffset;
2093361fc4cbSmaya      } else {
2094361fc4cbSmaya         buffer->bo = NULL;
2095361fc4cbSmaya      }
2096361fc4cbSmaya   }
2097361fc4cbSmaya   return VK_SUCCESS;
2098361fc4cbSmaya}
2099361fc4cbSmaya
21007ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
2101361fc4cbSmayatu_BindImageMemory2(VkDevice device,
2102361fc4cbSmaya                    uint32_t bindInfoCount,
2103361fc4cbSmaya                    const VkBindImageMemoryInfo *pBindInfos)
2104361fc4cbSmaya{
2105361fc4cbSmaya   for (uint32_t i = 0; i < bindInfoCount; ++i) {
2106361fc4cbSmaya      TU_FROM_HANDLE(tu_image, image, pBindInfos[i].image);
2107361fc4cbSmaya      TU_FROM_HANDLE(tu_device_memory, mem, pBindInfos[i].memory);
2108361fc4cbSmaya
2109361fc4cbSmaya      if (mem) {
2110361fc4cbSmaya         image->bo = &mem->bo;
2111361fc4cbSmaya         image->bo_offset = pBindInfos[i].memoryOffset;
2112361fc4cbSmaya      } else {
2113361fc4cbSmaya         image->bo = NULL;
2114361fc4cbSmaya         image->bo_offset = 0;
2115361fc4cbSmaya      }
2116361fc4cbSmaya   }
2117361fc4cbSmaya
2118361fc4cbSmaya   return VK_SUCCESS;
2119361fc4cbSmaya}
2120361fc4cbSmaya
21217ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
2122361fc4cbSmayatu_QueueBindSparse(VkQueue _queue,
2123361fc4cbSmaya                   uint32_t bindInfoCount,
2124361fc4cbSmaya                   const VkBindSparseInfo *pBindInfo,
2125361fc4cbSmaya                   VkFence _fence)
2126361fc4cbSmaya{
2127361fc4cbSmaya   return VK_SUCCESS;
2128361fc4cbSmaya}
2129361fc4cbSmaya
21307ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
2131361fc4cbSmayatu_CreateEvent(VkDevice _device,
2132361fc4cbSmaya               const VkEventCreateInfo *pCreateInfo,
2133361fc4cbSmaya               const VkAllocationCallbacks *pAllocator,
2134361fc4cbSmaya               VkEvent *pEvent)
2135361fc4cbSmaya{
2136361fc4cbSmaya   TU_FROM_HANDLE(tu_device, device, _device);
2137361fc4cbSmaya
21387ec681f3Smrg   struct tu_event *event =
21397ec681f3Smrg         vk_object_alloc(&device->vk, pAllocator, sizeof(*event),
21407ec681f3Smrg                         VK_OBJECT_TYPE_EVENT);
2141361fc4cbSmaya   if (!event)
21427ec681f3Smrg      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
21437ec681f3Smrg
21447ec681f3Smrg   VkResult result = tu_bo_init_new(device, &event->bo, 0x1000,
21457ec681f3Smrg                                    TU_BO_ALLOC_NO_FLAGS);
21467ec681f3Smrg   if (result != VK_SUCCESS)
21477ec681f3Smrg      goto fail_alloc;
21487ec681f3Smrg
21497ec681f3Smrg   result = tu_bo_map(device, &event->bo);
21507ec681f3Smrg   if (result != VK_SUCCESS)
21517ec681f3Smrg      goto fail_map;
2152361fc4cbSmaya
2153361fc4cbSmaya   *pEvent = tu_event_to_handle(event);
2154361fc4cbSmaya
2155361fc4cbSmaya   return VK_SUCCESS;
21567ec681f3Smrg
21577ec681f3Smrgfail_map:
21587ec681f3Smrg   tu_bo_finish(device, &event->bo);
21597ec681f3Smrgfail_alloc:
21607ec681f3Smrg   vk_object_free(&device->vk, pAllocator, event);
21617ec681f3Smrg   return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2162361fc4cbSmaya}
2163361fc4cbSmaya
21647ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
2165361fc4cbSmayatu_DestroyEvent(VkDevice _device,
2166361fc4cbSmaya                VkEvent _event,
2167361fc4cbSmaya                const VkAllocationCallbacks *pAllocator)
2168361fc4cbSmaya{
2169361fc4cbSmaya   TU_FROM_HANDLE(tu_device, device, _device);
2170361fc4cbSmaya   TU_FROM_HANDLE(tu_event, event, _event);
2171361fc4cbSmaya
2172361fc4cbSmaya   if (!event)
2173361fc4cbSmaya      return;
21747ec681f3Smrg
21757ec681f3Smrg   tu_bo_finish(device, &event->bo);
21767ec681f3Smrg   vk_object_free(&device->vk, pAllocator, event);
2177361fc4cbSmaya}
2178361fc4cbSmaya
21797ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
2180361fc4cbSmayatu_GetEventStatus(VkDevice _device, VkEvent _event)
2181361fc4cbSmaya{
2182361fc4cbSmaya   TU_FROM_HANDLE(tu_event, event, _event);
2183361fc4cbSmaya
21847ec681f3Smrg   if (*(uint64_t*) event->bo.map == 1)
2185361fc4cbSmaya      return VK_EVENT_SET;
2186361fc4cbSmaya   return VK_EVENT_RESET;
2187361fc4cbSmaya}
2188361fc4cbSmaya
21897ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
2190361fc4cbSmayatu_SetEvent(VkDevice _device, VkEvent _event)
2191361fc4cbSmaya{
2192361fc4cbSmaya   TU_FROM_HANDLE(tu_event, event, _event);
21937ec681f3Smrg   *(uint64_t*) event->bo.map = 1;
2194361fc4cbSmaya
2195361fc4cbSmaya   return VK_SUCCESS;
2196361fc4cbSmaya}
2197361fc4cbSmaya
21987ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
2199361fc4cbSmayatu_ResetEvent(VkDevice _device, VkEvent _event)
2200361fc4cbSmaya{
2201361fc4cbSmaya   TU_FROM_HANDLE(tu_event, event, _event);
22027ec681f3Smrg   *(uint64_t*) event->bo.map = 0;
2203361fc4cbSmaya
2204361fc4cbSmaya   return VK_SUCCESS;
2205361fc4cbSmaya}
2206361fc4cbSmaya
22077ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
2208361fc4cbSmayatu_CreateBuffer(VkDevice _device,
2209361fc4cbSmaya                const VkBufferCreateInfo *pCreateInfo,
2210361fc4cbSmaya                const VkAllocationCallbacks *pAllocator,
2211361fc4cbSmaya                VkBuffer *pBuffer)
2212361fc4cbSmaya{
2213361fc4cbSmaya   TU_FROM_HANDLE(tu_device, device, _device);
2214361fc4cbSmaya   struct tu_buffer *buffer;
2215361fc4cbSmaya
2216361fc4cbSmaya   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
2217361fc4cbSmaya
22187ec681f3Smrg   buffer = vk_object_alloc(&device->vk, pAllocator, sizeof(*buffer),
22197ec681f3Smrg                            VK_OBJECT_TYPE_BUFFER);
2220361fc4cbSmaya   if (buffer == NULL)
22217ec681f3Smrg      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2222361fc4cbSmaya
2223361fc4cbSmaya   buffer->size = pCreateInfo->size;
2224361fc4cbSmaya   buffer->usage = pCreateInfo->usage;
2225361fc4cbSmaya   buffer->flags = pCreateInfo->flags;
2226361fc4cbSmaya
2227361fc4cbSmaya   *pBuffer = tu_buffer_to_handle(buffer);
2228361fc4cbSmaya
2229361fc4cbSmaya   return VK_SUCCESS;
2230361fc4cbSmaya}
2231361fc4cbSmaya
22327ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
2233361fc4cbSmayatu_DestroyBuffer(VkDevice _device,
2234361fc4cbSmaya                 VkBuffer _buffer,
2235361fc4cbSmaya                 const VkAllocationCallbacks *pAllocator)
2236361fc4cbSmaya{
2237361fc4cbSmaya   TU_FROM_HANDLE(tu_device, device, _device);
2238361fc4cbSmaya   TU_FROM_HANDLE(tu_buffer, buffer, _buffer);
2239361fc4cbSmaya
2240361fc4cbSmaya   if (!buffer)
2241361fc4cbSmaya      return;
2242361fc4cbSmaya
22437ec681f3Smrg   vk_object_free(&device->vk, pAllocator, buffer);
2244361fc4cbSmaya}
2245361fc4cbSmaya
22467ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
2247361fc4cbSmayatu_CreateFramebuffer(VkDevice _device,
2248361fc4cbSmaya                     const VkFramebufferCreateInfo *pCreateInfo,
2249361fc4cbSmaya                     const VkAllocationCallbacks *pAllocator,
2250361fc4cbSmaya                     VkFramebuffer *pFramebuffer)
2251361fc4cbSmaya{
2252361fc4cbSmaya   TU_FROM_HANDLE(tu_device, device, _device);
22537ec681f3Smrg   TU_FROM_HANDLE(tu_render_pass, pass, pCreateInfo->renderPass);
2254361fc4cbSmaya   struct tu_framebuffer *framebuffer;
2255361fc4cbSmaya
2256361fc4cbSmaya   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO);
2257361fc4cbSmaya
22587ec681f3Smrg   bool imageless = pCreateInfo->flags & VK_FRAMEBUFFER_CREATE_IMAGELESS_BIT;
22597ec681f3Smrg
22607ec681f3Smrg   size_t size = sizeof(*framebuffer);
22617ec681f3Smrg   if (!imageless)
22627ec681f3Smrg      size += sizeof(struct tu_attachment_info) * pCreateInfo->attachmentCount;
22637ec681f3Smrg   framebuffer = vk_object_alloc(&device->vk, pAllocator, size,
22647ec681f3Smrg                                 VK_OBJECT_TYPE_FRAMEBUFFER);
2265361fc4cbSmaya   if (framebuffer == NULL)
22667ec681f3Smrg      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2267361fc4cbSmaya
2268361fc4cbSmaya   framebuffer->attachment_count = pCreateInfo->attachmentCount;
2269361fc4cbSmaya   framebuffer->width = pCreateInfo->width;
2270361fc4cbSmaya   framebuffer->height = pCreateInfo->height;
2271361fc4cbSmaya   framebuffer->layers = pCreateInfo->layers;
22727ec681f3Smrg
22737ec681f3Smrg   if (!imageless) {
22747ec681f3Smrg      for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) {
22757ec681f3Smrg         VkImageView _iview = pCreateInfo->pAttachments[i];
22767ec681f3Smrg         struct tu_image_view *iview = tu_image_view_from_handle(_iview);
22777ec681f3Smrg         framebuffer->attachments[i].attachment = iview;
22787ec681f3Smrg      }
2279361fc4cbSmaya   }
2280361fc4cbSmaya
22817ec681f3Smrg   tu_framebuffer_tiling_config(framebuffer, device, pass);
22827ec681f3Smrg
2283361fc4cbSmaya   *pFramebuffer = tu_framebuffer_to_handle(framebuffer);
2284361fc4cbSmaya   return VK_SUCCESS;
2285361fc4cbSmaya}
2286361fc4cbSmaya
22877ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
2288361fc4cbSmayatu_DestroyFramebuffer(VkDevice _device,
2289361fc4cbSmaya                      VkFramebuffer _fb,
2290361fc4cbSmaya                      const VkAllocationCallbacks *pAllocator)
2291361fc4cbSmaya{
2292361fc4cbSmaya   TU_FROM_HANDLE(tu_device, device, _device);
2293361fc4cbSmaya   TU_FROM_HANDLE(tu_framebuffer, fb, _fb);
2294361fc4cbSmaya
2295361fc4cbSmaya   if (!fb)
2296361fc4cbSmaya      return;
22977ec681f3Smrg
22987ec681f3Smrg   vk_object_free(&device->vk, pAllocator, fb);
2299361fc4cbSmaya}
2300361fc4cbSmaya
2301361fc4cbSmayastatic void
2302361fc4cbSmayatu_init_sampler(struct tu_device *device,
2303361fc4cbSmaya                struct tu_sampler *sampler,
2304361fc4cbSmaya                const VkSamplerCreateInfo *pCreateInfo)
2305361fc4cbSmaya{
23067ec681f3Smrg   const struct VkSamplerReductionModeCreateInfo *reduction =
23077ec681f3Smrg      vk_find_struct_const(pCreateInfo->pNext, SAMPLER_REDUCTION_MODE_CREATE_INFO);
23087ec681f3Smrg   const struct VkSamplerYcbcrConversionInfo *ycbcr_conversion =
23097ec681f3Smrg      vk_find_struct_const(pCreateInfo->pNext,  SAMPLER_YCBCR_CONVERSION_INFO);
23107ec681f3Smrg   const VkSamplerCustomBorderColorCreateInfoEXT *custom_border_color =
23117ec681f3Smrg      vk_find_struct_const(pCreateInfo->pNext, SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT);
23127ec681f3Smrg   /* for non-custom border colors, the VK enum is translated directly to an offset in
23137ec681f3Smrg    * the border color buffer. custom border colors are located immediately after the
23147ec681f3Smrg    * builtin colors, and thus an offset of TU_BORDER_COLOR_BUILTIN is added.
23157ec681f3Smrg    */
23167ec681f3Smrg   uint32_t border_color = (unsigned) pCreateInfo->borderColor;
23177ec681f3Smrg   if (pCreateInfo->borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT ||
23187ec681f3Smrg       pCreateInfo->borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT) {
23197ec681f3Smrg      mtx_lock(&device->mutex);
23207ec681f3Smrg      border_color = BITSET_FFS(device->custom_border_color);
23217ec681f3Smrg      BITSET_CLEAR(device->custom_border_color, border_color);
23227ec681f3Smrg      mtx_unlock(&device->mutex);
23237ec681f3Smrg      tu6_pack_border_color(device->global_bo.map + gb_offset(bcolor[border_color]),
23247ec681f3Smrg                            &custom_border_color->customBorderColor,
23257ec681f3Smrg                            pCreateInfo->borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT);
23267ec681f3Smrg      border_color += TU_BORDER_COLOR_BUILTIN;
23277ec681f3Smrg   }
23287ec681f3Smrg
23297ec681f3Smrg   unsigned aniso = pCreateInfo->anisotropyEnable ?
23307ec681f3Smrg      util_last_bit(MIN2((uint32_t)pCreateInfo->maxAnisotropy >> 1, 8)) : 0;
23317ec681f3Smrg   bool miplinear = (pCreateInfo->mipmapMode == VK_SAMPLER_MIPMAP_MODE_LINEAR);
23327ec681f3Smrg   float min_lod = CLAMP(pCreateInfo->minLod, 0.0f, 4095.0f / 256.0f);
23337ec681f3Smrg   float max_lod = CLAMP(pCreateInfo->maxLod, 0.0f, 4095.0f / 256.0f);
23347ec681f3Smrg
23357ec681f3Smrg   sampler->descriptor[0] =
23367ec681f3Smrg      COND(miplinear, A6XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR) |
23377ec681f3Smrg      A6XX_TEX_SAMP_0_XY_MAG(tu6_tex_filter(pCreateInfo->magFilter, aniso)) |
23387ec681f3Smrg      A6XX_TEX_SAMP_0_XY_MIN(tu6_tex_filter(pCreateInfo->minFilter, aniso)) |
23397ec681f3Smrg      A6XX_TEX_SAMP_0_ANISO(aniso) |
23407ec681f3Smrg      A6XX_TEX_SAMP_0_WRAP_S(tu6_tex_wrap(pCreateInfo->addressModeU)) |
23417ec681f3Smrg      A6XX_TEX_SAMP_0_WRAP_T(tu6_tex_wrap(pCreateInfo->addressModeV)) |
23427ec681f3Smrg      A6XX_TEX_SAMP_0_WRAP_R(tu6_tex_wrap(pCreateInfo->addressModeW)) |
23437ec681f3Smrg      A6XX_TEX_SAMP_0_LOD_BIAS(pCreateInfo->mipLodBias);
23447ec681f3Smrg   sampler->descriptor[1] =
23457ec681f3Smrg      /* COND(!cso->seamless_cube_map, A6XX_TEX_SAMP_1_CUBEMAPSEAMLESSFILTOFF) | */
23467ec681f3Smrg      COND(pCreateInfo->unnormalizedCoordinates, A6XX_TEX_SAMP_1_UNNORM_COORDS) |
23477ec681f3Smrg      A6XX_TEX_SAMP_1_MIN_LOD(min_lod) |
23487ec681f3Smrg      A6XX_TEX_SAMP_1_MAX_LOD(max_lod) |
23497ec681f3Smrg      COND(pCreateInfo->compareEnable,
23507ec681f3Smrg           A6XX_TEX_SAMP_1_COMPARE_FUNC(tu6_compare_func(pCreateInfo->compareOp)));
23517ec681f3Smrg   sampler->descriptor[2] = A6XX_TEX_SAMP_2_BCOLOR(border_color);
23527ec681f3Smrg   sampler->descriptor[3] = 0;
23537ec681f3Smrg
23547ec681f3Smrg   if (reduction) {
23557ec681f3Smrg      sampler->descriptor[2] |= A6XX_TEX_SAMP_2_REDUCTION_MODE(
23567ec681f3Smrg         tu6_reduction_mode(reduction->reductionMode));
23577ec681f3Smrg   }
23587ec681f3Smrg
23597ec681f3Smrg   sampler->ycbcr_sampler = ycbcr_conversion ?
23607ec681f3Smrg      tu_sampler_ycbcr_conversion_from_handle(ycbcr_conversion->conversion) : NULL;
23617ec681f3Smrg
23627ec681f3Smrg   if (sampler->ycbcr_sampler &&
23637ec681f3Smrg       sampler->ycbcr_sampler->chroma_filter == VK_FILTER_LINEAR) {
23647ec681f3Smrg      sampler->descriptor[2] |= A6XX_TEX_SAMP_2_CHROMA_LINEAR;
23657ec681f3Smrg   }
23667ec681f3Smrg
23677ec681f3Smrg   /* TODO:
23687ec681f3Smrg    * A6XX_TEX_SAMP_1_MIPFILTER_LINEAR_FAR disables mipmapping, but vk has no NONE mipfilter?
23697ec681f3Smrg    */
2370361fc4cbSmaya}
2371361fc4cbSmaya
23727ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
2373361fc4cbSmayatu_CreateSampler(VkDevice _device,
2374361fc4cbSmaya                 const VkSamplerCreateInfo *pCreateInfo,
2375361fc4cbSmaya                 const VkAllocationCallbacks *pAllocator,
2376361fc4cbSmaya                 VkSampler *pSampler)
2377361fc4cbSmaya{
2378361fc4cbSmaya   TU_FROM_HANDLE(tu_device, device, _device);
2379361fc4cbSmaya   struct tu_sampler *sampler;
2380361fc4cbSmaya
2381361fc4cbSmaya   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
2382361fc4cbSmaya
23837ec681f3Smrg   sampler = vk_object_alloc(&device->vk, pAllocator, sizeof(*sampler),
23847ec681f3Smrg                             VK_OBJECT_TYPE_SAMPLER);
2385361fc4cbSmaya   if (!sampler)
23867ec681f3Smrg      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
2387361fc4cbSmaya
2388361fc4cbSmaya   tu_init_sampler(device, sampler, pCreateInfo);
2389361fc4cbSmaya   *pSampler = tu_sampler_to_handle(sampler);
2390361fc4cbSmaya
2391361fc4cbSmaya   return VK_SUCCESS;
2392361fc4cbSmaya}
2393361fc4cbSmaya
23947ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
2395361fc4cbSmayatu_DestroySampler(VkDevice _device,
2396361fc4cbSmaya                  VkSampler _sampler,
2397361fc4cbSmaya                  const VkAllocationCallbacks *pAllocator)
2398361fc4cbSmaya{
2399361fc4cbSmaya   TU_FROM_HANDLE(tu_device, device, _device);
2400361fc4cbSmaya   TU_FROM_HANDLE(tu_sampler, sampler, _sampler);
24017ec681f3Smrg   uint32_t border_color;
2402361fc4cbSmaya
2403361fc4cbSmaya   if (!sampler)
2404361fc4cbSmaya      return;
24057ec681f3Smrg
24067ec681f3Smrg   border_color = (sampler->descriptor[2] & A6XX_TEX_SAMP_2_BCOLOR__MASK) >> A6XX_TEX_SAMP_2_BCOLOR__SHIFT;
24077ec681f3Smrg   if (border_color >= TU_BORDER_COLOR_BUILTIN) {
24087ec681f3Smrg      border_color -= TU_BORDER_COLOR_BUILTIN;
24097ec681f3Smrg      /* if the sampler had a custom border color, free it. TODO: no lock */
24107ec681f3Smrg      mtx_lock(&device->mutex);
24117ec681f3Smrg      assert(!BITSET_TEST(device->custom_border_color, border_color));
24127ec681f3Smrg      BITSET_SET(device->custom_border_color, border_color);
24137ec681f3Smrg      mtx_unlock(&device->mutex);
24147ec681f3Smrg   }
24157ec681f3Smrg
24167ec681f3Smrg   vk_object_free(&device->vk, pAllocator, sampler);
2417361fc4cbSmaya}
2418361fc4cbSmaya
2419361fc4cbSmaya/* vk_icd.h does not declare this function, so we declare it here to
2420361fc4cbSmaya * suppress Wmissing-prototypes.
2421361fc4cbSmaya */
2422361fc4cbSmayaPUBLIC VKAPI_ATTR VkResult VKAPI_CALL
2423361fc4cbSmayavk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion);
2424361fc4cbSmaya
2425361fc4cbSmayaPUBLIC VKAPI_ATTR VkResult VKAPI_CALL
2426361fc4cbSmayavk_icdNegotiateLoaderICDInterfaceVersion(uint32_t *pSupportedVersion)
2427361fc4cbSmaya{
2428361fc4cbSmaya   /* For the full details on loader interface versioning, see
2429361fc4cbSmaya    * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>.
2430361fc4cbSmaya    * What follows is a condensed summary, to help you navigate the large and
2431361fc4cbSmaya    * confusing official doc.
2432361fc4cbSmaya    *
2433361fc4cbSmaya    *   - Loader interface v0 is incompatible with later versions. We don't
2434361fc4cbSmaya    *     support it.
2435361fc4cbSmaya    *
2436361fc4cbSmaya    *   - In loader interface v1:
2437361fc4cbSmaya    *       - The first ICD entrypoint called by the loader is
2438361fc4cbSmaya    *         vk_icdGetInstanceProcAddr(). The ICD must statically expose this
2439361fc4cbSmaya    *         entrypoint.
2440361fc4cbSmaya    *       - The ICD must statically expose no other Vulkan symbol unless it
2441361fc4cbSmaya    * is linked with -Bsymbolic.
2442361fc4cbSmaya    *       - Each dispatchable Vulkan handle created by the ICD must be
2443361fc4cbSmaya    *         a pointer to a struct whose first member is VK_LOADER_DATA. The
2444361fc4cbSmaya    *         ICD must initialize VK_LOADER_DATA.loadMagic to
2445361fc4cbSmaya    * ICD_LOADER_MAGIC.
2446361fc4cbSmaya    *       - The loader implements vkCreate{PLATFORM}SurfaceKHR() and
2447361fc4cbSmaya    *         vkDestroySurfaceKHR(). The ICD must be capable of working with
2448361fc4cbSmaya    *         such loader-managed surfaces.
2449361fc4cbSmaya    *
2450361fc4cbSmaya    *    - Loader interface v2 differs from v1 in:
2451361fc4cbSmaya    *       - The first ICD entrypoint called by the loader is
2452361fc4cbSmaya    *         vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must
2453361fc4cbSmaya    *         statically expose this entrypoint.
2454361fc4cbSmaya    *
2455361fc4cbSmaya    *    - Loader interface v3 differs from v2 in:
2456361fc4cbSmaya    *        - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(),
2457361fc4cbSmaya    *          vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR,
2458361fc4cbSmaya    *          because the loader no longer does so.
2459361fc4cbSmaya    */
2460361fc4cbSmaya   *pSupportedVersion = MIN2(*pSupportedVersion, 3u);
2461361fc4cbSmaya   return VK_SUCCESS;
2462361fc4cbSmaya}
2463361fc4cbSmaya
24647ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
2465361fc4cbSmayatu_GetMemoryFdKHR(VkDevice _device,
2466361fc4cbSmaya                  const VkMemoryGetFdInfoKHR *pGetFdInfo,
2467361fc4cbSmaya                  int *pFd)
2468361fc4cbSmaya{
2469361fc4cbSmaya   TU_FROM_HANDLE(tu_device, device, _device);
2470361fc4cbSmaya   TU_FROM_HANDLE(tu_device_memory, memory, pGetFdInfo->memory);
2471361fc4cbSmaya
2472361fc4cbSmaya   assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR);
2473361fc4cbSmaya
2474361fc4cbSmaya   /* At the moment, we support only the below handle types. */
2475361fc4cbSmaya   assert(pGetFdInfo->handleType ==
2476361fc4cbSmaya             VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT ||
2477361fc4cbSmaya          pGetFdInfo->handleType ==
2478361fc4cbSmaya             VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
2479361fc4cbSmaya
2480361fc4cbSmaya   int prime_fd = tu_bo_export_dmabuf(device, &memory->bo);
2481361fc4cbSmaya   if (prime_fd < 0)
24827ec681f3Smrg      return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
2483361fc4cbSmaya
2484361fc4cbSmaya   *pFd = prime_fd;
2485361fc4cbSmaya   return VK_SUCCESS;
2486361fc4cbSmaya}
2487361fc4cbSmaya
24887ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
2489361fc4cbSmayatu_GetMemoryFdPropertiesKHR(VkDevice _device,
2490361fc4cbSmaya                            VkExternalMemoryHandleTypeFlagBits handleType,
2491361fc4cbSmaya                            int fd,
2492361fc4cbSmaya                            VkMemoryFdPropertiesKHR *pMemoryFdProperties)
2493361fc4cbSmaya{
2494361fc4cbSmaya   assert(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT);
2495361fc4cbSmaya   pMemoryFdProperties->memoryTypeBits = 1;
2496361fc4cbSmaya   return VK_SUCCESS;
2497361fc4cbSmaya}
2498361fc4cbSmaya
24997ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
2500361fc4cbSmayatu_GetPhysicalDeviceExternalFenceProperties(
2501361fc4cbSmaya   VkPhysicalDevice physicalDevice,
2502361fc4cbSmaya   const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo,
2503361fc4cbSmaya   VkExternalFenceProperties *pExternalFenceProperties)
2504361fc4cbSmaya{
2505361fc4cbSmaya   pExternalFenceProperties->exportFromImportedHandleTypes = 0;
2506361fc4cbSmaya   pExternalFenceProperties->compatibleHandleTypes = 0;
2507361fc4cbSmaya   pExternalFenceProperties->externalFenceFeatures = 0;
2508361fc4cbSmaya}
2509361fc4cbSmaya
25107ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
2511361fc4cbSmayatu_GetDeviceGroupPeerMemoryFeatures(
2512361fc4cbSmaya   VkDevice device,
2513361fc4cbSmaya   uint32_t heapIndex,
2514361fc4cbSmaya   uint32_t localDeviceIndex,
2515361fc4cbSmaya   uint32_t remoteDeviceIndex,
2516361fc4cbSmaya   VkPeerMemoryFeatureFlags *pPeerMemoryFeatures)
2517361fc4cbSmaya{
2518361fc4cbSmaya   assert(localDeviceIndex == remoteDeviceIndex);
2519361fc4cbSmaya
2520361fc4cbSmaya   *pPeerMemoryFeatures = VK_PEER_MEMORY_FEATURE_COPY_SRC_BIT |
2521361fc4cbSmaya                          VK_PEER_MEMORY_FEATURE_COPY_DST_BIT |
2522361fc4cbSmaya                          VK_PEER_MEMORY_FEATURE_GENERIC_SRC_BIT |
2523361fc4cbSmaya                          VK_PEER_MEMORY_FEATURE_GENERIC_DST_BIT;
2524361fc4cbSmaya}
25257ec681f3Smrg
25267ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
25277ec681f3Smrgtu_GetPhysicalDeviceMultisamplePropertiesEXT(
25287ec681f3Smrg   VkPhysicalDevice                            physicalDevice,
25297ec681f3Smrg   VkSampleCountFlagBits                       samples,
25307ec681f3Smrg   VkMultisamplePropertiesEXT*                 pMultisampleProperties)
25317ec681f3Smrg{
25327ec681f3Smrg   TU_FROM_HANDLE(tu_physical_device, pdevice, physicalDevice);
25337ec681f3Smrg
25347ec681f3Smrg   if (samples <= VK_SAMPLE_COUNT_4_BIT && pdevice->vk.supported_extensions.EXT_sample_locations)
25357ec681f3Smrg      pMultisampleProperties->maxSampleLocationGridSize = (VkExtent2D){ 1, 1 };
25367ec681f3Smrg   else
25377ec681f3Smrg      pMultisampleProperties->maxSampleLocationGridSize = (VkExtent2D){ 0, 0 };
25387ec681f3Smrg}
2539