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