17ec681f3Smrg/* 27ec681f3Smrg * Copyright © 2019 Red Hat. 37ec681f3Smrg * 47ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 57ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 67ec681f3Smrg * to deal in the Software without restriction, including without limitation 77ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 87ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 97ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 107ec681f3Smrg * 117ec681f3Smrg * The above copyright notice and this permission notice (including the next 127ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the 137ec681f3Smrg * Software. 147ec681f3Smrg * 157ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 167ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 177ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 187ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 197ec681f3Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 207ec681f3Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 217ec681f3Smrg * IN THE SOFTWARE. 227ec681f3Smrg */ 237ec681f3Smrg 247ec681f3Smrg#include "lvp_private.h" 257ec681f3Smrg 267ec681f3Smrg#include "pipe-loader/pipe_loader.h" 277ec681f3Smrg#include "git_sha1.h" 287ec681f3Smrg#include "vk_util.h" 297ec681f3Smrg#include "pipe/p_config.h" 307ec681f3Smrg#include "pipe/p_defines.h" 317ec681f3Smrg#include "pipe/p_state.h" 327ec681f3Smrg#include "pipe/p_context.h" 337ec681f3Smrg#include "frontend/drisw_api.h" 347ec681f3Smrg 357ec681f3Smrg#include "util/u_inlines.h" 367ec681f3Smrg#include "util/os_memory.h" 377ec681f3Smrg#include "util/u_thread.h" 387ec681f3Smrg#include "util/u_atomic.h" 397ec681f3Smrg#include "util/timespec.h" 407ec681f3Smrg#include "os_time.h" 417ec681f3Smrg 427ec681f3Smrg#if defined(VK_USE_PLATFORM_WAYLAND_KHR) || \ 437ec681f3Smrg defined(VK_USE_PLATFORM_WIN32_KHR) || \ 447ec681f3Smrg defined(VK_USE_PLATFORM_XCB_KHR) || \ 457ec681f3Smrg defined(VK_USE_PLATFORM_XLIB_KHR) 467ec681f3Smrg#define LVP_USE_WSI_PLATFORM 477ec681f3Smrg#endif 487ec681f3Smrg#define LVP_API_VERSION VK_MAKE_VERSION(1, 2, VK_HEADER_VERSION) 497ec681f3Smrg 507ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_EnumerateInstanceVersion(uint32_t* pApiVersion) 517ec681f3Smrg{ 527ec681f3Smrg *pApiVersion = LVP_API_VERSION; 537ec681f3Smrg return VK_SUCCESS; 547ec681f3Smrg} 557ec681f3Smrg 567ec681f3Smrgstatic const struct vk_instance_extension_table lvp_instance_extensions_supported = { 577ec681f3Smrg .KHR_device_group_creation = true, 587ec681f3Smrg .KHR_external_fence_capabilities = true, 597ec681f3Smrg .KHR_external_memory_capabilities = true, 607ec681f3Smrg .KHR_external_semaphore_capabilities = true, 617ec681f3Smrg .KHR_get_physical_device_properties2 = true, 627ec681f3Smrg .EXT_debug_report = true, 637ec681f3Smrg#ifdef LVP_USE_WSI_PLATFORM 647ec681f3Smrg .KHR_get_surface_capabilities2 = true, 657ec681f3Smrg .KHR_surface = true, 667ec681f3Smrg .KHR_surface_protected_capabilities = true, 677ec681f3Smrg#endif 687ec681f3Smrg#ifdef VK_USE_PLATFORM_WAYLAND_KHR 697ec681f3Smrg .KHR_wayland_surface = true, 707ec681f3Smrg#endif 717ec681f3Smrg#ifdef VK_USE_PLATFORM_WIN32_KHR 727ec681f3Smrg .KHR_win32_surface = true, 737ec681f3Smrg#endif 747ec681f3Smrg#ifdef VK_USE_PLATFORM_XCB_KHR 757ec681f3Smrg .KHR_xcb_surface = true, 767ec681f3Smrg#endif 777ec681f3Smrg#ifdef VK_USE_PLATFORM_XLIB_KHR 787ec681f3Smrg .KHR_xlib_surface = true, 797ec681f3Smrg#endif 807ec681f3Smrg}; 817ec681f3Smrg 827ec681f3Smrgstatic const struct vk_device_extension_table lvp_device_extensions_supported = { 837ec681f3Smrg .KHR_8bit_storage = true, 847ec681f3Smrg .KHR_16bit_storage = true, 857ec681f3Smrg .KHR_bind_memory2 = true, 867ec681f3Smrg .KHR_buffer_device_address = true, 877ec681f3Smrg .KHR_create_renderpass2 = true, 887ec681f3Smrg .KHR_copy_commands2 = true, 897ec681f3Smrg .KHR_dedicated_allocation = true, 907ec681f3Smrg .KHR_depth_stencil_resolve = true, 917ec681f3Smrg .KHR_descriptor_update_template = true, 927ec681f3Smrg .KHR_device_group = true, 937ec681f3Smrg .KHR_draw_indirect_count = true, 947ec681f3Smrg .KHR_driver_properties = true, 957ec681f3Smrg .KHR_external_fence = true, 967ec681f3Smrg .KHR_external_memory = true, 977ec681f3Smrg#ifdef PIPE_MEMORY_FD 987ec681f3Smrg .KHR_external_memory_fd = true, 997ec681f3Smrg#endif 1007ec681f3Smrg .KHR_external_semaphore = true, 1017ec681f3Smrg .KHR_shader_float_controls = true, 1027ec681f3Smrg .KHR_get_memory_requirements2 = true, 1037ec681f3Smrg#ifdef LVP_USE_WSI_PLATFORM 1047ec681f3Smrg .KHR_incremental_present = true, 1057ec681f3Smrg#endif 1067ec681f3Smrg .KHR_image_format_list = true, 1077ec681f3Smrg .KHR_imageless_framebuffer = true, 1087ec681f3Smrg .KHR_maintenance1 = true, 1097ec681f3Smrg .KHR_maintenance2 = true, 1107ec681f3Smrg .KHR_maintenance3 = true, 1117ec681f3Smrg .KHR_multiview = true, 1127ec681f3Smrg .KHR_push_descriptor = true, 1137ec681f3Smrg .KHR_relaxed_block_layout = true, 1147ec681f3Smrg .KHR_sampler_mirror_clamp_to_edge = true, 1157ec681f3Smrg .KHR_separate_depth_stencil_layouts = true, 1167ec681f3Smrg .KHR_shader_atomic_int64 = true, 1177ec681f3Smrg .KHR_shader_draw_parameters = true, 1187ec681f3Smrg .KHR_shader_float16_int8 = true, 1197ec681f3Smrg .KHR_shader_subgroup_extended_types = true, 1207ec681f3Smrg .KHR_spirv_1_4 = true, 1217ec681f3Smrg .KHR_storage_buffer_storage_class = true, 1227ec681f3Smrg#ifdef LVP_USE_WSI_PLATFORM 1237ec681f3Smrg .KHR_swapchain = true, 1247ec681f3Smrg#endif 1257ec681f3Smrg .KHR_timeline_semaphore = true, 1267ec681f3Smrg .KHR_uniform_buffer_standard_layout = true, 1277ec681f3Smrg .KHR_variable_pointers = true, 1287ec681f3Smrg .EXT_4444_formats = true, 1297ec681f3Smrg .EXT_calibrated_timestamps = true, 1307ec681f3Smrg .EXT_color_write_enable = true, 1317ec681f3Smrg .EXT_conditional_rendering = true, 1327ec681f3Smrg .EXT_depth_clip_enable = true, 1337ec681f3Smrg .EXT_extended_dynamic_state = true, 1347ec681f3Smrg .EXT_extended_dynamic_state2 = true, 1357ec681f3Smrg .EXT_external_memory_host = true, 1367ec681f3Smrg .EXT_host_query_reset = true, 1377ec681f3Smrg .EXT_index_type_uint8 = true, 1387ec681f3Smrg .EXT_multi_draw = true, 1397ec681f3Smrg .EXT_post_depth_coverage = true, 1407ec681f3Smrg .EXT_private_data = true, 1417ec681f3Smrg .EXT_primitive_topology_list_restart = true, 1427ec681f3Smrg .EXT_sampler_filter_minmax = true, 1437ec681f3Smrg .EXT_scalar_block_layout = true, 1447ec681f3Smrg .EXT_separate_stencil_usage = true, 1457ec681f3Smrg .EXT_shader_stencil_export = true, 1467ec681f3Smrg .EXT_shader_viewport_index_layer = true, 1477ec681f3Smrg .EXT_transform_feedback = true, 1487ec681f3Smrg .EXT_vertex_attribute_divisor = true, 1497ec681f3Smrg .EXT_vertex_input_dynamic_state = true, 1507ec681f3Smrg .EXT_custom_border_color = true, 1517ec681f3Smrg .EXT_provoking_vertex = true, 1527ec681f3Smrg .EXT_line_rasterization = true, 1537ec681f3Smrg .GOOGLE_decorate_string = true, 1547ec681f3Smrg .GOOGLE_hlsl_functionality1 = true, 1557ec681f3Smrg}; 1567ec681f3Smrg 1577ec681f3Smrgstatic VkResult VKAPI_CALL 1587ec681f3Smrglvp_physical_device_init(struct lvp_physical_device *device, 1597ec681f3Smrg struct lvp_instance *instance, 1607ec681f3Smrg struct pipe_loader_device *pld) 1617ec681f3Smrg{ 1627ec681f3Smrg VkResult result; 1637ec681f3Smrg 1647ec681f3Smrg struct vk_physical_device_dispatch_table dispatch_table; 1657ec681f3Smrg vk_physical_device_dispatch_table_from_entrypoints( 1667ec681f3Smrg &dispatch_table, &lvp_physical_device_entrypoints, true); 1677ec681f3Smrg vk_physical_device_dispatch_table_from_entrypoints( 1687ec681f3Smrg &dispatch_table, &wsi_physical_device_entrypoints, false); 1697ec681f3Smrg result = vk_physical_device_init(&device->vk, &instance->vk, 1707ec681f3Smrg NULL, &dispatch_table); 1717ec681f3Smrg if (result != VK_SUCCESS) { 1727ec681f3Smrg vk_error(instance, result); 1737ec681f3Smrg goto fail; 1747ec681f3Smrg } 1757ec681f3Smrg device->pld = pld; 1767ec681f3Smrg 1777ec681f3Smrg device->pscreen = pipe_loader_create_screen_vk(device->pld, true); 1787ec681f3Smrg if (!device->pscreen) 1797ec681f3Smrg return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); 1807ec681f3Smrg 1817ec681f3Smrg device->max_images = device->pscreen->get_shader_param(device->pscreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_MAX_SHADER_IMAGES); 1827ec681f3Smrg device->vk.supported_extensions = lvp_device_extensions_supported; 1837ec681f3Smrg result = lvp_init_wsi(device); 1847ec681f3Smrg if (result != VK_SUCCESS) { 1857ec681f3Smrg vk_physical_device_finish(&device->vk); 1867ec681f3Smrg vk_error(instance, result); 1877ec681f3Smrg goto fail; 1887ec681f3Smrg } 1897ec681f3Smrg 1907ec681f3Smrg return VK_SUCCESS; 1917ec681f3Smrg fail: 1927ec681f3Smrg return result; 1937ec681f3Smrg} 1947ec681f3Smrg 1957ec681f3Smrgstatic void VKAPI_CALL 1967ec681f3Smrglvp_physical_device_finish(struct lvp_physical_device *device) 1977ec681f3Smrg{ 1987ec681f3Smrg lvp_finish_wsi(device); 1997ec681f3Smrg device->pscreen->destroy(device->pscreen); 2007ec681f3Smrg vk_physical_device_finish(&device->vk); 2017ec681f3Smrg} 2027ec681f3Smrg 2037ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_CreateInstance( 2047ec681f3Smrg const VkInstanceCreateInfo* pCreateInfo, 2057ec681f3Smrg const VkAllocationCallbacks* pAllocator, 2067ec681f3Smrg VkInstance* pInstance) 2077ec681f3Smrg{ 2087ec681f3Smrg struct lvp_instance *instance; 2097ec681f3Smrg VkResult result; 2107ec681f3Smrg 2117ec681f3Smrg assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO); 2127ec681f3Smrg 2137ec681f3Smrg if (pAllocator == NULL) 2147ec681f3Smrg pAllocator = vk_default_allocator(); 2157ec681f3Smrg 2167ec681f3Smrg instance = vk_zalloc(pAllocator, sizeof(*instance), 8, 2177ec681f3Smrg VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 2187ec681f3Smrg if (!instance) 2197ec681f3Smrg return vk_error(NULL, VK_ERROR_OUT_OF_HOST_MEMORY); 2207ec681f3Smrg 2217ec681f3Smrg struct vk_instance_dispatch_table dispatch_table; 2227ec681f3Smrg vk_instance_dispatch_table_from_entrypoints( 2237ec681f3Smrg &dispatch_table, &lvp_instance_entrypoints, true); 2247ec681f3Smrg vk_instance_dispatch_table_from_entrypoints( 2257ec681f3Smrg &dispatch_table, &wsi_instance_entrypoints, false); 2267ec681f3Smrg 2277ec681f3Smrg result = vk_instance_init(&instance->vk, 2287ec681f3Smrg &lvp_instance_extensions_supported, 2297ec681f3Smrg &dispatch_table, 2307ec681f3Smrg pCreateInfo, 2317ec681f3Smrg pAllocator); 2327ec681f3Smrg if (result != VK_SUCCESS) { 2337ec681f3Smrg vk_free(pAllocator, instance); 2347ec681f3Smrg return vk_error(instance, result); 2357ec681f3Smrg } 2367ec681f3Smrg 2377ec681f3Smrg instance->apiVersion = LVP_API_VERSION; 2387ec681f3Smrg instance->physicalDeviceCount = -1; 2397ec681f3Smrg 2407ec681f3Smrg // _mesa_locale_init(); 2417ec681f3Smrg // VG(VALGRIND_CREATE_MEMPOOL(instance, 0, false)); 2427ec681f3Smrg 2437ec681f3Smrg *pInstance = lvp_instance_to_handle(instance); 2447ec681f3Smrg 2457ec681f3Smrg return VK_SUCCESS; 2467ec681f3Smrg} 2477ec681f3Smrg 2487ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_DestroyInstance( 2497ec681f3Smrg VkInstance _instance, 2507ec681f3Smrg const VkAllocationCallbacks* pAllocator) 2517ec681f3Smrg{ 2527ec681f3Smrg LVP_FROM_HANDLE(lvp_instance, instance, _instance); 2537ec681f3Smrg 2547ec681f3Smrg if (!instance) 2557ec681f3Smrg return; 2567ec681f3Smrg if (instance->physicalDeviceCount > 0) 2577ec681f3Smrg lvp_physical_device_finish(&instance->physicalDevice); 2587ec681f3Smrg // _mesa_locale_fini(); 2597ec681f3Smrg 2607ec681f3Smrg pipe_loader_release(&instance->devs, instance->num_devices); 2617ec681f3Smrg 2627ec681f3Smrg vk_instance_finish(&instance->vk); 2637ec681f3Smrg vk_free(&instance->vk.alloc, instance); 2647ec681f3Smrg} 2657ec681f3Smrg 2667ec681f3Smrg#if defined(HAVE_PIPE_LOADER_DRI) 2677ec681f3Smrgstatic void lvp_get_image(struct dri_drawable *dri_drawable, 2687ec681f3Smrg int x, int y, unsigned width, unsigned height, unsigned stride, 2697ec681f3Smrg void *data) 2707ec681f3Smrg{ 2717ec681f3Smrg 2727ec681f3Smrg} 2737ec681f3Smrg 2747ec681f3Smrgstatic void lvp_put_image(struct dri_drawable *dri_drawable, 2757ec681f3Smrg void *data, unsigned width, unsigned height) 2767ec681f3Smrg{ 2777ec681f3Smrg fprintf(stderr, "put image %dx%d\n", width, height); 2787ec681f3Smrg} 2797ec681f3Smrg 2807ec681f3Smrgstatic void lvp_put_image2(struct dri_drawable *dri_drawable, 2817ec681f3Smrg void *data, int x, int y, unsigned width, unsigned height, 2827ec681f3Smrg unsigned stride) 2837ec681f3Smrg{ 2847ec681f3Smrg fprintf(stderr, "put image 2 %d,%d %dx%d\n", x, y, width, height); 2857ec681f3Smrg} 2867ec681f3Smrg 2877ec681f3Smrgstatic struct drisw_loader_funcs lvp_sw_lf = { 2887ec681f3Smrg .get_image = lvp_get_image, 2897ec681f3Smrg .put_image = lvp_put_image, 2907ec681f3Smrg .put_image2 = lvp_put_image2, 2917ec681f3Smrg}; 2927ec681f3Smrg#endif 2937ec681f3Smrg 2947ec681f3Smrgstatic VkResult 2957ec681f3Smrglvp_enumerate_physical_devices(struct lvp_instance *instance) 2967ec681f3Smrg{ 2977ec681f3Smrg VkResult result; 2987ec681f3Smrg 2997ec681f3Smrg if (instance->physicalDeviceCount != -1) 3007ec681f3Smrg return VK_SUCCESS; 3017ec681f3Smrg 3027ec681f3Smrg /* sw only for now */ 3037ec681f3Smrg instance->num_devices = pipe_loader_sw_probe(NULL, 0); 3047ec681f3Smrg 3057ec681f3Smrg assert(instance->num_devices == 1); 3067ec681f3Smrg 3077ec681f3Smrg#if defined(HAVE_PIPE_LOADER_DRI) 3087ec681f3Smrg pipe_loader_sw_probe_dri(&instance->devs, &lvp_sw_lf); 3097ec681f3Smrg#else 3107ec681f3Smrg pipe_loader_sw_probe_null(&instance->devs); 3117ec681f3Smrg#endif 3127ec681f3Smrg 3137ec681f3Smrg result = lvp_physical_device_init(&instance->physicalDevice, 3147ec681f3Smrg instance, &instance->devs[0]); 3157ec681f3Smrg if (result == VK_ERROR_INCOMPATIBLE_DRIVER) { 3167ec681f3Smrg instance->physicalDeviceCount = 0; 3177ec681f3Smrg } else if (result == VK_SUCCESS) { 3187ec681f3Smrg instance->physicalDeviceCount = 1; 3197ec681f3Smrg } 3207ec681f3Smrg 3217ec681f3Smrg return result; 3227ec681f3Smrg} 3237ec681f3Smrg 3247ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_EnumeratePhysicalDevices( 3257ec681f3Smrg VkInstance _instance, 3267ec681f3Smrg uint32_t* pPhysicalDeviceCount, 3277ec681f3Smrg VkPhysicalDevice* pPhysicalDevices) 3287ec681f3Smrg{ 3297ec681f3Smrg LVP_FROM_HANDLE(lvp_instance, instance, _instance); 3307ec681f3Smrg VkResult result; 3317ec681f3Smrg 3327ec681f3Smrg result = lvp_enumerate_physical_devices(instance); 3337ec681f3Smrg if (result != VK_SUCCESS) 3347ec681f3Smrg return result; 3357ec681f3Smrg 3367ec681f3Smrg if (!pPhysicalDevices) { 3377ec681f3Smrg *pPhysicalDeviceCount = instance->physicalDeviceCount; 3387ec681f3Smrg } else if (*pPhysicalDeviceCount >= 1) { 3397ec681f3Smrg pPhysicalDevices[0] = lvp_physical_device_to_handle(&instance->physicalDevice); 3407ec681f3Smrg *pPhysicalDeviceCount = 1; 3417ec681f3Smrg } else { 3427ec681f3Smrg *pPhysicalDeviceCount = 0; 3437ec681f3Smrg } 3447ec681f3Smrg 3457ec681f3Smrg return VK_SUCCESS; 3467ec681f3Smrg} 3477ec681f3Smrg 3487ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_EnumeratePhysicalDeviceGroups( 3497ec681f3Smrg VkInstance _instance, 3507ec681f3Smrg uint32_t* pPhysicalDeviceGroupCount, 3517ec681f3Smrg VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) 3527ec681f3Smrg{ 3537ec681f3Smrg LVP_FROM_HANDLE(lvp_instance, instance, _instance); 3547ec681f3Smrg VK_OUTARRAY_MAKE_TYPED(VkPhysicalDeviceGroupProperties, out, 3557ec681f3Smrg pPhysicalDeviceGroupProperties, 3567ec681f3Smrg pPhysicalDeviceGroupCount); 3577ec681f3Smrg 3587ec681f3Smrg VkResult result = lvp_enumerate_physical_devices(instance); 3597ec681f3Smrg if (result != VK_SUCCESS) 3607ec681f3Smrg return result; 3617ec681f3Smrg 3627ec681f3Smrg vk_outarray_append_typed(VkPhysicalDeviceGroupProperties, &out, p) { 3637ec681f3Smrg p->physicalDeviceCount = 1; 3647ec681f3Smrg memset(p->physicalDevices, 0, sizeof(p->physicalDevices)); 3657ec681f3Smrg p->physicalDevices[0] = lvp_physical_device_to_handle(&instance->physicalDevice); 3667ec681f3Smrg p->subsetAllocation = false; 3677ec681f3Smrg } 3687ec681f3Smrg 3697ec681f3Smrg return vk_outarray_status(&out); 3707ec681f3Smrg} 3717ec681f3Smrg 3727ec681f3Smrgstatic int 3737ec681f3Smrgmin_vertex_pipeline_param(struct pipe_screen *pscreen, enum pipe_shader_cap param) 3747ec681f3Smrg{ 3757ec681f3Smrg int val = INT_MAX; 3767ec681f3Smrg for (int i = 0; i < PIPE_SHADER_COMPUTE; ++i) { 3777ec681f3Smrg if (i == PIPE_SHADER_FRAGMENT || 3787ec681f3Smrg !pscreen->get_shader_param(pscreen, i, 3797ec681f3Smrg PIPE_SHADER_CAP_MAX_INSTRUCTIONS)) 3807ec681f3Smrg continue; 3817ec681f3Smrg 3827ec681f3Smrg val = MAX2(val, pscreen->get_shader_param(pscreen, i, param)); 3837ec681f3Smrg } 3847ec681f3Smrg return val; 3857ec681f3Smrg} 3867ec681f3Smrg 3877ec681f3Smrgstatic int 3887ec681f3Smrgmin_shader_param(struct pipe_screen *pscreen, enum pipe_shader_cap param) 3897ec681f3Smrg{ 3907ec681f3Smrg return MIN3(min_vertex_pipeline_param(pscreen, param), 3917ec681f3Smrg pscreen->get_shader_param(pscreen, PIPE_SHADER_FRAGMENT, param), 3927ec681f3Smrg pscreen->get_shader_param(pscreen, PIPE_SHADER_COMPUTE, param)); 3937ec681f3Smrg} 3947ec681f3Smrg 3957ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceFeatures( 3967ec681f3Smrg VkPhysicalDevice physicalDevice, 3977ec681f3Smrg VkPhysicalDeviceFeatures* pFeatures) 3987ec681f3Smrg{ 3997ec681f3Smrg LVP_FROM_HANDLE(lvp_physical_device, pdevice, physicalDevice); 4007ec681f3Smrg bool indirect = false;//pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_GLSL_FEATURE_LEVEL) >= 400; 4017ec681f3Smrg memset(pFeatures, 0, sizeof(*pFeatures)); 4027ec681f3Smrg *pFeatures = (VkPhysicalDeviceFeatures) { 4037ec681f3Smrg .robustBufferAccess = true, 4047ec681f3Smrg .fullDrawIndexUint32 = true, 4057ec681f3Smrg .imageCubeArray = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_CUBE_MAP_ARRAY) != 0), 4067ec681f3Smrg .independentBlend = true, 4077ec681f3Smrg .geometryShader = (pdevice->pscreen->get_shader_param(pdevice->pscreen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) != 0), 4087ec681f3Smrg .tessellationShader = (pdevice->pscreen->get_shader_param(pdevice->pscreen, PIPE_SHADER_TESS_EVAL, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) != 0), 4097ec681f3Smrg .sampleRateShading = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_SAMPLE_SHADING) != 0), 4107ec681f3Smrg .dualSrcBlend = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS) != 0), 4117ec681f3Smrg .logicOp = true, 4127ec681f3Smrg .multiDrawIndirect = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MULTI_DRAW_INDIRECT) != 0), 4137ec681f3Smrg .drawIndirectFirstInstance = true, 4147ec681f3Smrg .depthClamp = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_DEPTH_CLIP_DISABLE) != 0), 4157ec681f3Smrg .depthBiasClamp = true, 4167ec681f3Smrg .fillModeNonSolid = true, 4177ec681f3Smrg .depthBounds = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_DEPTH_BOUNDS_TEST) != 0), 4187ec681f3Smrg .wideLines = true, 4197ec681f3Smrg .largePoints = true, 4207ec681f3Smrg .alphaToOne = true, 4217ec681f3Smrg .multiViewport = true, 4227ec681f3Smrg .samplerAnisotropy = true, 4237ec681f3Smrg .textureCompressionETC2 = false, 4247ec681f3Smrg .textureCompressionASTC_LDR = false, 4257ec681f3Smrg .textureCompressionBC = true, 4267ec681f3Smrg .occlusionQueryPrecise = true, 4277ec681f3Smrg .pipelineStatisticsQuery = true, 4287ec681f3Smrg .vertexPipelineStoresAndAtomics = (min_vertex_pipeline_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_SHADER_BUFFERS) != 0), 4297ec681f3Smrg .fragmentStoresAndAtomics = (pdevice->pscreen->get_shader_param(pdevice->pscreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_MAX_SHADER_BUFFERS) != 0), 4307ec681f3Smrg .shaderTessellationAndGeometryPointSize = true, 4317ec681f3Smrg .shaderImageGatherExtended = true, 4327ec681f3Smrg .shaderStorageImageExtendedFormats = (min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_SHADER_IMAGES) != 0), 4337ec681f3Smrg .shaderStorageImageMultisample = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_TEXTURE_MULTISAMPLE) != 0), 4347ec681f3Smrg .shaderUniformBufferArrayDynamicIndexing = true, 4357ec681f3Smrg .shaderSampledImageArrayDynamicIndexing = indirect, 4367ec681f3Smrg .shaderStorageBufferArrayDynamicIndexing = true, 4377ec681f3Smrg .shaderStorageImageArrayDynamicIndexing = indirect, 4387ec681f3Smrg .shaderStorageImageReadWithoutFormat = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_IMAGE_LOAD_FORMATTED) != 0), 4397ec681f3Smrg .shaderStorageImageWriteWithoutFormat = (min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_SHADER_IMAGES) != 0), 4407ec681f3Smrg .shaderClipDistance = true, 4417ec681f3Smrg .shaderCullDistance = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_CULL_DISTANCE) == 1), 4427ec681f3Smrg .shaderFloat64 = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_DOUBLES) == 1), 4437ec681f3Smrg .shaderInt64 = (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_INT64) == 1), 4447ec681f3Smrg .shaderInt16 = (min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_INT16) == 1), 4457ec681f3Smrg .variableMultisampleRate = false, 4467ec681f3Smrg .inheritedQueries = false, 4477ec681f3Smrg }; 4487ec681f3Smrg} 4497ec681f3Smrg 4507ec681f3Smrgstatic void 4517ec681f3Smrglvp_get_physical_device_features_1_1(struct lvp_physical_device *pdevice, 4527ec681f3Smrg VkPhysicalDeviceVulkan11Features *f) 4537ec681f3Smrg{ 4547ec681f3Smrg assert(f->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES); 4557ec681f3Smrg 4567ec681f3Smrg f->storageBuffer16BitAccess = true; 4577ec681f3Smrg f->uniformAndStorageBuffer16BitAccess = true; 4587ec681f3Smrg f->storagePushConstant16 = true; 4597ec681f3Smrg f->storageInputOutput16 = false; 4607ec681f3Smrg f->multiview = true; 4617ec681f3Smrg f->multiviewGeometryShader = true; 4627ec681f3Smrg f->multiviewTessellationShader = true; 4637ec681f3Smrg f->variablePointersStorageBuffer = true; 4647ec681f3Smrg f->variablePointers = false; 4657ec681f3Smrg f->protectedMemory = false; 4667ec681f3Smrg f->samplerYcbcrConversion = false; 4677ec681f3Smrg f->shaderDrawParameters = true; 4687ec681f3Smrg} 4697ec681f3Smrg 4707ec681f3Smrgstatic void 4717ec681f3Smrglvp_get_physical_device_features_1_2(struct lvp_physical_device *pdevice, 4727ec681f3Smrg VkPhysicalDeviceVulkan12Features *f) 4737ec681f3Smrg{ 4747ec681f3Smrg assert(f->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES); 4757ec681f3Smrg 4767ec681f3Smrg f->samplerMirrorClampToEdge = true; 4777ec681f3Smrg f->drawIndirectCount = true; 4787ec681f3Smrg f->storageBuffer8BitAccess = true; 4797ec681f3Smrg f->uniformAndStorageBuffer8BitAccess = true; 4807ec681f3Smrg f->storagePushConstant8 = true; 4817ec681f3Smrg f->shaderBufferInt64Atomics = true; 4827ec681f3Smrg f->shaderSharedInt64Atomics = true; 4837ec681f3Smrg f->shaderFloat16 = pdevice->pscreen->get_shader_param(pdevice->pscreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_FP16) != 0; 4847ec681f3Smrg f->shaderInt8 = true; 4857ec681f3Smrg 4867ec681f3Smrg f->descriptorIndexing = false; 4877ec681f3Smrg f->shaderInputAttachmentArrayDynamicIndexing = false; 4887ec681f3Smrg f->shaderUniformTexelBufferArrayDynamicIndexing = false; 4897ec681f3Smrg f->shaderStorageTexelBufferArrayDynamicIndexing = false; 4907ec681f3Smrg f->shaderUniformBufferArrayNonUniformIndexing = false; 4917ec681f3Smrg f->shaderSampledImageArrayNonUniformIndexing = false; 4927ec681f3Smrg f->shaderStorageBufferArrayNonUniformIndexing = false; 4937ec681f3Smrg f->shaderStorageImageArrayNonUniformIndexing = false; 4947ec681f3Smrg f->shaderInputAttachmentArrayNonUniformIndexing = false; 4957ec681f3Smrg f->shaderUniformTexelBufferArrayNonUniformIndexing = false; 4967ec681f3Smrg f->shaderStorageTexelBufferArrayNonUniformIndexing = false; 4977ec681f3Smrg f->descriptorBindingUniformBufferUpdateAfterBind = false; 4987ec681f3Smrg f->descriptorBindingSampledImageUpdateAfterBind = false; 4997ec681f3Smrg f->descriptorBindingStorageImageUpdateAfterBind = false; 5007ec681f3Smrg f->descriptorBindingStorageBufferUpdateAfterBind = false; 5017ec681f3Smrg f->descriptorBindingUniformTexelBufferUpdateAfterBind = false; 5027ec681f3Smrg f->descriptorBindingStorageTexelBufferUpdateAfterBind = false; 5037ec681f3Smrg f->descriptorBindingUpdateUnusedWhilePending = false; 5047ec681f3Smrg f->descriptorBindingPartiallyBound = false; 5057ec681f3Smrg f->descriptorBindingVariableDescriptorCount = false; 5067ec681f3Smrg f->runtimeDescriptorArray = false; 5077ec681f3Smrg 5087ec681f3Smrg f->samplerFilterMinmax = true; 5097ec681f3Smrg f->scalarBlockLayout = true; 5107ec681f3Smrg f->imagelessFramebuffer = true; 5117ec681f3Smrg f->uniformBufferStandardLayout = true; 5127ec681f3Smrg f->shaderSubgroupExtendedTypes = true; 5137ec681f3Smrg f->separateDepthStencilLayouts = true; 5147ec681f3Smrg f->hostQueryReset = true; 5157ec681f3Smrg f->timelineSemaphore = true; 5167ec681f3Smrg f->bufferDeviceAddress = true; 5177ec681f3Smrg f->bufferDeviceAddressCaptureReplay = false; 5187ec681f3Smrg f->bufferDeviceAddressMultiDevice = false; 5197ec681f3Smrg f->vulkanMemoryModel = false; 5207ec681f3Smrg f->vulkanMemoryModelDeviceScope = false; 5217ec681f3Smrg f->vulkanMemoryModelAvailabilityVisibilityChains = false; 5227ec681f3Smrg f->shaderOutputViewportIndex = true; 5237ec681f3Smrg f->shaderOutputLayer = true; 5247ec681f3Smrg f->subgroupBroadcastDynamicId = true; 5257ec681f3Smrg} 5267ec681f3Smrg 5277ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceFeatures2( 5287ec681f3Smrg VkPhysicalDevice physicalDevice, 5297ec681f3Smrg VkPhysicalDeviceFeatures2 *pFeatures) 5307ec681f3Smrg{ 5317ec681f3Smrg LVP_FROM_HANDLE(lvp_physical_device, pdevice, physicalDevice); 5327ec681f3Smrg lvp_GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features); 5337ec681f3Smrg 5347ec681f3Smrg VkPhysicalDeviceVulkan11Features core_1_1 = { 5357ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES, 5367ec681f3Smrg }; 5377ec681f3Smrg lvp_get_physical_device_features_1_1(pdevice, &core_1_1); 5387ec681f3Smrg 5397ec681f3Smrg VkPhysicalDeviceVulkan12Features core_1_2 = { 5407ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES, 5417ec681f3Smrg }; 5427ec681f3Smrg lvp_get_physical_device_features_1_2(pdevice, &core_1_2); 5437ec681f3Smrg 5447ec681f3Smrg vk_foreach_struct(ext, pFeatures->pNext) { 5457ec681f3Smrg 5467ec681f3Smrg if (vk_get_physical_device_core_1_1_feature_ext(ext, &core_1_1)) 5477ec681f3Smrg continue; 5487ec681f3Smrg if (vk_get_physical_device_core_1_2_feature_ext(ext, &core_1_2)) 5497ec681f3Smrg continue; 5507ec681f3Smrg 5517ec681f3Smrg switch (ext->sType) { 5527ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIVATE_DATA_FEATURES_EXT: { 5537ec681f3Smrg VkPhysicalDevicePrivateDataFeaturesEXT *features = 5547ec681f3Smrg (VkPhysicalDevicePrivateDataFeaturesEXT *)ext; 5557ec681f3Smrg features->privateData = true; 5567ec681f3Smrg break; 5577ec681f3Smrg } 5587ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_FEATURES_EXT: { 5597ec681f3Smrg VkPhysicalDeviceLineRasterizationFeaturesEXT *features = 5607ec681f3Smrg (VkPhysicalDeviceLineRasterizationFeaturesEXT *)ext; 5617ec681f3Smrg features->rectangularLines = true; 5627ec681f3Smrg features->bresenhamLines = true; 5637ec681f3Smrg features->smoothLines = true; 5647ec681f3Smrg features->stippledRectangularLines = true; 5657ec681f3Smrg features->stippledBresenhamLines = true; 5667ec681f3Smrg features->stippledSmoothLines = true; 5677ec681f3Smrg break; 5687ec681f3Smrg } 5697ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: { 5707ec681f3Smrg VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *features = 5717ec681f3Smrg (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT *)ext; 5727ec681f3Smrg features->vertexAttributeInstanceRateZeroDivisor = false; 5737ec681f3Smrg if (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR) != 0) { 5747ec681f3Smrg features->vertexAttributeInstanceRateDivisor = true; 5757ec681f3Smrg } else { 5767ec681f3Smrg features->vertexAttributeInstanceRateDivisor = false; 5777ec681f3Smrg } 5787ec681f3Smrg break; 5797ec681f3Smrg } 5807ec681f3Smrg 5817ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INDEX_TYPE_UINT8_FEATURES_EXT: { 5827ec681f3Smrg VkPhysicalDeviceIndexTypeUint8FeaturesEXT *features = 5837ec681f3Smrg (VkPhysicalDeviceIndexTypeUint8FeaturesEXT *)ext; 5847ec681f3Smrg features->indexTypeUint8 = true; 5857ec681f3Smrg break; 5867ec681f3Smrg } 5877ec681f3Smrg 5887ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT: { 5897ec681f3Smrg VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *features = 5907ec681f3Smrg (VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT *)ext; 5917ec681f3Smrg features->vertexInputDynamicState = true; 5927ec681f3Smrg break; 5937ec681f3Smrg } 5947ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT: { 5957ec681f3Smrg VkPhysicalDeviceTransformFeedbackFeaturesEXT *features = 5967ec681f3Smrg (VkPhysicalDeviceTransformFeedbackFeaturesEXT*)ext; 5977ec681f3Smrg 5987ec681f3Smrg features->transformFeedback = true; 5997ec681f3Smrg features->geometryStreams = true; 6007ec681f3Smrg break; 6017ec681f3Smrg } 6027ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONDITIONAL_RENDERING_FEATURES_EXT: { 6037ec681f3Smrg VkPhysicalDeviceConditionalRenderingFeaturesEXT *features = 6047ec681f3Smrg (VkPhysicalDeviceConditionalRenderingFeaturesEXT*)ext; 6057ec681f3Smrg features->conditionalRendering = true; 6067ec681f3Smrg features->inheritedConditionalRendering = false; 6077ec681f3Smrg break; 6087ec681f3Smrg } 6097ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT: { 6107ec681f3Smrg VkPhysicalDeviceExtendedDynamicStateFeaturesEXT *features = 6117ec681f3Smrg (VkPhysicalDeviceExtendedDynamicStateFeaturesEXT*)ext; 6127ec681f3Smrg features->extendedDynamicState = true; 6137ec681f3Smrg break; 6147ec681f3Smrg } 6157ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_4444_FORMATS_FEATURES_EXT: { 6167ec681f3Smrg VkPhysicalDevice4444FormatsFeaturesEXT *features = 6177ec681f3Smrg (VkPhysicalDevice4444FormatsFeaturesEXT*)ext; 6187ec681f3Smrg features->formatA4R4G4B4 = true; 6197ec681f3Smrg features->formatA4B4G4R4 = true; 6207ec681f3Smrg break; 6217ec681f3Smrg } 6227ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT: { 6237ec681f3Smrg VkPhysicalDeviceCustomBorderColorFeaturesEXT *features = 6247ec681f3Smrg (VkPhysicalDeviceCustomBorderColorFeaturesEXT *)ext; 6257ec681f3Smrg features->customBorderColors = true; 6267ec681f3Smrg features->customBorderColorWithoutFormat = true; 6277ec681f3Smrg break; 6287ec681f3Smrg } 6297ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COLOR_WRITE_ENABLE_FEATURES_EXT: { 6307ec681f3Smrg VkPhysicalDeviceColorWriteEnableFeaturesEXT *features = 6317ec681f3Smrg (VkPhysicalDeviceColorWriteEnableFeaturesEXT *)ext; 6327ec681f3Smrg features->colorWriteEnable = true; 6337ec681f3Smrg break; 6347ec681f3Smrg } 6357ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_FEATURES_EXT: { 6367ec681f3Smrg VkPhysicalDeviceProvokingVertexFeaturesEXT *features = 6377ec681f3Smrg (VkPhysicalDeviceProvokingVertexFeaturesEXT*)ext; 6387ec681f3Smrg features->provokingVertexLast = true; 6397ec681f3Smrg features->transformFeedbackPreservesProvokingVertex = true; 6407ec681f3Smrg break; 6417ec681f3Smrg } 6427ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_FEATURES_EXT: { 6437ec681f3Smrg VkPhysicalDeviceMultiDrawFeaturesEXT *features = (VkPhysicalDeviceMultiDrawFeaturesEXT *)ext; 6447ec681f3Smrg features->multiDraw = true; 6457ec681f3Smrg break; 6467ec681f3Smrg } 6477ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_CLIP_ENABLE_FEATURES_EXT: { 6487ec681f3Smrg VkPhysicalDeviceDepthClipEnableFeaturesEXT *features = 6497ec681f3Smrg (VkPhysicalDeviceDepthClipEnableFeaturesEXT *)ext; 6507ec681f3Smrg if (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_DEPTH_CLAMP_ENABLE) != 0) 6517ec681f3Smrg features->depthClipEnable = true; 6527ec681f3Smrg else 6537ec681f3Smrg features->depthClipEnable = false; 6547ec681f3Smrg break; 6557ec681f3Smrg } 6567ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT: { 6577ec681f3Smrg VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *features = (VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *)ext; 6587ec681f3Smrg features->extendedDynamicState2 = true; 6597ec681f3Smrg features->extendedDynamicState2LogicOp = true; 6607ec681f3Smrg features->extendedDynamicState2PatchControlPoints = true; 6617ec681f3Smrg break; 6627ec681f3Smrg } 6637ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT: { 6647ec681f3Smrg VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT *features = (VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT *)ext; 6657ec681f3Smrg features->primitiveTopologyListRestart = true; 6667ec681f3Smrg features->primitiveTopologyPatchListRestart = true; 6677ec681f3Smrg break; 6687ec681f3Smrg } 6697ec681f3Smrg default: 6707ec681f3Smrg break; 6717ec681f3Smrg } 6727ec681f3Smrg } 6737ec681f3Smrg} 6747ec681f3Smrg 6757ec681f3Smrgvoid 6767ec681f3Smrglvp_device_get_cache_uuid(void *uuid) 6777ec681f3Smrg{ 6787ec681f3Smrg memset(uuid, 0, VK_UUID_SIZE); 6797ec681f3Smrg snprintf(uuid, VK_UUID_SIZE, "val-%s", MESA_GIT_SHA1 + 4); 6807ec681f3Smrg} 6817ec681f3Smrg 6827ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, 6837ec681f3Smrg VkPhysicalDeviceProperties *pProperties) 6847ec681f3Smrg{ 6857ec681f3Smrg LVP_FROM_HANDLE(lvp_physical_device, pdevice, physicalDevice); 6867ec681f3Smrg 6877ec681f3Smrg VkSampleCountFlags sample_counts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT; 6887ec681f3Smrg 6897ec681f3Smrg uint64_t grid_size[3], block_size[3]; 6907ec681f3Smrg uint64_t max_threads_per_block, max_local_size; 6917ec681f3Smrg 6927ec681f3Smrg pdevice->pscreen->get_compute_param(pdevice->pscreen, PIPE_SHADER_IR_NIR, 6937ec681f3Smrg PIPE_COMPUTE_CAP_MAX_GRID_SIZE, grid_size); 6947ec681f3Smrg pdevice->pscreen->get_compute_param(pdevice->pscreen, PIPE_SHADER_IR_NIR, 6957ec681f3Smrg PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE, block_size); 6967ec681f3Smrg pdevice->pscreen->get_compute_param(pdevice->pscreen, PIPE_SHADER_IR_NIR, 6977ec681f3Smrg PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK, 6987ec681f3Smrg &max_threads_per_block); 6997ec681f3Smrg pdevice->pscreen->get_compute_param(pdevice->pscreen, PIPE_SHADER_IR_NIR, 7007ec681f3Smrg PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE, 7017ec681f3Smrg &max_local_size); 7027ec681f3Smrg 7037ec681f3Smrg VkPhysicalDeviceLimits limits = { 7047ec681f3Smrg .maxImageDimension1D = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE), 7057ec681f3Smrg .maxImageDimension2D = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE), 7067ec681f3Smrg .maxImageDimension3D = (1 << pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS)), 7077ec681f3Smrg .maxImageDimensionCube = (1 << pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS)), 7087ec681f3Smrg .maxImageArrayLayers = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS), 7097ec681f3Smrg .maxTexelBufferElements = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE), 7107ec681f3Smrg .maxUniformBufferRange = min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE), 7117ec681f3Smrg .maxStorageBufferRange = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_SHADER_BUFFER_SIZE), 7127ec681f3Smrg .maxPushConstantsSize = MAX_PUSH_CONSTANTS_SIZE, 7137ec681f3Smrg .maxMemoryAllocationCount = UINT32_MAX, 7147ec681f3Smrg .maxSamplerAllocationCount = 32 * 1024, 7157ec681f3Smrg .bufferImageGranularity = 64, /* A cache line */ 7167ec681f3Smrg .sparseAddressSpaceSize = 0, 7177ec681f3Smrg .maxBoundDescriptorSets = MAX_SETS, 7187ec681f3Smrg .maxPerStageDescriptorSamplers = min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS), 7197ec681f3Smrg .maxPerStageDescriptorUniformBuffers = min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_CONST_BUFFERS) - 1, 7207ec681f3Smrg .maxPerStageDescriptorStorageBuffers = min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_SHADER_BUFFERS), 7217ec681f3Smrg .maxPerStageDescriptorSampledImages = min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_SAMPLER_VIEWS), 7227ec681f3Smrg .maxPerStageDescriptorStorageImages = min_shader_param(pdevice->pscreen, PIPE_SHADER_CAP_MAX_SHADER_IMAGES), 7237ec681f3Smrg .maxPerStageDescriptorInputAttachments = 8, 7247ec681f3Smrg .maxPerStageResources = 128, 7257ec681f3Smrg .maxDescriptorSetSamplers = 32 * 1024, 7267ec681f3Smrg .maxDescriptorSetUniformBuffers = 256, 7277ec681f3Smrg .maxDescriptorSetUniformBuffersDynamic = 256, 7287ec681f3Smrg .maxDescriptorSetStorageBuffers = 256, 7297ec681f3Smrg .maxDescriptorSetStorageBuffersDynamic = 256, 7307ec681f3Smrg .maxDescriptorSetSampledImages = 256, 7317ec681f3Smrg .maxDescriptorSetStorageImages = 256, 7327ec681f3Smrg .maxDescriptorSetInputAttachments = 256, 7337ec681f3Smrg .maxVertexInputAttributes = 32, 7347ec681f3Smrg .maxVertexInputBindings = 32, 7357ec681f3Smrg .maxVertexInputAttributeOffset = 2047, 7367ec681f3Smrg .maxVertexInputBindingStride = 2048, 7377ec681f3Smrg .maxVertexOutputComponents = 128, 7387ec681f3Smrg .maxTessellationGenerationLevel = 64, 7397ec681f3Smrg .maxTessellationPatchSize = 32, 7407ec681f3Smrg .maxTessellationControlPerVertexInputComponents = 128, 7417ec681f3Smrg .maxTessellationControlPerVertexOutputComponents = 128, 7427ec681f3Smrg .maxTessellationControlPerPatchOutputComponents = 128, 7437ec681f3Smrg .maxTessellationControlTotalOutputComponents = 4096, 7447ec681f3Smrg .maxTessellationEvaluationInputComponents = 128, 7457ec681f3Smrg .maxTessellationEvaluationOutputComponents = 128, 7467ec681f3Smrg .maxGeometryShaderInvocations = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_GS_INVOCATIONS), 7477ec681f3Smrg .maxGeometryInputComponents = 64, 7487ec681f3Smrg .maxGeometryOutputComponents = 128, 7497ec681f3Smrg .maxGeometryOutputVertices = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES), 7507ec681f3Smrg .maxGeometryTotalOutputComponents = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS), 7517ec681f3Smrg .maxFragmentInputComponents = 128, 7527ec681f3Smrg .maxFragmentOutputAttachments = 8, 7537ec681f3Smrg .maxFragmentDualSrcAttachments = 2, 7547ec681f3Smrg .maxFragmentCombinedOutputResources = 8, 7557ec681f3Smrg .maxComputeSharedMemorySize = max_local_size, 7567ec681f3Smrg .maxComputeWorkGroupCount = { grid_size[0], grid_size[1], grid_size[2] }, 7577ec681f3Smrg .maxComputeWorkGroupInvocations = max_threads_per_block, 7587ec681f3Smrg .maxComputeWorkGroupSize = { block_size[0], block_size[1], block_size[2] }, 7597ec681f3Smrg .subPixelPrecisionBits = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_RASTERIZER_SUBPIXEL_BITS), 7607ec681f3Smrg .subTexelPrecisionBits = 8, 7617ec681f3Smrg .mipmapPrecisionBits = 4, 7627ec681f3Smrg .maxDrawIndexedIndexValue = UINT32_MAX, 7637ec681f3Smrg .maxDrawIndirectCount = UINT32_MAX, 7647ec681f3Smrg .maxSamplerLodBias = 16, 7657ec681f3Smrg .maxSamplerAnisotropy = 16, 7667ec681f3Smrg .maxViewports = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_VIEWPORTS), 7677ec681f3Smrg .maxViewportDimensions = { (1 << 14), (1 << 14) }, 7687ec681f3Smrg .viewportBoundsRange = { -32768.0, 32768.0 }, 7697ec681f3Smrg .viewportSubPixelBits = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_VIEWPORT_SUBPIXEL_BITS), 7707ec681f3Smrg .minMemoryMapAlignment = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT), 7717ec681f3Smrg .minTexelBufferOffsetAlignment = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT), 7727ec681f3Smrg .minUniformBufferOffsetAlignment = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT), 7737ec681f3Smrg .minStorageBufferOffsetAlignment = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT), 7747ec681f3Smrg .minTexelOffset = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MIN_TEXEL_OFFSET), 7757ec681f3Smrg .maxTexelOffset = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXEL_OFFSET), 7767ec681f3Smrg .minTexelGatherOffset = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MIN_TEXTURE_GATHER_OFFSET), 7777ec681f3Smrg .maxTexelGatherOffset = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_GATHER_OFFSET), 7787ec681f3Smrg .minInterpolationOffset = -2, /* FIXME */ 7797ec681f3Smrg .maxInterpolationOffset = 2, /* FIXME */ 7807ec681f3Smrg .subPixelInterpolationOffsetBits = 8, /* FIXME */ 7817ec681f3Smrg .maxFramebufferWidth = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE), 7827ec681f3Smrg .maxFramebufferHeight = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_2D_SIZE), 7837ec681f3Smrg .maxFramebufferLayers = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS), 7847ec681f3Smrg .framebufferColorSampleCounts = sample_counts, 7857ec681f3Smrg .framebufferDepthSampleCounts = sample_counts, 7867ec681f3Smrg .framebufferStencilSampleCounts = sample_counts, 7877ec681f3Smrg .framebufferNoAttachmentsSampleCounts = sample_counts, 7887ec681f3Smrg .maxColorAttachments = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_RENDER_TARGETS), 7897ec681f3Smrg .sampledImageColorSampleCounts = sample_counts, 7907ec681f3Smrg .sampledImageIntegerSampleCounts = sample_counts, 7917ec681f3Smrg .sampledImageDepthSampleCounts = sample_counts, 7927ec681f3Smrg .sampledImageStencilSampleCounts = sample_counts, 7937ec681f3Smrg .storageImageSampleCounts = sample_counts, 7947ec681f3Smrg .maxSampleMaskWords = 1, 7957ec681f3Smrg .timestampComputeAndGraphics = true, 7967ec681f3Smrg .timestampPeriod = 1, 7977ec681f3Smrg .maxClipDistances = 8, 7987ec681f3Smrg .maxCullDistances = 8, 7997ec681f3Smrg .maxCombinedClipAndCullDistances = 8, 8007ec681f3Smrg .discreteQueuePriorities = 2, 8017ec681f3Smrg .pointSizeRange = { 0.0, pdevice->pscreen->get_paramf(pdevice->pscreen, PIPE_CAPF_MAX_POINT_WIDTH) }, 8027ec681f3Smrg .lineWidthRange = { 1.0, pdevice->pscreen->get_paramf(pdevice->pscreen, PIPE_CAPF_MAX_LINE_WIDTH) }, 8037ec681f3Smrg .pointSizeGranularity = (1.0 / 8.0), 8047ec681f3Smrg .lineWidthGranularity = 1.0 / 128.0, 8057ec681f3Smrg .strictLines = true, 8067ec681f3Smrg .standardSampleLocations = true, 8077ec681f3Smrg .optimalBufferCopyOffsetAlignment = 128, 8087ec681f3Smrg .optimalBufferCopyRowPitchAlignment = 128, 8097ec681f3Smrg .nonCoherentAtomSize = 64, 8107ec681f3Smrg }; 8117ec681f3Smrg 8127ec681f3Smrg *pProperties = (VkPhysicalDeviceProperties) { 8137ec681f3Smrg .apiVersion = LVP_API_VERSION, 8147ec681f3Smrg .driverVersion = 1, 8157ec681f3Smrg .vendorID = VK_VENDOR_ID_MESA, 8167ec681f3Smrg .deviceID = 0, 8177ec681f3Smrg .deviceType = VK_PHYSICAL_DEVICE_TYPE_CPU, 8187ec681f3Smrg .limits = limits, 8197ec681f3Smrg .sparseProperties = {0}, 8207ec681f3Smrg }; 8217ec681f3Smrg 8227ec681f3Smrg strcpy(pProperties->deviceName, pdevice->pscreen->get_name(pdevice->pscreen)); 8237ec681f3Smrg lvp_device_get_cache_uuid(pProperties->pipelineCacheUUID); 8247ec681f3Smrg 8257ec681f3Smrg} 8267ec681f3Smrg 8277ec681f3Smrgextern unsigned lp_native_vector_width; 8287ec681f3Smrgstatic void 8297ec681f3Smrglvp_get_physical_device_properties_1_1(struct lvp_physical_device *pdevice, 8307ec681f3Smrg VkPhysicalDeviceVulkan11Properties *p) 8317ec681f3Smrg{ 8327ec681f3Smrg assert(p->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES); 8337ec681f3Smrg 8347ec681f3Smrg memset(p->deviceUUID, 0, VK_UUID_SIZE); 8357ec681f3Smrg memset(p->driverUUID, 0, VK_UUID_SIZE); 8367ec681f3Smrg memset(p->deviceLUID, 0, VK_LUID_SIZE); 8377ec681f3Smrg /* The LUID is for Windows. */ 8387ec681f3Smrg p->deviceLUIDValid = false; 8397ec681f3Smrg p->deviceNodeMask = 0; 8407ec681f3Smrg 8417ec681f3Smrg p->subgroupSize = lp_native_vector_width / 32; 8427ec681f3Smrg p->subgroupSupportedStages = VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_COMPUTE_BIT; 8437ec681f3Smrg p->subgroupSupportedOperations = VK_SUBGROUP_FEATURE_BASIC_BIT | VK_SUBGROUP_FEATURE_VOTE_BIT | VK_SUBGROUP_FEATURE_ARITHMETIC_BIT | VK_SUBGROUP_FEATURE_BALLOT_BIT; 8447ec681f3Smrg p->subgroupQuadOperationsInAllStages = false; 8457ec681f3Smrg 8467ec681f3Smrg p->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES; 8477ec681f3Smrg p->maxMultiviewViewCount = 6; 8487ec681f3Smrg p->maxMultiviewInstanceIndex = INT_MAX; 8497ec681f3Smrg p->protectedNoFault = false; 8507ec681f3Smrg p->maxPerSetDescriptors = 1024; 8517ec681f3Smrg p->maxMemoryAllocationSize = (1u << 31); 8527ec681f3Smrg} 8537ec681f3Smrg 8547ec681f3Smrgstatic void 8557ec681f3Smrglvp_get_physical_device_properties_1_2(struct lvp_physical_device *pdevice, 8567ec681f3Smrg VkPhysicalDeviceVulkan12Properties *p) 8577ec681f3Smrg{ 8587ec681f3Smrg p->driverID = VK_DRIVER_ID_MESA_LLVMPIPE; 8597ec681f3Smrg snprintf(p->driverName, VK_MAX_DRIVER_NAME_SIZE, "llvmpipe"); 8607ec681f3Smrg snprintf(p->driverInfo, VK_MAX_DRIVER_INFO_SIZE, "Mesa " PACKAGE_VERSION MESA_GIT_SHA1 8617ec681f3Smrg#ifdef MESA_LLVM_VERSION_STRING 8627ec681f3Smrg " (LLVM " MESA_LLVM_VERSION_STRING ")" 8637ec681f3Smrg#endif 8647ec681f3Smrg ); 8657ec681f3Smrg 8667ec681f3Smrg p->conformanceVersion = (VkConformanceVersion){ 8677ec681f3Smrg .major = 0, 8687ec681f3Smrg .minor = 0, 8697ec681f3Smrg .subminor = 0, 8707ec681f3Smrg .patch = 0, 8717ec681f3Smrg }; 8727ec681f3Smrg 8737ec681f3Smrg p->denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL_KHR; 8747ec681f3Smrg p->roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL_KHR; 8757ec681f3Smrg p->shaderDenormFlushToZeroFloat16 = false; 8767ec681f3Smrg p->shaderDenormPreserveFloat16 = false; 8777ec681f3Smrg p->shaderRoundingModeRTEFloat16 = true; 8787ec681f3Smrg p->shaderRoundingModeRTZFloat16 = false; 8797ec681f3Smrg p->shaderSignedZeroInfNanPreserveFloat16 = true; 8807ec681f3Smrg 8817ec681f3Smrg p->shaderDenormFlushToZeroFloat32 = false; 8827ec681f3Smrg p->shaderDenormPreserveFloat32 = false; 8837ec681f3Smrg p->shaderRoundingModeRTEFloat32 = true; 8847ec681f3Smrg p->shaderRoundingModeRTZFloat32 = false; 8857ec681f3Smrg p->shaderSignedZeroInfNanPreserveFloat32 = true; 8867ec681f3Smrg 8877ec681f3Smrg p->shaderDenormFlushToZeroFloat64 = false; 8887ec681f3Smrg p->shaderDenormPreserveFloat64 = false; 8897ec681f3Smrg p->shaderRoundingModeRTEFloat64 = true; 8907ec681f3Smrg p->shaderRoundingModeRTZFloat64 = false; 8917ec681f3Smrg p->shaderSignedZeroInfNanPreserveFloat64 = true; 8927ec681f3Smrg 8937ec681f3Smrg p->maxUpdateAfterBindDescriptorsInAllPools = UINT32_MAX / 64; 8947ec681f3Smrg p->shaderUniformBufferArrayNonUniformIndexingNative = false; 8957ec681f3Smrg p->shaderSampledImageArrayNonUniformIndexingNative = false; 8967ec681f3Smrg p->shaderStorageBufferArrayNonUniformIndexingNative = false; 8977ec681f3Smrg p->shaderStorageImageArrayNonUniformIndexingNative = false; 8987ec681f3Smrg p->shaderInputAttachmentArrayNonUniformIndexingNative = false; 8997ec681f3Smrg p->robustBufferAccessUpdateAfterBind = true; 9007ec681f3Smrg p->quadDivergentImplicitLod = false; 9017ec681f3Smrg 9027ec681f3Smrg size_t max_descriptor_set_size = 65536; //TODO 9037ec681f3Smrg p->maxPerStageDescriptorUpdateAfterBindSamplers = max_descriptor_set_size; 9047ec681f3Smrg p->maxPerStageDescriptorUpdateAfterBindUniformBuffers = max_descriptor_set_size; 9057ec681f3Smrg p->maxPerStageDescriptorUpdateAfterBindStorageBuffers = max_descriptor_set_size; 9067ec681f3Smrg p->maxPerStageDescriptorUpdateAfterBindSampledImages = max_descriptor_set_size; 9077ec681f3Smrg p->maxPerStageDescriptorUpdateAfterBindStorageImages = max_descriptor_set_size; 9087ec681f3Smrg p->maxPerStageDescriptorUpdateAfterBindInputAttachments = max_descriptor_set_size; 9097ec681f3Smrg p->maxPerStageUpdateAfterBindResources = max_descriptor_set_size; 9107ec681f3Smrg p->maxDescriptorSetUpdateAfterBindSamplers = max_descriptor_set_size; 9117ec681f3Smrg p->maxDescriptorSetUpdateAfterBindUniformBuffers = max_descriptor_set_size; 9127ec681f3Smrg p->maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = 16; 9137ec681f3Smrg p->maxDescriptorSetUpdateAfterBindStorageBuffers = max_descriptor_set_size; 9147ec681f3Smrg p->maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = 16; 9157ec681f3Smrg p->maxDescriptorSetUpdateAfterBindSampledImages = max_descriptor_set_size; 9167ec681f3Smrg p->maxDescriptorSetUpdateAfterBindStorageImages = max_descriptor_set_size; 9177ec681f3Smrg p->maxDescriptorSetUpdateAfterBindInputAttachments = max_descriptor_set_size; 9187ec681f3Smrg 9197ec681f3Smrg p->supportedDepthResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT | VK_RESOLVE_MODE_AVERAGE_BIT; 9207ec681f3Smrg p->supportedStencilResolveModes = VK_RESOLVE_MODE_SAMPLE_ZERO_BIT; 9217ec681f3Smrg p->independentResolveNone = false; 9227ec681f3Smrg p->independentResolve = false; 9237ec681f3Smrg 9247ec681f3Smrg p->filterMinmaxImageComponentMapping = true; 9257ec681f3Smrg p->filterMinmaxSingleComponentFormats = true; 9267ec681f3Smrg 9277ec681f3Smrg p->maxTimelineSemaphoreValueDifference = UINT64_MAX; 9287ec681f3Smrg p->framebufferIntegerColorSampleCounts = VK_SAMPLE_COUNT_1_BIT; 9297ec681f3Smrg} 9307ec681f3Smrg 9317ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceProperties2( 9327ec681f3Smrg VkPhysicalDevice physicalDevice, 9337ec681f3Smrg VkPhysicalDeviceProperties2 *pProperties) 9347ec681f3Smrg{ 9357ec681f3Smrg LVP_FROM_HANDLE(lvp_physical_device, pdevice, physicalDevice); 9367ec681f3Smrg lvp_GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties); 9377ec681f3Smrg 9387ec681f3Smrg VkPhysicalDeviceVulkan11Properties core_1_1 = { 9397ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES, 9407ec681f3Smrg }; 9417ec681f3Smrg lvp_get_physical_device_properties_1_1(pdevice, &core_1_1); 9427ec681f3Smrg 9437ec681f3Smrg VkPhysicalDeviceVulkan12Properties core_1_2 = { 9447ec681f3Smrg .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES, 9457ec681f3Smrg }; 9467ec681f3Smrg lvp_get_physical_device_properties_1_2(pdevice, &core_1_2); 9477ec681f3Smrg 9487ec681f3Smrg vk_foreach_struct(ext, pProperties->pNext) { 9497ec681f3Smrg 9507ec681f3Smrg if (vk_get_physical_device_core_1_1_property_ext(ext, &core_1_1)) 9517ec681f3Smrg continue; 9527ec681f3Smrg if (vk_get_physical_device_core_1_2_property_ext(ext, &core_1_2)) 9537ec681f3Smrg continue; 9547ec681f3Smrg switch (ext->sType) { 9557ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: { 9567ec681f3Smrg VkPhysicalDevicePushDescriptorPropertiesKHR *properties = 9577ec681f3Smrg (VkPhysicalDevicePushDescriptorPropertiesKHR *) ext; 9587ec681f3Smrg properties->maxPushDescriptors = MAX_PUSH_DESCRIPTORS; 9597ec681f3Smrg break; 9607ec681f3Smrg } 9617ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: { 9627ec681f3Smrg VkPhysicalDevicePointClippingProperties *properties = 9637ec681f3Smrg (VkPhysicalDevicePointClippingProperties*)ext; 9647ec681f3Smrg properties->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES; 9657ec681f3Smrg break; 9667ec681f3Smrg } 9677ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: { 9687ec681f3Smrg VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *props = 9697ec681f3Smrg (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT *)ext; 9707ec681f3Smrg if (pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR) != 0) 9717ec681f3Smrg props->maxVertexAttribDivisor = UINT32_MAX; 9727ec681f3Smrg else 9737ec681f3Smrg props->maxVertexAttribDivisor = 1; 9747ec681f3Smrg break; 9757ec681f3Smrg } 9767ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT: { 9777ec681f3Smrg VkPhysicalDeviceTransformFeedbackPropertiesEXT *properties = 9787ec681f3Smrg (VkPhysicalDeviceTransformFeedbackPropertiesEXT*)ext; 9797ec681f3Smrg properties->maxTransformFeedbackStreams = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_VERTEX_STREAMS); 9807ec681f3Smrg properties->maxTransformFeedbackBuffers = pdevice->pscreen->get_param(pdevice->pscreen, PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS); 9817ec681f3Smrg properties->maxTransformFeedbackBufferSize = UINT32_MAX; 9827ec681f3Smrg properties->maxTransformFeedbackStreamDataSize = 512; 9837ec681f3Smrg properties->maxTransformFeedbackBufferDataSize = 512; 9847ec681f3Smrg properties->maxTransformFeedbackBufferDataStride = 512; 9857ec681f3Smrg properties->transformFeedbackQueries = true; 9867ec681f3Smrg properties->transformFeedbackStreamsLinesTriangles = false; 9877ec681f3Smrg properties->transformFeedbackRasterizationStreamSelect = false; 9887ec681f3Smrg properties->transformFeedbackDraw = true; 9897ec681f3Smrg break; 9907ec681f3Smrg } 9917ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES_EXT: { 9927ec681f3Smrg VkPhysicalDeviceLineRasterizationPropertiesEXT *properties = 9937ec681f3Smrg (VkPhysicalDeviceLineRasterizationPropertiesEXT *)ext; 9947ec681f3Smrg properties->lineSubPixelPrecisionBits = 9957ec681f3Smrg pdevice->pscreen->get_param(pdevice->pscreen, 9967ec681f3Smrg PIPE_CAP_RASTERIZER_SUBPIXEL_BITS); 9977ec681f3Smrg break; 9987ec681f3Smrg } 9997ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT: { 10007ec681f3Smrg VkPhysicalDeviceExternalMemoryHostPropertiesEXT *properties = 10017ec681f3Smrg (VkPhysicalDeviceExternalMemoryHostPropertiesEXT *)ext; 10027ec681f3Smrg properties->minImportedHostPointerAlignment = 4096; 10037ec681f3Smrg break; 10047ec681f3Smrg } 10057ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT: { 10067ec681f3Smrg VkPhysicalDeviceCustomBorderColorPropertiesEXT *properties = 10077ec681f3Smrg (VkPhysicalDeviceCustomBorderColorPropertiesEXT *)ext; 10087ec681f3Smrg properties->maxCustomBorderColorSamplers = 32 * 1024; 10097ec681f3Smrg break; 10107ec681f3Smrg } 10117ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT: { 10127ec681f3Smrg VkPhysicalDeviceProvokingVertexPropertiesEXT *properties = 10137ec681f3Smrg (VkPhysicalDeviceProvokingVertexPropertiesEXT*)ext; 10147ec681f3Smrg properties->provokingVertexModePerPipeline = true; 10157ec681f3Smrg properties->transformFeedbackPreservesTriangleFanProvokingVertex = true; 10167ec681f3Smrg break; 10177ec681f3Smrg } 10187ec681f3Smrg case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT: { 10197ec681f3Smrg VkPhysicalDeviceMultiDrawPropertiesEXT *props = (VkPhysicalDeviceMultiDrawPropertiesEXT *)ext; 10207ec681f3Smrg props->maxMultiDrawCount = 2048; 10217ec681f3Smrg break; 10227ec681f3Smrg } 10237ec681f3Smrg default: 10247ec681f3Smrg break; 10257ec681f3Smrg } 10267ec681f3Smrg } 10277ec681f3Smrg} 10287ec681f3Smrg 10297ec681f3Smrgstatic void lvp_get_physical_device_queue_family_properties( 10307ec681f3Smrg VkQueueFamilyProperties* pQueueFamilyProperties) 10317ec681f3Smrg{ 10327ec681f3Smrg *pQueueFamilyProperties = (VkQueueFamilyProperties) { 10337ec681f3Smrg .queueFlags = VK_QUEUE_GRAPHICS_BIT | 10347ec681f3Smrg VK_QUEUE_COMPUTE_BIT | 10357ec681f3Smrg VK_QUEUE_TRANSFER_BIT, 10367ec681f3Smrg .queueCount = 1, 10377ec681f3Smrg .timestampValidBits = 64, 10387ec681f3Smrg .minImageTransferGranularity = (VkExtent3D) { 1, 1, 1 }, 10397ec681f3Smrg }; 10407ec681f3Smrg} 10417ec681f3Smrg 10427ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceQueueFamilyProperties( 10437ec681f3Smrg VkPhysicalDevice physicalDevice, 10447ec681f3Smrg uint32_t* pCount, 10457ec681f3Smrg VkQueueFamilyProperties* pQueueFamilyProperties) 10467ec681f3Smrg{ 10477ec681f3Smrg if (pQueueFamilyProperties == NULL) { 10487ec681f3Smrg *pCount = 1; 10497ec681f3Smrg return; 10507ec681f3Smrg } 10517ec681f3Smrg 10527ec681f3Smrg assert(*pCount >= 1); 10537ec681f3Smrg lvp_get_physical_device_queue_family_properties(pQueueFamilyProperties); 10547ec681f3Smrg} 10557ec681f3Smrg 10567ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceQueueFamilyProperties2( 10577ec681f3Smrg VkPhysicalDevice physicalDevice, 10587ec681f3Smrg uint32_t* pCount, 10597ec681f3Smrg VkQueueFamilyProperties2 *pQueueFamilyProperties) 10607ec681f3Smrg{ 10617ec681f3Smrg if (pQueueFamilyProperties == NULL) { 10627ec681f3Smrg *pCount = 1; 10637ec681f3Smrg return; 10647ec681f3Smrg } 10657ec681f3Smrg 10667ec681f3Smrg assert(*pCount >= 1); 10677ec681f3Smrg lvp_get_physical_device_queue_family_properties(&pQueueFamilyProperties->queueFamilyProperties); 10687ec681f3Smrg} 10697ec681f3Smrg 10707ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceMemoryProperties( 10717ec681f3Smrg VkPhysicalDevice physicalDevice, 10727ec681f3Smrg VkPhysicalDeviceMemoryProperties* pMemoryProperties) 10737ec681f3Smrg{ 10747ec681f3Smrg pMemoryProperties->memoryTypeCount = 1; 10757ec681f3Smrg pMemoryProperties->memoryTypes[0] = (VkMemoryType) { 10767ec681f3Smrg .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | 10777ec681f3Smrg VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | 10787ec681f3Smrg VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | 10797ec681f3Smrg VK_MEMORY_PROPERTY_HOST_CACHED_BIT, 10807ec681f3Smrg .heapIndex = 0, 10817ec681f3Smrg }; 10827ec681f3Smrg 10837ec681f3Smrg pMemoryProperties->memoryHeapCount = 1; 10847ec681f3Smrg pMemoryProperties->memoryHeaps[0] = (VkMemoryHeap) { 10857ec681f3Smrg .size = 2ULL*1024*1024*1024, 10867ec681f3Smrg .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT, 10877ec681f3Smrg }; 10887ec681f3Smrg} 10897ec681f3Smrg 10907ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceMemoryProperties2( 10917ec681f3Smrg VkPhysicalDevice physicalDevice, 10927ec681f3Smrg VkPhysicalDeviceMemoryProperties2 *pMemoryProperties) 10937ec681f3Smrg{ 10947ec681f3Smrg lvp_GetPhysicalDeviceMemoryProperties(physicalDevice, 10957ec681f3Smrg &pMemoryProperties->memoryProperties); 10967ec681f3Smrg} 10977ec681f3Smrg 10987ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL 10997ec681f3Smrglvp_GetMemoryHostPointerPropertiesEXT( 11007ec681f3Smrg VkDevice _device, 11017ec681f3Smrg VkExternalMemoryHandleTypeFlagBits handleType, 11027ec681f3Smrg const void *pHostPointer, 11037ec681f3Smrg VkMemoryHostPointerPropertiesEXT *pMemoryHostPointerProperties) 11047ec681f3Smrg{ 11057ec681f3Smrg switch (handleType) { 11067ec681f3Smrg case VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT: { 11077ec681f3Smrg pMemoryHostPointerProperties->memoryTypeBits = 1; 11087ec681f3Smrg return VK_SUCCESS; 11097ec681f3Smrg } 11107ec681f3Smrg default: 11117ec681f3Smrg return VK_ERROR_INVALID_EXTERNAL_HANDLE; 11127ec681f3Smrg } 11137ec681f3Smrg} 11147ec681f3Smrg 11157ec681f3SmrgVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL lvp_GetInstanceProcAddr( 11167ec681f3Smrg VkInstance _instance, 11177ec681f3Smrg const char* pName) 11187ec681f3Smrg{ 11197ec681f3Smrg LVP_FROM_HANDLE(lvp_instance, instance, _instance); 11207ec681f3Smrg return vk_instance_get_proc_addr(&instance->vk, 11217ec681f3Smrg &lvp_instance_entrypoints, 11227ec681f3Smrg pName); 11237ec681f3Smrg} 11247ec681f3Smrg 11257ec681f3Smrg/* Windows will use a dll definition file to avoid build errors. */ 11267ec681f3Smrg#ifdef _WIN32 11277ec681f3Smrg#undef PUBLIC 11287ec681f3Smrg#define PUBLIC 11297ec681f3Smrg#endif 11307ec681f3Smrg 11317ec681f3Smrg/* The loader wants us to expose a second GetInstanceProcAddr function 11327ec681f3Smrg * to work around certain LD_PRELOAD issues seen in apps. 11337ec681f3Smrg */ 11347ec681f3SmrgPUBLIC 11357ec681f3SmrgVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr( 11367ec681f3Smrg VkInstance instance, 11377ec681f3Smrg const char* pName); 11387ec681f3Smrg 11397ec681f3SmrgPUBLIC 11407ec681f3SmrgVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr( 11417ec681f3Smrg VkInstance instance, 11427ec681f3Smrg const char* pName) 11437ec681f3Smrg{ 11447ec681f3Smrg return lvp_GetInstanceProcAddr(instance, pName); 11457ec681f3Smrg} 11467ec681f3Smrg 11477ec681f3SmrgPUBLIC 11487ec681f3SmrgVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr( 11497ec681f3Smrg VkInstance _instance, 11507ec681f3Smrg const char* pName); 11517ec681f3Smrg 11527ec681f3SmrgPUBLIC 11537ec681f3SmrgVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr( 11547ec681f3Smrg VkInstance _instance, 11557ec681f3Smrg const char* pName) 11567ec681f3Smrg{ 11577ec681f3Smrg LVP_FROM_HANDLE(lvp_instance, instance, _instance); 11587ec681f3Smrg return vk_instance_get_physical_device_proc_addr(&instance->vk, pName); 11597ec681f3Smrg} 11607ec681f3Smrg 11617ec681f3Smrgstatic void 11627ec681f3Smrgset_last_fence(struct lvp_device *device, struct pipe_fence_handle *handle, uint64_t timeline) 11637ec681f3Smrg{ 11647ec681f3Smrg simple_mtx_lock(&device->queue.last_lock); 11657ec681f3Smrg device->queue.last_fence_timeline = timeline; 11667ec681f3Smrg device->pscreen->fence_reference(device->pscreen, &device->queue.last_fence, handle); 11677ec681f3Smrg simple_mtx_unlock(&device->queue.last_lock); 11687ec681f3Smrg} 11697ec681f3Smrg 11707ec681f3Smrgstatic void 11717ec681f3Smrgthread_flush(struct lvp_device *device, struct lvp_fence *fence, uint64_t timeline, 11727ec681f3Smrg unsigned num_timelines, struct lvp_semaphore_timeline **timelines) 11737ec681f3Smrg{ 11747ec681f3Smrg struct pipe_fence_handle *handle = NULL; 11757ec681f3Smrg device->queue.ctx->flush(device->queue.ctx, &handle, 0); 11767ec681f3Smrg if (fence) 11777ec681f3Smrg device->pscreen->fence_reference(device->pscreen, &fence->handle, handle); 11787ec681f3Smrg set_last_fence(device, handle, timeline); 11797ec681f3Smrg /* this is the array of signaling timeline semaphore links */ 11807ec681f3Smrg for (unsigned i = 0; i < num_timelines; i++) 11817ec681f3Smrg device->pscreen->fence_reference(device->pscreen, &timelines[i]->fence, handle); 11827ec681f3Smrg 11837ec681f3Smrg device->pscreen->fence_reference(device->pscreen, &handle, NULL); 11847ec681f3Smrg} 11857ec681f3Smrg 11867ec681f3Smrg/* get a new timeline link for creating a new signal event 11877ec681f3Smrg * sema->lock MUST be locked before calling 11887ec681f3Smrg */ 11897ec681f3Smrgstatic struct lvp_semaphore_timeline * 11907ec681f3Smrgget_semaphore_link(struct lvp_semaphore *sema) 11917ec681f3Smrg{ 11927ec681f3Smrg if (!util_dynarray_num_elements(&sema->links, struct lvp_semaphore_timeline*)) { 11937ec681f3Smrg#define NUM_LINKS 50 11947ec681f3Smrg /* bucket allocate using the ralloc ctx because I like buckets */ 11957ec681f3Smrg struct lvp_semaphore_timeline *link = ralloc_array(sema->mem, struct lvp_semaphore_timeline, NUM_LINKS); 11967ec681f3Smrg for (unsigned i = 0; i < NUM_LINKS; i++) { 11977ec681f3Smrg link[i].next = NULL; 11987ec681f3Smrg link[i].fence = NULL; 11997ec681f3Smrg util_dynarray_append(&sema->links, struct lvp_semaphore_timeline*, &link[i]); 12007ec681f3Smrg } 12017ec681f3Smrg } 12027ec681f3Smrg struct lvp_semaphore_timeline *tl = util_dynarray_pop(&sema->links, struct lvp_semaphore_timeline*); 12037ec681f3Smrg if (sema->timeline) 12047ec681f3Smrg sema->latest->next = tl; 12057ec681f3Smrg else 12067ec681f3Smrg sema->timeline = tl; 12077ec681f3Smrg sema->latest = tl; 12087ec681f3Smrg return tl; 12097ec681f3Smrg} 12107ec681f3Smrg 12117ec681f3Smrg/* prune any timeline links which are older than the current device timeline id 12127ec681f3Smrg * sema->lock MUST be locked before calling 12137ec681f3Smrg */ 12147ec681f3Smrgstatic void 12157ec681f3Smrgprune_semaphore_links(struct lvp_device *device, 12167ec681f3Smrg struct lvp_semaphore *sema, uint64_t timeline) 12177ec681f3Smrg{ 12187ec681f3Smrg if (!timeline) 12197ec681f3Smrg /* zero isn't a valid id to prune with */ 12207ec681f3Smrg return; 12217ec681f3Smrg struct lvp_semaphore_timeline *tl = sema->timeline; 12227ec681f3Smrg /* walk the timeline links and pop all the ones that are old */ 12237ec681f3Smrg while (tl && ((tl->timeline <= timeline) || (tl->signal <= sema->current))) { 12247ec681f3Smrg struct lvp_semaphore_timeline *cur = tl; 12257ec681f3Smrg /* only update current timeline id if the update is monotonic */ 12267ec681f3Smrg if (sema->current < tl->signal) 12277ec681f3Smrg sema->current = tl->signal; 12287ec681f3Smrg util_dynarray_append(&sema->links, struct lvp_semaphore_timeline*, tl); 12297ec681f3Smrg tl = tl->next; 12307ec681f3Smrg cur->next = NULL; 12317ec681f3Smrg device->pscreen->fence_reference(device->pscreen, &cur->fence, NULL); 12327ec681f3Smrg } 12337ec681f3Smrg /* this is now the current timeline link */ 12347ec681f3Smrg sema->timeline = tl; 12357ec681f3Smrg} 12367ec681f3Smrg 12377ec681f3Smrg/* find a timeline id that can be waited on to satisfy the signal condition 12387ec681f3Smrg * sema->lock MUST be locked before calling 12397ec681f3Smrg */ 12407ec681f3Smrgstatic struct lvp_semaphore_timeline * 12417ec681f3Smrgfind_semaphore_timeline(struct lvp_semaphore *sema, uint64_t signal) 12427ec681f3Smrg{ 12437ec681f3Smrg for (struct lvp_semaphore_timeline *tl = sema->timeline; tl; tl = tl->next) { 12447ec681f3Smrg if (tl->signal >= signal) 12457ec681f3Smrg return tl; 12467ec681f3Smrg } 12477ec681f3Smrg /* never submitted or is completed */ 12487ec681f3Smrg return NULL; 12497ec681f3Smrg} 12507ec681f3Smrg 12517ec681f3Smrgstruct timeline_wait { 12527ec681f3Smrg bool done; 12537ec681f3Smrg struct lvp_semaphore_timeline *tl; 12547ec681f3Smrg}; 12557ec681f3Smrg 12567ec681f3Smrgstatic VkResult wait_semaphores(struct lvp_device *device, 12577ec681f3Smrg const VkSemaphoreWaitInfo* pWaitInfo, 12587ec681f3Smrg uint64_t timeout) 12597ec681f3Smrg{ 12607ec681f3Smrg /* build array of timeline links to poll */ 12617ec681f3Smrg VkResult ret = VK_TIMEOUT; 12627ec681f3Smrg bool any = (pWaitInfo->flags & VK_SEMAPHORE_WAIT_ANY_BIT) == VK_SEMAPHORE_WAIT_ANY_BIT; 12637ec681f3Smrg unsigned num_remaining = any ? 1 : pWaitInfo->semaphoreCount; 12647ec681f3Smrg /* just allocate an array for simplicity */ 12657ec681f3Smrg struct timeline_wait *tl_array = calloc(pWaitInfo->semaphoreCount, sizeof(struct timeline_wait)); 12667ec681f3Smrg 12677ec681f3Smrg int64_t abs_timeout = os_time_get_absolute_timeout(timeout); 12687ec681f3Smrg /* UINT64_MAX will always overflow, so special case it 12697ec681f3Smrg * otherwise, calculate ((timeout / num_semaphores) / 10) to allow waiting 10 times on every semaphore 12707ec681f3Smrg */ 12717ec681f3Smrg uint64_t wait_interval = timeout == UINT64_MAX ? 5000 : timeout / pWaitInfo->semaphoreCount / 10; 12727ec681f3Smrg while (num_remaining) { 12737ec681f3Smrg for (unsigned i = 0; num_remaining && i < pWaitInfo->semaphoreCount; i++) { 12747ec681f3Smrg if (tl_array[i].done) //completed 12757ec681f3Smrg continue; 12767ec681f3Smrg if (timeout && timeout != UINT64_MAX) { 12777ec681f3Smrg /* update remaining timeout on every loop */ 12787ec681f3Smrg int64_t time_ns = os_time_get_nano(); 12797ec681f3Smrg if (abs_timeout <= time_ns) 12807ec681f3Smrg goto end; 12817ec681f3Smrg timeout = abs_timeout > time_ns ? abs_timeout - time_ns : 0; 12827ec681f3Smrg } 12837ec681f3Smrg const uint64_t waitval = pWaitInfo->pValues[i]; 12847ec681f3Smrg LVP_FROM_HANDLE(lvp_semaphore, sema, pWaitInfo->pSemaphores[i]); 12857ec681f3Smrg if (sema->current >= waitval) { 12867ec681f3Smrg tl_array[i].done = true; 12877ec681f3Smrg num_remaining--; 12887ec681f3Smrg continue; 12897ec681f3Smrg } 12907ec681f3Smrg if (!tl_array[i].tl) { 12917ec681f3Smrg /* no timeline link was available yet: try to find one */ 12927ec681f3Smrg simple_mtx_lock(&sema->lock); 12937ec681f3Smrg /* always prune first to update current timeline id */ 12947ec681f3Smrg prune_semaphore_links(device, sema, device->queue.last_finished); 12957ec681f3Smrg tl_array[i].tl = find_semaphore_timeline(sema, waitval); 12967ec681f3Smrg if (timeout && !tl_array[i].tl) { 12977ec681f3Smrg /* still no timeline link available: 12987ec681f3Smrg * try waiting on the conditional for a broadcast instead of melting the cpu 12997ec681f3Smrg */ 13007ec681f3Smrg mtx_lock(&sema->submit_lock); 13017ec681f3Smrg struct timespec t; 13027ec681f3Smrg t.tv_nsec = wait_interval % 1000000000u; 13037ec681f3Smrg t.tv_sec = (wait_interval - t.tv_nsec) / 1000000000u; 13047ec681f3Smrg cnd_timedwait(&sema->submit, &sema->submit_lock, &t); 13057ec681f3Smrg mtx_unlock(&sema->submit_lock); 13067ec681f3Smrg tl_array[i].tl = find_semaphore_timeline(sema, waitval); 13077ec681f3Smrg } 13087ec681f3Smrg simple_mtx_unlock(&sema->lock); 13097ec681f3Smrg } 13107ec681f3Smrg /* mark semaphore as done if: 13117ec681f3Smrg * - timeline id comparison passes 13127ec681f3Smrg * - fence for timeline id exists and completes 13137ec681f3Smrg */ 13147ec681f3Smrg if (sema->current >= waitval || 13157ec681f3Smrg (tl_array[i].tl && 13167ec681f3Smrg tl_array[i].tl->fence && 13177ec681f3Smrg device->pscreen->fence_finish(device->pscreen, NULL, tl_array[i].tl->fence, wait_interval))) { 13187ec681f3Smrg tl_array[i].done = true; 13197ec681f3Smrg num_remaining--; 13207ec681f3Smrg } 13217ec681f3Smrg } 13227ec681f3Smrg if (!timeout) 13237ec681f3Smrg break; 13247ec681f3Smrg } 13257ec681f3Smrg if (!num_remaining) 13267ec681f3Smrg ret = VK_SUCCESS; 13277ec681f3Smrg 13287ec681f3Smrgend: 13297ec681f3Smrg free(tl_array); 13307ec681f3Smrg return ret; 13317ec681f3Smrg} 13327ec681f3Smrg 13337ec681f3Smrgvoid 13347ec681f3Smrgqueue_thread_noop(void *data, void *gdata, int thread_index) 13357ec681f3Smrg{ 13367ec681f3Smrg struct lvp_device *device = gdata; 13377ec681f3Smrg struct lvp_fence *fence = data; 13387ec681f3Smrg thread_flush(device, fence, fence->timeline, 0, NULL); 13397ec681f3Smrg} 13407ec681f3Smrg 13417ec681f3Smrgstatic void 13427ec681f3Smrgqueue_thread(void *data, void *gdata, int thread_index) 13437ec681f3Smrg{ 13447ec681f3Smrg struct lvp_queue_work *task = data; 13457ec681f3Smrg struct lvp_device *device = gdata; 13467ec681f3Smrg struct lvp_queue *queue = &device->queue; 13477ec681f3Smrg 13487ec681f3Smrg if (task->wait_count) { 13497ec681f3Smrg /* identical to WaitSemaphores */ 13507ec681f3Smrg VkSemaphoreWaitInfo wait; 13517ec681f3Smrg wait.flags = 0; //wait on all semaphores 13527ec681f3Smrg wait.semaphoreCount = task->wait_count; 13537ec681f3Smrg wait.pSemaphores = task->waits; 13547ec681f3Smrg wait.pValues = task->wait_vals; 13557ec681f3Smrg //wait 13567ec681f3Smrg wait_semaphores(device, &wait, UINT64_MAX); 13577ec681f3Smrg } 13587ec681f3Smrg 13597ec681f3Smrg //execute 13607ec681f3Smrg for (unsigned i = 0; i < task->cmd_buffer_count; i++) { 13617ec681f3Smrg lvp_execute_cmds(queue->device, queue, task->cmd_buffers[i]); 13627ec681f3Smrg } 13637ec681f3Smrg 13647ec681f3Smrg thread_flush(device, task->fence, task->timeline, task->timeline_count, task->timelines); 13657ec681f3Smrg free(task); 13667ec681f3Smrg} 13677ec681f3Smrg 13687ec681f3Smrgstatic VkResult 13697ec681f3Smrglvp_queue_init(struct lvp_device *device, struct lvp_queue *queue, 13707ec681f3Smrg const VkDeviceQueueCreateInfo *create_info, 13717ec681f3Smrg uint32_t index_in_family) 13727ec681f3Smrg{ 13737ec681f3Smrg VkResult result = vk_queue_init(&queue->vk, &device->vk, create_info, 13747ec681f3Smrg index_in_family); 13757ec681f3Smrg if (result != VK_SUCCESS) 13767ec681f3Smrg return result; 13777ec681f3Smrg 13787ec681f3Smrg queue->device = device; 13797ec681f3Smrg 13807ec681f3Smrg simple_mtx_init(&queue->last_lock, mtx_plain); 13817ec681f3Smrg queue->timeline = 0; 13827ec681f3Smrg queue->ctx = device->pscreen->context_create(device->pscreen, NULL, PIPE_CONTEXT_ROBUST_BUFFER_ACCESS); 13837ec681f3Smrg queue->cso = cso_create_context(queue->ctx, CSO_NO_VBUF); 13847ec681f3Smrg util_queue_init(&queue->queue, "lavapipe", 8, 1, UTIL_QUEUE_INIT_RESIZE_IF_FULL, device); 13857ec681f3Smrg p_atomic_set(&queue->count, 0); 13867ec681f3Smrg 13877ec681f3Smrg return VK_SUCCESS; 13887ec681f3Smrg} 13897ec681f3Smrg 13907ec681f3Smrgstatic void 13917ec681f3Smrglvp_queue_finish(struct lvp_queue *queue) 13927ec681f3Smrg{ 13937ec681f3Smrg util_queue_finish(&queue->queue); 13947ec681f3Smrg util_queue_destroy(&queue->queue); 13957ec681f3Smrg 13967ec681f3Smrg cso_destroy_context(queue->cso); 13977ec681f3Smrg queue->ctx->destroy(queue->ctx); 13987ec681f3Smrg simple_mtx_destroy(&queue->last_lock); 13997ec681f3Smrg 14007ec681f3Smrg vk_queue_finish(&queue->vk); 14017ec681f3Smrg} 14027ec681f3Smrg 14037ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDevice( 14047ec681f3Smrg VkPhysicalDevice physicalDevice, 14057ec681f3Smrg const VkDeviceCreateInfo* pCreateInfo, 14067ec681f3Smrg const VkAllocationCallbacks* pAllocator, 14077ec681f3Smrg VkDevice* pDevice) 14087ec681f3Smrg{ 14097ec681f3Smrg fprintf(stderr, "WARNING: lavapipe is not a conformant vulkan implementation, testing use only.\n"); 14107ec681f3Smrg 14117ec681f3Smrg LVP_FROM_HANDLE(lvp_physical_device, physical_device, physicalDevice); 14127ec681f3Smrg struct lvp_device *device; 14137ec681f3Smrg struct lvp_instance *instance = (struct lvp_instance *)physical_device->vk.instance; 14147ec681f3Smrg 14157ec681f3Smrg assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO); 14167ec681f3Smrg 14177ec681f3Smrg device = vk_zalloc2(&physical_device->vk.instance->alloc, pAllocator, 14187ec681f3Smrg sizeof(*device), 8, 14197ec681f3Smrg VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 14207ec681f3Smrg if (!device) 14217ec681f3Smrg return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); 14227ec681f3Smrg 14237ec681f3Smrg struct vk_device_dispatch_table dispatch_table; 14247ec681f3Smrg vk_device_dispatch_table_from_entrypoints(&dispatch_table, 14257ec681f3Smrg &lvp_device_entrypoints, true); 14267ec681f3Smrg vk_device_dispatch_table_from_entrypoints(&dispatch_table, 14277ec681f3Smrg &wsi_device_entrypoints, false); 14287ec681f3Smrg VkResult result = vk_device_init(&device->vk, 14297ec681f3Smrg &physical_device->vk, 14307ec681f3Smrg &dispatch_table, pCreateInfo, 14317ec681f3Smrg pAllocator); 14327ec681f3Smrg if (result != VK_SUCCESS) { 14337ec681f3Smrg vk_free(&device->vk.alloc, device); 14347ec681f3Smrg return result; 14357ec681f3Smrg } 14367ec681f3Smrg 14377ec681f3Smrg device->instance = (struct lvp_instance *)physical_device->vk.instance; 14387ec681f3Smrg device->physical_device = physical_device; 14397ec681f3Smrg 14407ec681f3Smrg device->pscreen = physical_device->pscreen; 14417ec681f3Smrg 14427ec681f3Smrg assert(pCreateInfo->queueCreateInfoCount == 1); 14437ec681f3Smrg assert(pCreateInfo->pQueueCreateInfos[0].queueFamilyIndex == 0); 14447ec681f3Smrg assert(pCreateInfo->pQueueCreateInfos[0].queueCount == 1); 14457ec681f3Smrg lvp_queue_init(device, &device->queue, pCreateInfo->pQueueCreateInfos, 0); 14467ec681f3Smrg 14477ec681f3Smrg *pDevice = lvp_device_to_handle(device); 14487ec681f3Smrg 14497ec681f3Smrg return VK_SUCCESS; 14507ec681f3Smrg 14517ec681f3Smrg} 14527ec681f3Smrg 14537ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_DestroyDevice( 14547ec681f3Smrg VkDevice _device, 14557ec681f3Smrg const VkAllocationCallbacks* pAllocator) 14567ec681f3Smrg{ 14577ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 14587ec681f3Smrg 14597ec681f3Smrg if (device->queue.last_fence) 14607ec681f3Smrg device->pscreen->fence_reference(device->pscreen, &device->queue.last_fence, NULL); 14617ec681f3Smrg lvp_queue_finish(&device->queue); 14627ec681f3Smrg vk_device_finish(&device->vk); 14637ec681f3Smrg vk_free(&device->vk.alloc, device); 14647ec681f3Smrg} 14657ec681f3Smrg 14667ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_EnumerateInstanceExtensionProperties( 14677ec681f3Smrg const char* pLayerName, 14687ec681f3Smrg uint32_t* pPropertyCount, 14697ec681f3Smrg VkExtensionProperties* pProperties) 14707ec681f3Smrg{ 14717ec681f3Smrg if (pLayerName) 14727ec681f3Smrg return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); 14737ec681f3Smrg 14747ec681f3Smrg return vk_enumerate_instance_extension_properties( 14757ec681f3Smrg &lvp_instance_extensions_supported, pPropertyCount, pProperties); 14767ec681f3Smrg} 14777ec681f3Smrg 14787ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_EnumerateInstanceLayerProperties( 14797ec681f3Smrg uint32_t* pPropertyCount, 14807ec681f3Smrg VkLayerProperties* pProperties) 14817ec681f3Smrg{ 14827ec681f3Smrg if (pProperties == NULL) { 14837ec681f3Smrg *pPropertyCount = 0; 14847ec681f3Smrg return VK_SUCCESS; 14857ec681f3Smrg } 14867ec681f3Smrg 14877ec681f3Smrg /* None supported at this time */ 14887ec681f3Smrg return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); 14897ec681f3Smrg} 14907ec681f3Smrg 14917ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_EnumerateDeviceLayerProperties( 14927ec681f3Smrg VkPhysicalDevice physicalDevice, 14937ec681f3Smrg uint32_t* pPropertyCount, 14947ec681f3Smrg VkLayerProperties* pProperties) 14957ec681f3Smrg{ 14967ec681f3Smrg if (pProperties == NULL) { 14977ec681f3Smrg *pPropertyCount = 0; 14987ec681f3Smrg return VK_SUCCESS; 14997ec681f3Smrg } 15007ec681f3Smrg 15017ec681f3Smrg /* None supported at this time */ 15027ec681f3Smrg return vk_error(NULL, VK_ERROR_LAYER_NOT_PRESENT); 15037ec681f3Smrg} 15047ec681f3Smrg 15057ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_QueueSubmit( 15067ec681f3Smrg VkQueue _queue, 15077ec681f3Smrg uint32_t submitCount, 15087ec681f3Smrg const VkSubmitInfo* pSubmits, 15097ec681f3Smrg VkFence _fence) 15107ec681f3Smrg{ 15117ec681f3Smrg LVP_FROM_HANDLE(lvp_queue, queue, _queue); 15127ec681f3Smrg LVP_FROM_HANDLE(lvp_fence, fence, _fence); 15137ec681f3Smrg 15147ec681f3Smrg /* each submit is a separate job to simplify/streamline semaphore waits */ 15157ec681f3Smrg for (uint32_t i = 0; i < submitCount; i++) { 15167ec681f3Smrg uint64_t timeline = ++queue->timeline; 15177ec681f3Smrg struct lvp_queue_work *task = malloc(sizeof(struct lvp_queue_work) + 15187ec681f3Smrg pSubmits[i].commandBufferCount * sizeof(struct lvp_cmd_buffer *) + 15197ec681f3Smrg pSubmits[i].signalSemaphoreCount * sizeof(struct lvp_semaphore_timeline*) + 15207ec681f3Smrg pSubmits[i].waitSemaphoreCount * (sizeof(VkSemaphore) + sizeof(uint64_t))); 15217ec681f3Smrg task->cmd_buffer_count = pSubmits[i].commandBufferCount; 15227ec681f3Smrg task->timeline_count = pSubmits[i].signalSemaphoreCount; 15237ec681f3Smrg task->wait_count = pSubmits[i].waitSemaphoreCount; 15247ec681f3Smrg task->fence = fence; 15257ec681f3Smrg task->timeline = timeline; 15267ec681f3Smrg task->cmd_buffers = (struct lvp_cmd_buffer **)(task + 1); 15277ec681f3Smrg task->timelines = (struct lvp_semaphore_timeline**)((uint8_t*)task->cmd_buffers + pSubmits[i].commandBufferCount * sizeof(struct lvp_cmd_buffer *)); 15287ec681f3Smrg task->waits = (VkSemaphore*)((uint8_t*)task->timelines + pSubmits[i].signalSemaphoreCount * sizeof(struct lvp_semaphore_timeline *)); 15297ec681f3Smrg task->wait_vals = (uint64_t*)((uint8_t*)task->waits + pSubmits[i].waitSemaphoreCount * sizeof(VkSemaphore)); 15307ec681f3Smrg 15317ec681f3Smrg unsigned c = 0; 15327ec681f3Smrg for (uint32_t j = 0; j < pSubmits[i].commandBufferCount; j++) { 15337ec681f3Smrg task->cmd_buffers[c++] = lvp_cmd_buffer_from_handle(pSubmits[i].pCommandBuffers[j]); 15347ec681f3Smrg } 15357ec681f3Smrg const VkTimelineSemaphoreSubmitInfo *info = vk_find_struct_const(pSubmits[i].pNext, TIMELINE_SEMAPHORE_SUBMIT_INFO); 15367ec681f3Smrg unsigned s = 0; 15377ec681f3Smrg for (unsigned j = 0; j < pSubmits[i].signalSemaphoreCount; j++) { 15387ec681f3Smrg LVP_FROM_HANDLE(lvp_semaphore, sema, pSubmits[i].pSignalSemaphores[j]); 15397ec681f3Smrg if (!sema->is_timeline) { 15407ec681f3Smrg /* non-timeline semaphores never matter to lavapipe */ 15417ec681f3Smrg task->timeline_count--; 15427ec681f3Smrg continue; 15437ec681f3Smrg } 15447ec681f3Smrg simple_mtx_lock(&sema->lock); 15457ec681f3Smrg /* always prune first to make links available and update timeline id */ 15467ec681f3Smrg prune_semaphore_links(queue->device, sema, queue->last_finished); 15477ec681f3Smrg if (sema->current < info->pSignalSemaphoreValues[j]) { 15487ec681f3Smrg /* only signal semaphores if the new id is >= the current one */ 15497ec681f3Smrg struct lvp_semaphore_timeline *tl = get_semaphore_link(sema); 15507ec681f3Smrg tl->signal = info->pSignalSemaphoreValues[j]; 15517ec681f3Smrg tl->timeline = timeline; 15527ec681f3Smrg task->timelines[s] = tl; 15537ec681f3Smrg s++; 15547ec681f3Smrg } else 15557ec681f3Smrg task->timeline_count--; 15567ec681f3Smrg simple_mtx_unlock(&sema->lock); 15577ec681f3Smrg } 15587ec681f3Smrg unsigned w = 0; 15597ec681f3Smrg for (unsigned j = 0; j < pSubmits[i].waitSemaphoreCount; j++) { 15607ec681f3Smrg LVP_FROM_HANDLE(lvp_semaphore, sema, pSubmits[i].pWaitSemaphores[j]); 15617ec681f3Smrg if (!sema->is_timeline) { 15627ec681f3Smrg /* non-timeline semaphores never matter to lavapipe */ 15637ec681f3Smrg task->wait_count--; 15647ec681f3Smrg continue; 15657ec681f3Smrg } 15667ec681f3Smrg simple_mtx_lock(&sema->lock); 15677ec681f3Smrg /* always prune first to update timeline id */ 15687ec681f3Smrg prune_semaphore_links(queue->device, sema, queue->last_finished); 15697ec681f3Smrg if (info->pWaitSemaphoreValues[j] && 15707ec681f3Smrg pSubmits[i].pWaitDstStageMask && pSubmits[i].pWaitDstStageMask[j] && 15717ec681f3Smrg sema->current < info->pWaitSemaphoreValues[j]) { 15727ec681f3Smrg /* only wait on semaphores if the new id is > the current one and a wait mask is set 15737ec681f3Smrg * 15747ec681f3Smrg * technically the mask could be used to check whether there's gfx/compute ops on a cmdbuf and no-op, 15757ec681f3Smrg * but probably that's not worth the complexity 15767ec681f3Smrg */ 15777ec681f3Smrg task->waits[w] = pSubmits[i].pWaitSemaphores[j]; 15787ec681f3Smrg task->wait_vals[w] = info->pWaitSemaphoreValues[j]; 15797ec681f3Smrg w++; 15807ec681f3Smrg } else 15817ec681f3Smrg task->wait_count--; 15827ec681f3Smrg simple_mtx_unlock(&sema->lock); 15837ec681f3Smrg } 15847ec681f3Smrg if (fence && i == submitCount - 1) { 15857ec681f3Smrg /* u_queue fences should only be signaled for the last submit, as this is the one that 15867ec681f3Smrg * the vk fence represents 15877ec681f3Smrg */ 15887ec681f3Smrg fence->timeline = timeline; 15897ec681f3Smrg util_queue_add_job(&queue->queue, task, &fence->fence, queue_thread, NULL, 0); 15907ec681f3Smrg } else 15917ec681f3Smrg util_queue_add_job(&queue->queue, task, NULL, queue_thread, NULL, 0); 15927ec681f3Smrg } 15937ec681f3Smrg if (!submitCount && fence) { 15947ec681f3Smrg /* special case where a fence is created to use as a synchronization point */ 15957ec681f3Smrg fence->timeline = p_atomic_inc_return(&queue->timeline); 15967ec681f3Smrg util_queue_add_job(&queue->queue, fence, &fence->fence, queue_thread_noop, NULL, 0); 15977ec681f3Smrg } 15987ec681f3Smrg 15997ec681f3Smrg return VK_SUCCESS; 16007ec681f3Smrg} 16017ec681f3Smrg 16027ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_QueueWaitIdle( 16037ec681f3Smrg VkQueue _queue) 16047ec681f3Smrg{ 16057ec681f3Smrg LVP_FROM_HANDLE(lvp_queue, queue, _queue); 16067ec681f3Smrg 16077ec681f3Smrg util_queue_finish(&queue->queue); 16087ec681f3Smrg simple_mtx_lock(&queue->last_lock); 16097ec681f3Smrg uint64_t timeline = queue->last_fence_timeline; 16107ec681f3Smrg if (queue->last_fence) { 16117ec681f3Smrg queue->device->pscreen->fence_finish(queue->device->pscreen, NULL, queue->last_fence, PIPE_TIMEOUT_INFINITE); 16127ec681f3Smrg queue->device->pscreen->fence_reference(queue->device->pscreen, &queue->device->queue.last_fence, NULL); 16137ec681f3Smrg queue->last_finished = timeline; 16147ec681f3Smrg } 16157ec681f3Smrg simple_mtx_unlock(&queue->last_lock); 16167ec681f3Smrg return VK_SUCCESS; 16177ec681f3Smrg} 16187ec681f3Smrg 16197ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_DeviceWaitIdle( 16207ec681f3Smrg VkDevice _device) 16217ec681f3Smrg{ 16227ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 16237ec681f3Smrg 16247ec681f3Smrg lvp_QueueWaitIdle(lvp_queue_to_handle(&device->queue)); 16257ec681f3Smrg 16267ec681f3Smrg return VK_SUCCESS; 16277ec681f3Smrg} 16287ec681f3Smrg 16297ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_AllocateMemory( 16307ec681f3Smrg VkDevice _device, 16317ec681f3Smrg const VkMemoryAllocateInfo* pAllocateInfo, 16327ec681f3Smrg const VkAllocationCallbacks* pAllocator, 16337ec681f3Smrg VkDeviceMemory* pMem) 16347ec681f3Smrg{ 16357ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 16367ec681f3Smrg struct lvp_device_memory *mem; 16377ec681f3Smrg const VkExportMemoryAllocateInfo *export_info = NULL; 16387ec681f3Smrg const VkImportMemoryFdInfoKHR *import_info = NULL; 16397ec681f3Smrg const VkImportMemoryHostPointerInfoEXT *host_ptr_info = NULL; 16407ec681f3Smrg VkResult error = VK_ERROR_OUT_OF_DEVICE_MEMORY; 16417ec681f3Smrg assert(pAllocateInfo->sType == VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO); 16427ec681f3Smrg 16437ec681f3Smrg if (pAllocateInfo->allocationSize == 0) { 16447ec681f3Smrg /* Apparently, this is allowed */ 16457ec681f3Smrg *pMem = VK_NULL_HANDLE; 16467ec681f3Smrg return VK_SUCCESS; 16477ec681f3Smrg } 16487ec681f3Smrg 16497ec681f3Smrg vk_foreach_struct_const(ext, pAllocateInfo->pNext) { 16507ec681f3Smrg switch ((unsigned)ext->sType) { 16517ec681f3Smrg case VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT: 16527ec681f3Smrg host_ptr_info = (VkImportMemoryHostPointerInfoEXT*)ext; 16537ec681f3Smrg assert(host_ptr_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT); 16547ec681f3Smrg break; 16557ec681f3Smrg case VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO: 16567ec681f3Smrg export_info = (VkExportMemoryAllocateInfo*)ext; 16577ec681f3Smrg assert(export_info->handleTypes == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); 16587ec681f3Smrg break; 16597ec681f3Smrg case VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR: 16607ec681f3Smrg import_info = (VkImportMemoryFdInfoKHR*)ext; 16617ec681f3Smrg assert(import_info->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); 16627ec681f3Smrg break; 16637ec681f3Smrg default: 16647ec681f3Smrg break; 16657ec681f3Smrg } 16667ec681f3Smrg } 16677ec681f3Smrg 16687ec681f3Smrg#ifdef PIPE_MEMORY_FD 16697ec681f3Smrg if (import_info != NULL && import_info->fd < 0) { 16707ec681f3Smrg return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); 16717ec681f3Smrg } 16727ec681f3Smrg#endif 16737ec681f3Smrg 16747ec681f3Smrg mem = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*mem), 8, 16757ec681f3Smrg VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 16767ec681f3Smrg if (mem == NULL) 16777ec681f3Smrg return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 16787ec681f3Smrg 16797ec681f3Smrg vk_object_base_init(&device->vk, &mem->base, 16807ec681f3Smrg VK_OBJECT_TYPE_DEVICE_MEMORY); 16817ec681f3Smrg 16827ec681f3Smrg mem->memory_type = LVP_DEVICE_MEMORY_TYPE_DEFAULT; 16837ec681f3Smrg mem->backed_fd = -1; 16847ec681f3Smrg 16857ec681f3Smrg if (host_ptr_info) { 16867ec681f3Smrg mem->pmem = host_ptr_info->pHostPointer; 16877ec681f3Smrg mem->memory_type = LVP_DEVICE_MEMORY_TYPE_USER_PTR; 16887ec681f3Smrg } 16897ec681f3Smrg#ifdef PIPE_MEMORY_FD 16907ec681f3Smrg else if(import_info) { 16917ec681f3Smrg uint64_t size; 16927ec681f3Smrg if(!device->pscreen->import_memory_fd(device->pscreen, import_info->fd, &mem->pmem, &size)) { 16937ec681f3Smrg close(import_info->fd); 16947ec681f3Smrg error = VK_ERROR_INVALID_EXTERNAL_HANDLE; 16957ec681f3Smrg goto fail; 16967ec681f3Smrg } 16977ec681f3Smrg if(size < pAllocateInfo->allocationSize) { 16987ec681f3Smrg device->pscreen->free_memory_fd(device->pscreen, mem->pmem); 16997ec681f3Smrg close(import_info->fd); 17007ec681f3Smrg goto fail; 17017ec681f3Smrg } 17027ec681f3Smrg if (export_info) { 17037ec681f3Smrg mem->backed_fd = import_info->fd; 17047ec681f3Smrg } 17057ec681f3Smrg else { 17067ec681f3Smrg close(import_info->fd); 17077ec681f3Smrg } 17087ec681f3Smrg mem->memory_type = LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD; 17097ec681f3Smrg } 17107ec681f3Smrg else if (export_info) { 17117ec681f3Smrg mem->pmem = device->pscreen->allocate_memory_fd(device->pscreen, pAllocateInfo->allocationSize, &mem->backed_fd); 17127ec681f3Smrg if (!mem->pmem || mem->backed_fd < 0) { 17137ec681f3Smrg goto fail; 17147ec681f3Smrg } 17157ec681f3Smrg mem->memory_type = LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD; 17167ec681f3Smrg } 17177ec681f3Smrg#endif 17187ec681f3Smrg else { 17197ec681f3Smrg mem->pmem = device->pscreen->allocate_memory(device->pscreen, pAllocateInfo->allocationSize); 17207ec681f3Smrg if (!mem->pmem) { 17217ec681f3Smrg goto fail; 17227ec681f3Smrg } 17237ec681f3Smrg } 17247ec681f3Smrg 17257ec681f3Smrg mem->type_index = pAllocateInfo->memoryTypeIndex; 17267ec681f3Smrg 17277ec681f3Smrg *pMem = lvp_device_memory_to_handle(mem); 17287ec681f3Smrg 17297ec681f3Smrg return VK_SUCCESS; 17307ec681f3Smrg 17317ec681f3Smrgfail: 17327ec681f3Smrg vk_free2(&device->vk.alloc, pAllocator, mem); 17337ec681f3Smrg return vk_error(device, error); 17347ec681f3Smrg} 17357ec681f3Smrg 17367ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_FreeMemory( 17377ec681f3Smrg VkDevice _device, 17387ec681f3Smrg VkDeviceMemory _mem, 17397ec681f3Smrg const VkAllocationCallbacks* pAllocator) 17407ec681f3Smrg{ 17417ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 17427ec681f3Smrg LVP_FROM_HANDLE(lvp_device_memory, mem, _mem); 17437ec681f3Smrg 17447ec681f3Smrg if (mem == NULL) 17457ec681f3Smrg return; 17467ec681f3Smrg 17477ec681f3Smrg switch(mem->memory_type) { 17487ec681f3Smrg case LVP_DEVICE_MEMORY_TYPE_DEFAULT: 17497ec681f3Smrg device->pscreen->free_memory(device->pscreen, mem->pmem); 17507ec681f3Smrg break; 17517ec681f3Smrg#ifdef PIPE_MEMORY_FD 17527ec681f3Smrg case LVP_DEVICE_MEMORY_TYPE_OPAQUE_FD: 17537ec681f3Smrg device->pscreen->free_memory_fd(device->pscreen, mem->pmem); 17547ec681f3Smrg if(mem->backed_fd >= 0) 17557ec681f3Smrg close(mem->backed_fd); 17567ec681f3Smrg break; 17577ec681f3Smrg#endif 17587ec681f3Smrg case LVP_DEVICE_MEMORY_TYPE_USER_PTR: 17597ec681f3Smrg default: 17607ec681f3Smrg break; 17617ec681f3Smrg } 17627ec681f3Smrg vk_object_base_finish(&mem->base); 17637ec681f3Smrg vk_free2(&device->vk.alloc, pAllocator, mem); 17647ec681f3Smrg 17657ec681f3Smrg} 17667ec681f3Smrg 17677ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_MapMemory( 17687ec681f3Smrg VkDevice _device, 17697ec681f3Smrg VkDeviceMemory _memory, 17707ec681f3Smrg VkDeviceSize offset, 17717ec681f3Smrg VkDeviceSize size, 17727ec681f3Smrg VkMemoryMapFlags flags, 17737ec681f3Smrg void** ppData) 17747ec681f3Smrg{ 17757ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 17767ec681f3Smrg LVP_FROM_HANDLE(lvp_device_memory, mem, _memory); 17777ec681f3Smrg void *map; 17787ec681f3Smrg if (mem == NULL) { 17797ec681f3Smrg *ppData = NULL; 17807ec681f3Smrg return VK_SUCCESS; 17817ec681f3Smrg } 17827ec681f3Smrg 17837ec681f3Smrg map = device->pscreen->map_memory(device->pscreen, mem->pmem); 17847ec681f3Smrg 17857ec681f3Smrg *ppData = (char *)map + offset; 17867ec681f3Smrg return VK_SUCCESS; 17877ec681f3Smrg} 17887ec681f3Smrg 17897ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_UnmapMemory( 17907ec681f3Smrg VkDevice _device, 17917ec681f3Smrg VkDeviceMemory _memory) 17927ec681f3Smrg{ 17937ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 17947ec681f3Smrg LVP_FROM_HANDLE(lvp_device_memory, mem, _memory); 17957ec681f3Smrg 17967ec681f3Smrg if (mem == NULL) 17977ec681f3Smrg return; 17987ec681f3Smrg 17997ec681f3Smrg device->pscreen->unmap_memory(device->pscreen, mem->pmem); 18007ec681f3Smrg} 18017ec681f3Smrg 18027ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_FlushMappedMemoryRanges( 18037ec681f3Smrg VkDevice _device, 18047ec681f3Smrg uint32_t memoryRangeCount, 18057ec681f3Smrg const VkMappedMemoryRange* pMemoryRanges) 18067ec681f3Smrg{ 18077ec681f3Smrg return VK_SUCCESS; 18087ec681f3Smrg} 18097ec681f3Smrg 18107ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_InvalidateMappedMemoryRanges( 18117ec681f3Smrg VkDevice _device, 18127ec681f3Smrg uint32_t memoryRangeCount, 18137ec681f3Smrg const VkMappedMemoryRange* pMemoryRanges) 18147ec681f3Smrg{ 18157ec681f3Smrg return VK_SUCCESS; 18167ec681f3Smrg} 18177ec681f3Smrg 18187ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetBufferMemoryRequirements( 18197ec681f3Smrg VkDevice device, 18207ec681f3Smrg VkBuffer _buffer, 18217ec681f3Smrg VkMemoryRequirements* pMemoryRequirements) 18227ec681f3Smrg{ 18237ec681f3Smrg LVP_FROM_HANDLE(lvp_buffer, buffer, _buffer); 18247ec681f3Smrg 18257ec681f3Smrg /* The Vulkan spec (git aaed022) says: 18267ec681f3Smrg * 18277ec681f3Smrg * memoryTypeBits is a bitfield and contains one bit set for every 18287ec681f3Smrg * supported memory type for the resource. The bit `1<<i` is set if and 18297ec681f3Smrg * only if the memory type `i` in the VkPhysicalDeviceMemoryProperties 18307ec681f3Smrg * structure for the physical device is supported. 18317ec681f3Smrg * 18327ec681f3Smrg * We support exactly one memory type. 18337ec681f3Smrg */ 18347ec681f3Smrg pMemoryRequirements->memoryTypeBits = 1; 18357ec681f3Smrg 18367ec681f3Smrg pMemoryRequirements->size = buffer->total_size; 18377ec681f3Smrg pMemoryRequirements->alignment = 64; 18387ec681f3Smrg} 18397ec681f3Smrg 18407ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetBufferMemoryRequirements2( 18417ec681f3Smrg VkDevice device, 18427ec681f3Smrg const VkBufferMemoryRequirementsInfo2 *pInfo, 18437ec681f3Smrg VkMemoryRequirements2 *pMemoryRequirements) 18447ec681f3Smrg{ 18457ec681f3Smrg lvp_GetBufferMemoryRequirements(device, pInfo->buffer, 18467ec681f3Smrg &pMemoryRequirements->memoryRequirements); 18477ec681f3Smrg vk_foreach_struct(ext, pMemoryRequirements->pNext) { 18487ec681f3Smrg switch (ext->sType) { 18497ec681f3Smrg case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: { 18507ec681f3Smrg VkMemoryDedicatedRequirements *req = 18517ec681f3Smrg (VkMemoryDedicatedRequirements *) ext; 18527ec681f3Smrg req->requiresDedicatedAllocation = false; 18537ec681f3Smrg req->prefersDedicatedAllocation = req->requiresDedicatedAllocation; 18547ec681f3Smrg break; 18557ec681f3Smrg } 18567ec681f3Smrg default: 18577ec681f3Smrg break; 18587ec681f3Smrg } 18597ec681f3Smrg } 18607ec681f3Smrg} 18617ec681f3Smrg 18627ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetImageMemoryRequirements( 18637ec681f3Smrg VkDevice device, 18647ec681f3Smrg VkImage _image, 18657ec681f3Smrg VkMemoryRequirements* pMemoryRequirements) 18667ec681f3Smrg{ 18677ec681f3Smrg LVP_FROM_HANDLE(lvp_image, image, _image); 18687ec681f3Smrg pMemoryRequirements->memoryTypeBits = 1; 18697ec681f3Smrg 18707ec681f3Smrg pMemoryRequirements->size = image->size; 18717ec681f3Smrg pMemoryRequirements->alignment = image->alignment; 18727ec681f3Smrg} 18737ec681f3Smrg 18747ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetImageMemoryRequirements2( 18757ec681f3Smrg VkDevice device, 18767ec681f3Smrg const VkImageMemoryRequirementsInfo2 *pInfo, 18777ec681f3Smrg VkMemoryRequirements2 *pMemoryRequirements) 18787ec681f3Smrg{ 18797ec681f3Smrg lvp_GetImageMemoryRequirements(device, pInfo->image, 18807ec681f3Smrg &pMemoryRequirements->memoryRequirements); 18817ec681f3Smrg 18827ec681f3Smrg vk_foreach_struct(ext, pMemoryRequirements->pNext) { 18837ec681f3Smrg switch (ext->sType) { 18847ec681f3Smrg case VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS: { 18857ec681f3Smrg VkMemoryDedicatedRequirements *req = 18867ec681f3Smrg (VkMemoryDedicatedRequirements *) ext; 18877ec681f3Smrg req->requiresDedicatedAllocation = false; 18887ec681f3Smrg req->prefersDedicatedAllocation = req->requiresDedicatedAllocation; 18897ec681f3Smrg break; 18907ec681f3Smrg } 18917ec681f3Smrg default: 18927ec681f3Smrg break; 18937ec681f3Smrg } 18947ec681f3Smrg } 18957ec681f3Smrg} 18967ec681f3Smrg 18977ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetImageSparseMemoryRequirements( 18987ec681f3Smrg VkDevice device, 18997ec681f3Smrg VkImage image, 19007ec681f3Smrg uint32_t* pSparseMemoryRequirementCount, 19017ec681f3Smrg VkSparseImageMemoryRequirements* pSparseMemoryRequirements) 19027ec681f3Smrg{ 19037ec681f3Smrg stub(); 19047ec681f3Smrg} 19057ec681f3Smrg 19067ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetImageSparseMemoryRequirements2( 19077ec681f3Smrg VkDevice device, 19087ec681f3Smrg const VkImageSparseMemoryRequirementsInfo2* pInfo, 19097ec681f3Smrg uint32_t* pSparseMemoryRequirementCount, 19107ec681f3Smrg VkSparseImageMemoryRequirements2* pSparseMemoryRequirements) 19117ec681f3Smrg{ 19127ec681f3Smrg stub(); 19137ec681f3Smrg} 19147ec681f3Smrg 19157ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetDeviceMemoryCommitment( 19167ec681f3Smrg VkDevice device, 19177ec681f3Smrg VkDeviceMemory memory, 19187ec681f3Smrg VkDeviceSize* pCommittedMemoryInBytes) 19197ec681f3Smrg{ 19207ec681f3Smrg *pCommittedMemoryInBytes = 0; 19217ec681f3Smrg} 19227ec681f3Smrg 19237ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_BindBufferMemory2(VkDevice _device, 19247ec681f3Smrg uint32_t bindInfoCount, 19257ec681f3Smrg const VkBindBufferMemoryInfo *pBindInfos) 19267ec681f3Smrg{ 19277ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 19287ec681f3Smrg for (uint32_t i = 0; i < bindInfoCount; ++i) { 19297ec681f3Smrg LVP_FROM_HANDLE(lvp_device_memory, mem, pBindInfos[i].memory); 19307ec681f3Smrg LVP_FROM_HANDLE(lvp_buffer, buffer, pBindInfos[i].buffer); 19317ec681f3Smrg 19327ec681f3Smrg buffer->pmem = mem->pmem; 19337ec681f3Smrg device->pscreen->resource_bind_backing(device->pscreen, 19347ec681f3Smrg buffer->bo, 19357ec681f3Smrg mem->pmem, 19367ec681f3Smrg pBindInfos[i].memoryOffset); 19377ec681f3Smrg } 19387ec681f3Smrg return VK_SUCCESS; 19397ec681f3Smrg} 19407ec681f3Smrg 19417ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_BindImageMemory2(VkDevice _device, 19427ec681f3Smrg uint32_t bindInfoCount, 19437ec681f3Smrg const VkBindImageMemoryInfo *pBindInfos) 19447ec681f3Smrg{ 19457ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 19467ec681f3Smrg for (uint32_t i = 0; i < bindInfoCount; ++i) { 19477ec681f3Smrg const VkBindImageMemoryInfo *bind_info = &pBindInfos[i]; 19487ec681f3Smrg LVP_FROM_HANDLE(lvp_device_memory, mem, bind_info->memory); 19497ec681f3Smrg LVP_FROM_HANDLE(lvp_image, image, bind_info->image); 19507ec681f3Smrg bool did_bind = false; 19517ec681f3Smrg 19527ec681f3Smrg vk_foreach_struct_const(s, bind_info->pNext) { 19537ec681f3Smrg switch (s->sType) { 19547ec681f3Smrg case VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR: { 19557ec681f3Smrg const VkBindImageMemorySwapchainInfoKHR *swapchain_info = 19567ec681f3Smrg (const VkBindImageMemorySwapchainInfoKHR *) s; 19577ec681f3Smrg struct lvp_image *swapchain_image = 19587ec681f3Smrg lvp_swapchain_get_image(swapchain_info->swapchain, 19597ec681f3Smrg swapchain_info->imageIndex); 19607ec681f3Smrg 19617ec681f3Smrg image->pmem = swapchain_image->pmem; 19627ec681f3Smrg image->memory_offset = swapchain_image->memory_offset; 19637ec681f3Smrg device->pscreen->resource_bind_backing(device->pscreen, 19647ec681f3Smrg image->bo, 19657ec681f3Smrg image->pmem, 19667ec681f3Smrg image->memory_offset); 19677ec681f3Smrg did_bind = true; 19687ec681f3Smrg } 19697ec681f3Smrg default: 19707ec681f3Smrg break; 19717ec681f3Smrg } 19727ec681f3Smrg } 19737ec681f3Smrg 19747ec681f3Smrg if (!did_bind) { 19757ec681f3Smrg if (!device->pscreen->resource_bind_backing(device->pscreen, 19767ec681f3Smrg image->bo, 19777ec681f3Smrg mem->pmem, 19787ec681f3Smrg bind_info->memoryOffset)) { 19797ec681f3Smrg /* This is probably caused by the texture being too large, so let's 19807ec681f3Smrg * report this as the *closest* allowed error-code. It's not ideal, 19817ec681f3Smrg * but it's unlikely that anyone will care too much. 19827ec681f3Smrg */ 19837ec681f3Smrg return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY); 19847ec681f3Smrg } 19857ec681f3Smrg image->pmem = mem->pmem; 19867ec681f3Smrg image->memory_offset = bind_info->memoryOffset; 19877ec681f3Smrg } 19887ec681f3Smrg } 19897ec681f3Smrg return VK_SUCCESS; 19907ec681f3Smrg} 19917ec681f3Smrg 19927ec681f3Smrg#ifdef PIPE_MEMORY_FD 19937ec681f3Smrg 19947ec681f3SmrgVkResult 19957ec681f3Smrglvp_GetMemoryFdKHR(VkDevice _device, const VkMemoryGetFdInfoKHR *pGetFdInfo, int *pFD) 19967ec681f3Smrg{ 19977ec681f3Smrg LVP_FROM_HANDLE(lvp_device_memory, memory, pGetFdInfo->memory); 19987ec681f3Smrg 19997ec681f3Smrg assert(pGetFdInfo->sType == VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR); 20007ec681f3Smrg assert(pGetFdInfo->handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT); 20017ec681f3Smrg 20027ec681f3Smrg *pFD = dup(memory->backed_fd); 20037ec681f3Smrg assert(*pFD >= 0); 20047ec681f3Smrg return VK_SUCCESS; 20057ec681f3Smrg} 20067ec681f3Smrg 20077ec681f3SmrgVkResult 20087ec681f3Smrglvp_GetMemoryFdPropertiesKHR(VkDevice _device, 20097ec681f3Smrg VkExternalMemoryHandleTypeFlagBits handleType, 20107ec681f3Smrg int fd, 20117ec681f3Smrg VkMemoryFdPropertiesKHR *pMemoryFdProperties) 20127ec681f3Smrg{ 20137ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 20147ec681f3Smrg 20157ec681f3Smrg assert(pMemoryFdProperties->sType == VK_STRUCTURE_TYPE_MEMORY_FD_PROPERTIES_KHR); 20167ec681f3Smrg 20177ec681f3Smrg if(handleType == VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT) { 20187ec681f3Smrg // There is only one memoryType so select this one 20197ec681f3Smrg pMemoryFdProperties->memoryTypeBits = 1; 20207ec681f3Smrg } 20217ec681f3Smrg else 20227ec681f3Smrg return vk_error(device->instance, VK_ERROR_INVALID_EXTERNAL_HANDLE); 20237ec681f3Smrg return VK_SUCCESS; 20247ec681f3Smrg} 20257ec681f3Smrg 20267ec681f3Smrg#endif 20277ec681f3Smrg 20287ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_QueueBindSparse( 20297ec681f3Smrg VkQueue queue, 20307ec681f3Smrg uint32_t bindInfoCount, 20317ec681f3Smrg const VkBindSparseInfo* pBindInfo, 20327ec681f3Smrg VkFence fence) 20337ec681f3Smrg{ 20347ec681f3Smrg stub_return(VK_ERROR_INCOMPATIBLE_DRIVER); 20357ec681f3Smrg} 20367ec681f3Smrg 20377ec681f3Smrg 20387ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_CreateFence( 20397ec681f3Smrg VkDevice _device, 20407ec681f3Smrg const VkFenceCreateInfo* pCreateInfo, 20417ec681f3Smrg const VkAllocationCallbacks* pAllocator, 20427ec681f3Smrg VkFence* pFence) 20437ec681f3Smrg{ 20447ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 20457ec681f3Smrg struct lvp_fence *fence; 20467ec681f3Smrg 20477ec681f3Smrg fence = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*fence), 8, 20487ec681f3Smrg VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 20497ec681f3Smrg if (fence == NULL) 20507ec681f3Smrg return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 20517ec681f3Smrg vk_object_base_init(&device->vk, &fence->base, VK_OBJECT_TYPE_FENCE); 20527ec681f3Smrg util_queue_fence_init(&fence->fence); 20537ec681f3Smrg fence->signalled = (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) == VK_FENCE_CREATE_SIGNALED_BIT; 20547ec681f3Smrg 20557ec681f3Smrg fence->handle = NULL; 20567ec681f3Smrg fence->timeline = 0; 20577ec681f3Smrg *pFence = lvp_fence_to_handle(fence); 20587ec681f3Smrg 20597ec681f3Smrg return VK_SUCCESS; 20607ec681f3Smrg} 20617ec681f3Smrg 20627ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_DestroyFence( 20637ec681f3Smrg VkDevice _device, 20647ec681f3Smrg VkFence _fence, 20657ec681f3Smrg const VkAllocationCallbacks* pAllocator) 20667ec681f3Smrg{ 20677ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 20687ec681f3Smrg LVP_FROM_HANDLE(lvp_fence, fence, _fence); 20697ec681f3Smrg 20707ec681f3Smrg if (!_fence) 20717ec681f3Smrg return; 20727ec681f3Smrg /* evade annoying destroy assert */ 20737ec681f3Smrg util_queue_fence_init(&fence->fence); 20747ec681f3Smrg util_queue_fence_destroy(&fence->fence); 20757ec681f3Smrg if (fence->handle) 20767ec681f3Smrg device->pscreen->fence_reference(device->pscreen, &fence->handle, NULL); 20777ec681f3Smrg 20787ec681f3Smrg vk_object_base_finish(&fence->base); 20797ec681f3Smrg vk_free2(&device->vk.alloc, pAllocator, fence); 20807ec681f3Smrg} 20817ec681f3Smrg 20827ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_ResetFences( 20837ec681f3Smrg VkDevice _device, 20847ec681f3Smrg uint32_t fenceCount, 20857ec681f3Smrg const VkFence* pFences) 20867ec681f3Smrg{ 20877ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 20887ec681f3Smrg for (unsigned i = 0; i < fenceCount; i++) { 20897ec681f3Smrg struct lvp_fence *fence = lvp_fence_from_handle(pFences[i]); 20907ec681f3Smrg /* ensure u_queue doesn't explode when submitting a completed lvp_fence 20917ec681f3Smrg * which has not yet signalled its u_queue fence 20927ec681f3Smrg */ 20937ec681f3Smrg util_queue_fence_wait(&fence->fence); 20947ec681f3Smrg 20957ec681f3Smrg if (fence->handle) { 20967ec681f3Smrg simple_mtx_lock(&device->queue.last_lock); 20977ec681f3Smrg if (fence->handle == device->queue.last_fence) 20987ec681f3Smrg device->pscreen->fence_reference(device->pscreen, &device->queue.last_fence, NULL); 20997ec681f3Smrg simple_mtx_unlock(&device->queue.last_lock); 21007ec681f3Smrg device->pscreen->fence_reference(device->pscreen, &fence->handle, NULL); 21017ec681f3Smrg } 21027ec681f3Smrg fence->signalled = false; 21037ec681f3Smrg } 21047ec681f3Smrg return VK_SUCCESS; 21057ec681f3Smrg} 21067ec681f3Smrg 21077ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_GetFenceStatus( 21087ec681f3Smrg VkDevice _device, 21097ec681f3Smrg VkFence _fence) 21107ec681f3Smrg{ 21117ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 21127ec681f3Smrg LVP_FROM_HANDLE(lvp_fence, fence, _fence); 21137ec681f3Smrg 21147ec681f3Smrg if (fence->signalled) 21157ec681f3Smrg return VK_SUCCESS; 21167ec681f3Smrg 21177ec681f3Smrg if (!util_queue_fence_is_signalled(&fence->fence) || 21187ec681f3Smrg !fence->handle || 21197ec681f3Smrg !device->pscreen->fence_finish(device->pscreen, NULL, fence->handle, 0)) 21207ec681f3Smrg return VK_NOT_READY; 21217ec681f3Smrg 21227ec681f3Smrg fence->signalled = true; 21237ec681f3Smrg simple_mtx_lock(&device->queue.last_lock); 21247ec681f3Smrg if (fence->handle == device->queue.last_fence) { 21257ec681f3Smrg device->pscreen->fence_reference(device->pscreen, &device->queue.last_fence, NULL); 21267ec681f3Smrg device->queue.last_finished = fence->timeline; 21277ec681f3Smrg } 21287ec681f3Smrg simple_mtx_unlock(&device->queue.last_lock); 21297ec681f3Smrg return VK_SUCCESS; 21307ec681f3Smrg} 21317ec681f3Smrg 21327ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_CreateFramebuffer( 21337ec681f3Smrg VkDevice _device, 21347ec681f3Smrg const VkFramebufferCreateInfo* pCreateInfo, 21357ec681f3Smrg const VkAllocationCallbacks* pAllocator, 21367ec681f3Smrg VkFramebuffer* pFramebuffer) 21377ec681f3Smrg{ 21387ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 21397ec681f3Smrg struct lvp_framebuffer *framebuffer; 21407ec681f3Smrg const VkFramebufferAttachmentsCreateInfo *imageless_create_info = 21417ec681f3Smrg vk_find_struct_const(pCreateInfo->pNext, 21427ec681f3Smrg FRAMEBUFFER_ATTACHMENTS_CREATE_INFO); 21437ec681f3Smrg 21447ec681f3Smrg assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO); 21457ec681f3Smrg 21467ec681f3Smrg size_t size = sizeof(*framebuffer); 21477ec681f3Smrg 21487ec681f3Smrg if (!imageless_create_info) 21497ec681f3Smrg size += sizeof(struct lvp_image_view *) * pCreateInfo->attachmentCount; 21507ec681f3Smrg framebuffer = vk_alloc2(&device->vk.alloc, pAllocator, size, 8, 21517ec681f3Smrg VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 21527ec681f3Smrg if (framebuffer == NULL) 21537ec681f3Smrg return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 21547ec681f3Smrg 21557ec681f3Smrg vk_object_base_init(&device->vk, &framebuffer->base, 21567ec681f3Smrg VK_OBJECT_TYPE_FRAMEBUFFER); 21577ec681f3Smrg 21587ec681f3Smrg if (!imageless_create_info) { 21597ec681f3Smrg framebuffer->attachment_count = pCreateInfo->attachmentCount; 21607ec681f3Smrg for (uint32_t i = 0; i < pCreateInfo->attachmentCount; i++) { 21617ec681f3Smrg VkImageView _iview = pCreateInfo->pAttachments[i]; 21627ec681f3Smrg framebuffer->attachments[i] = lvp_image_view_from_handle(_iview); 21637ec681f3Smrg } 21647ec681f3Smrg } 21657ec681f3Smrg 21667ec681f3Smrg framebuffer->width = pCreateInfo->width; 21677ec681f3Smrg framebuffer->height = pCreateInfo->height; 21687ec681f3Smrg framebuffer->layers = pCreateInfo->layers; 21697ec681f3Smrg framebuffer->imageless = !!imageless_create_info; 21707ec681f3Smrg 21717ec681f3Smrg *pFramebuffer = lvp_framebuffer_to_handle(framebuffer); 21727ec681f3Smrg 21737ec681f3Smrg return VK_SUCCESS; 21747ec681f3Smrg} 21757ec681f3Smrg 21767ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_DestroyFramebuffer( 21777ec681f3Smrg VkDevice _device, 21787ec681f3Smrg VkFramebuffer _fb, 21797ec681f3Smrg const VkAllocationCallbacks* pAllocator) 21807ec681f3Smrg{ 21817ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 21827ec681f3Smrg LVP_FROM_HANDLE(lvp_framebuffer, fb, _fb); 21837ec681f3Smrg 21847ec681f3Smrg if (!fb) 21857ec681f3Smrg return; 21867ec681f3Smrg vk_object_base_finish(&fb->base); 21877ec681f3Smrg vk_free2(&device->vk.alloc, pAllocator, fb); 21887ec681f3Smrg} 21897ec681f3Smrg 21907ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_WaitForFences( 21917ec681f3Smrg VkDevice _device, 21927ec681f3Smrg uint32_t fenceCount, 21937ec681f3Smrg const VkFence* pFences, 21947ec681f3Smrg VkBool32 waitAll, 21957ec681f3Smrg uint64_t timeout) 21967ec681f3Smrg{ 21977ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 21987ec681f3Smrg struct lvp_fence *fence = NULL; 21997ec681f3Smrg 22007ec681f3Smrg /* lavapipe is completely synchronous, so only one fence needs to be waited on */ 22017ec681f3Smrg if (waitAll) { 22027ec681f3Smrg /* find highest timeline id */ 22037ec681f3Smrg for (unsigned i = 0; i < fenceCount; i++) { 22047ec681f3Smrg struct lvp_fence *f = lvp_fence_from_handle(pFences[i]); 22057ec681f3Smrg 22067ec681f3Smrg /* this is an unsubmitted fence: immediately bail out */ 22077ec681f3Smrg if (!f->timeline && !f->signalled) 22087ec681f3Smrg return VK_TIMEOUT; 22097ec681f3Smrg if (!fence || f->timeline > fence->timeline) 22107ec681f3Smrg fence = f; 22117ec681f3Smrg } 22127ec681f3Smrg } else { 22137ec681f3Smrg /* find lowest timeline id */ 22147ec681f3Smrg for (unsigned i = 0; i < fenceCount; i++) { 22157ec681f3Smrg struct lvp_fence *f = lvp_fence_from_handle(pFences[i]); 22167ec681f3Smrg if (f->signalled) 22177ec681f3Smrg return VK_SUCCESS; 22187ec681f3Smrg if (f->timeline && (!fence || f->timeline < fence->timeline)) 22197ec681f3Smrg fence = f; 22207ec681f3Smrg } 22217ec681f3Smrg } 22227ec681f3Smrg if (!fence) 22237ec681f3Smrg return VK_TIMEOUT; 22247ec681f3Smrg if (fence->signalled) 22257ec681f3Smrg return VK_SUCCESS; 22267ec681f3Smrg 22277ec681f3Smrg if (!util_queue_fence_is_signalled(&fence->fence)) { 22287ec681f3Smrg int64_t abs_timeout = os_time_get_absolute_timeout(timeout); 22297ec681f3Smrg if (!util_queue_fence_wait_timeout(&fence->fence, abs_timeout)) 22307ec681f3Smrg return VK_TIMEOUT; 22317ec681f3Smrg 22327ec681f3Smrg int64_t time_ns = os_time_get_nano(); 22337ec681f3Smrg timeout = abs_timeout > time_ns ? abs_timeout - time_ns : 0; 22347ec681f3Smrg } 22357ec681f3Smrg 22367ec681f3Smrg if (!fence->handle || 22377ec681f3Smrg !device->pscreen->fence_finish(device->pscreen, NULL, fence->handle, timeout)) 22387ec681f3Smrg return VK_TIMEOUT; 22397ec681f3Smrg simple_mtx_lock(&device->queue.last_lock); 22407ec681f3Smrg if (fence->handle == device->queue.last_fence) { 22417ec681f3Smrg device->pscreen->fence_reference(device->pscreen, &device->queue.last_fence, NULL); 22427ec681f3Smrg device->queue.last_finished = fence->timeline; 22437ec681f3Smrg } 22447ec681f3Smrg simple_mtx_unlock(&device->queue.last_lock); 22457ec681f3Smrg fence->signalled = true; 22467ec681f3Smrg return VK_SUCCESS; 22477ec681f3Smrg} 22487ec681f3Smrg 22497ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_CreateSemaphore( 22507ec681f3Smrg VkDevice _device, 22517ec681f3Smrg const VkSemaphoreCreateInfo* pCreateInfo, 22527ec681f3Smrg const VkAllocationCallbacks* pAllocator, 22537ec681f3Smrg VkSemaphore* pSemaphore) 22547ec681f3Smrg{ 22557ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 22567ec681f3Smrg 22577ec681f3Smrg struct lvp_semaphore *sema = vk_alloc2(&device->vk.alloc, pAllocator, 22587ec681f3Smrg sizeof(*sema), 8, 22597ec681f3Smrg VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 22607ec681f3Smrg 22617ec681f3Smrg if (!sema) 22627ec681f3Smrg return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 22637ec681f3Smrg vk_object_base_init(&device->vk, &sema->base, 22647ec681f3Smrg VK_OBJECT_TYPE_SEMAPHORE); 22657ec681f3Smrg 22667ec681f3Smrg const VkSemaphoreTypeCreateInfo *info = vk_find_struct_const(pCreateInfo->pNext, SEMAPHORE_TYPE_CREATE_INFO); 22677ec681f3Smrg sema->is_timeline = info && info->semaphoreType == VK_SEMAPHORE_TYPE_TIMELINE; 22687ec681f3Smrg if (sema->is_timeline) { 22697ec681f3Smrg sema->is_timeline = true; 22707ec681f3Smrg sema->timeline = NULL; 22717ec681f3Smrg sema->current = info->initialValue; 22727ec681f3Smrg sema->mem = ralloc_context(NULL); 22737ec681f3Smrg util_dynarray_init(&sema->links, sema->mem); 22747ec681f3Smrg simple_mtx_init(&sema->lock, mtx_plain); 22757ec681f3Smrg mtx_init(&sema->submit_lock, mtx_plain); 22767ec681f3Smrg cnd_init(&sema->submit); 22777ec681f3Smrg } 22787ec681f3Smrg 22797ec681f3Smrg *pSemaphore = lvp_semaphore_to_handle(sema); 22807ec681f3Smrg 22817ec681f3Smrg return VK_SUCCESS; 22827ec681f3Smrg} 22837ec681f3Smrg 22847ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_DestroySemaphore( 22857ec681f3Smrg VkDevice _device, 22867ec681f3Smrg VkSemaphore _semaphore, 22877ec681f3Smrg const VkAllocationCallbacks* pAllocator) 22887ec681f3Smrg{ 22897ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 22907ec681f3Smrg LVP_FROM_HANDLE(lvp_semaphore, sema, _semaphore); 22917ec681f3Smrg 22927ec681f3Smrg if (!_semaphore) 22937ec681f3Smrg return; 22947ec681f3Smrg if (sema->is_timeline) { 22957ec681f3Smrg ralloc_free(sema->mem); 22967ec681f3Smrg simple_mtx_destroy(&sema->lock); 22977ec681f3Smrg mtx_destroy(&sema->submit_lock); 22987ec681f3Smrg cnd_destroy(&sema->submit); 22997ec681f3Smrg } 23007ec681f3Smrg vk_object_base_finish(&sema->base); 23017ec681f3Smrg vk_free2(&device->vk.alloc, pAllocator, sema); 23027ec681f3Smrg} 23037ec681f3Smrg 23047ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_WaitSemaphores( 23057ec681f3Smrg VkDevice _device, 23067ec681f3Smrg const VkSemaphoreWaitInfo* pWaitInfo, 23077ec681f3Smrg uint64_t timeout) 23087ec681f3Smrg{ 23097ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 23107ec681f3Smrg /* same mechanism as used by queue submit */ 23117ec681f3Smrg return wait_semaphores(device, pWaitInfo, timeout); 23127ec681f3Smrg} 23137ec681f3Smrg 23147ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_GetSemaphoreCounterValue( 23157ec681f3Smrg VkDevice _device, 23167ec681f3Smrg VkSemaphore _semaphore, 23177ec681f3Smrg uint64_t* pValue) 23187ec681f3Smrg{ 23197ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 23207ec681f3Smrg LVP_FROM_HANDLE(lvp_semaphore, sema, _semaphore); 23217ec681f3Smrg simple_mtx_lock(&sema->lock); 23227ec681f3Smrg prune_semaphore_links(device, sema, device->queue.last_finished); 23237ec681f3Smrg *pValue = sema->current; 23247ec681f3Smrg simple_mtx_unlock(&sema->lock); 23257ec681f3Smrg return VK_SUCCESS; 23267ec681f3Smrg} 23277ec681f3Smrg 23287ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_SignalSemaphore( 23297ec681f3Smrg VkDevice _device, 23307ec681f3Smrg const VkSemaphoreSignalInfo* pSignalInfo) 23317ec681f3Smrg{ 23327ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 23337ec681f3Smrg LVP_FROM_HANDLE(lvp_semaphore, sema, pSignalInfo->semaphore); 23347ec681f3Smrg 23357ec681f3Smrg /* try to remain monotonic */ 23367ec681f3Smrg if (sema->current < pSignalInfo->value) 23377ec681f3Smrg sema->current = pSignalInfo->value; 23387ec681f3Smrg cnd_broadcast(&sema->submit); 23397ec681f3Smrg simple_mtx_lock(&sema->lock); 23407ec681f3Smrg prune_semaphore_links(device, sema, device->queue.last_finished); 23417ec681f3Smrg simple_mtx_unlock(&sema->lock); 23427ec681f3Smrg return VK_SUCCESS; 23437ec681f3Smrg} 23447ec681f3Smrg 23457ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_CreateEvent( 23467ec681f3Smrg VkDevice _device, 23477ec681f3Smrg const VkEventCreateInfo* pCreateInfo, 23487ec681f3Smrg const VkAllocationCallbacks* pAllocator, 23497ec681f3Smrg VkEvent* pEvent) 23507ec681f3Smrg{ 23517ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 23527ec681f3Smrg struct lvp_event *event = vk_alloc2(&device->vk.alloc, pAllocator, 23537ec681f3Smrg sizeof(*event), 8, 23547ec681f3Smrg VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 23557ec681f3Smrg 23567ec681f3Smrg if (!event) 23577ec681f3Smrg return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 23587ec681f3Smrg 23597ec681f3Smrg vk_object_base_init(&device->vk, &event->base, VK_OBJECT_TYPE_EVENT); 23607ec681f3Smrg *pEvent = lvp_event_to_handle(event); 23617ec681f3Smrg event->event_storage = 0; 23627ec681f3Smrg 23637ec681f3Smrg return VK_SUCCESS; 23647ec681f3Smrg} 23657ec681f3Smrg 23667ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_DestroyEvent( 23677ec681f3Smrg VkDevice _device, 23687ec681f3Smrg VkEvent _event, 23697ec681f3Smrg const VkAllocationCallbacks* pAllocator) 23707ec681f3Smrg{ 23717ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 23727ec681f3Smrg LVP_FROM_HANDLE(lvp_event, event, _event); 23737ec681f3Smrg 23747ec681f3Smrg if (!event) 23757ec681f3Smrg return; 23767ec681f3Smrg 23777ec681f3Smrg vk_object_base_finish(&event->base); 23787ec681f3Smrg vk_free2(&device->vk.alloc, pAllocator, event); 23797ec681f3Smrg} 23807ec681f3Smrg 23817ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_GetEventStatus( 23827ec681f3Smrg VkDevice _device, 23837ec681f3Smrg VkEvent _event) 23847ec681f3Smrg{ 23857ec681f3Smrg LVP_FROM_HANDLE(lvp_event, event, _event); 23867ec681f3Smrg if (event->event_storage == 1) 23877ec681f3Smrg return VK_EVENT_SET; 23887ec681f3Smrg return VK_EVENT_RESET; 23897ec681f3Smrg} 23907ec681f3Smrg 23917ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_SetEvent( 23927ec681f3Smrg VkDevice _device, 23937ec681f3Smrg VkEvent _event) 23947ec681f3Smrg{ 23957ec681f3Smrg LVP_FROM_HANDLE(lvp_event, event, _event); 23967ec681f3Smrg event->event_storage = 1; 23977ec681f3Smrg 23987ec681f3Smrg return VK_SUCCESS; 23997ec681f3Smrg} 24007ec681f3Smrg 24017ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_ResetEvent( 24027ec681f3Smrg VkDevice _device, 24037ec681f3Smrg VkEvent _event) 24047ec681f3Smrg{ 24057ec681f3Smrg LVP_FROM_HANDLE(lvp_event, event, _event); 24067ec681f3Smrg event->event_storage = 0; 24077ec681f3Smrg 24087ec681f3Smrg return VK_SUCCESS; 24097ec681f3Smrg} 24107ec681f3Smrg 24117ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_CreateSampler( 24127ec681f3Smrg VkDevice _device, 24137ec681f3Smrg const VkSamplerCreateInfo* pCreateInfo, 24147ec681f3Smrg const VkAllocationCallbacks* pAllocator, 24157ec681f3Smrg VkSampler* pSampler) 24167ec681f3Smrg{ 24177ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 24187ec681f3Smrg struct lvp_sampler *sampler; 24197ec681f3Smrg const VkSamplerReductionModeCreateInfo *reduction_mode_create_info = 24207ec681f3Smrg vk_find_struct_const(pCreateInfo->pNext, 24217ec681f3Smrg SAMPLER_REDUCTION_MODE_CREATE_INFO); 24227ec681f3Smrg const VkSamplerCustomBorderColorCreateInfoEXT *custom_border_color_create_info = 24237ec681f3Smrg vk_find_struct_const(pCreateInfo->pNext, 24247ec681f3Smrg SAMPLER_CUSTOM_BORDER_COLOR_CREATE_INFO_EXT); 24257ec681f3Smrg 24267ec681f3Smrg assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO); 24277ec681f3Smrg 24287ec681f3Smrg sampler = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*sampler), 8, 24297ec681f3Smrg VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 24307ec681f3Smrg if (!sampler) 24317ec681f3Smrg return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 24327ec681f3Smrg 24337ec681f3Smrg vk_object_base_init(&device->vk, &sampler->base, 24347ec681f3Smrg VK_OBJECT_TYPE_SAMPLER); 24357ec681f3Smrg sampler->create_info = *pCreateInfo; 24367ec681f3Smrg 24377ec681f3Smrg switch (pCreateInfo->borderColor) { 24387ec681f3Smrg case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK: 24397ec681f3Smrg case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK: 24407ec681f3Smrg default: 24417ec681f3Smrg memset(&sampler->border_color, 0, sizeof(union pipe_color_union)); 24427ec681f3Smrg break; 24437ec681f3Smrg case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK: 24447ec681f3Smrg sampler->border_color.f[0] = sampler->border_color.f[1] = 24457ec681f3Smrg sampler->border_color.f[2] = 0.0f; 24467ec681f3Smrg sampler->border_color.f[3] = 1.0f; 24477ec681f3Smrg break; 24487ec681f3Smrg case VK_BORDER_COLOR_INT_OPAQUE_BLACK: 24497ec681f3Smrg sampler->border_color.i[0] = sampler->border_color.i[1] = 24507ec681f3Smrg sampler->border_color.i[2] = 0; 24517ec681f3Smrg sampler->border_color.i[3] = 1; 24527ec681f3Smrg break; 24537ec681f3Smrg case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE: 24547ec681f3Smrg sampler->border_color.f[0] = sampler->border_color.f[1] = 24557ec681f3Smrg sampler->border_color.f[2] = 1.0f; 24567ec681f3Smrg sampler->border_color.f[3] = 1.0f; 24577ec681f3Smrg break; 24587ec681f3Smrg case VK_BORDER_COLOR_INT_OPAQUE_WHITE: 24597ec681f3Smrg sampler->border_color.i[0] = sampler->border_color.i[1] = 24607ec681f3Smrg sampler->border_color.i[2] = 1; 24617ec681f3Smrg sampler->border_color.i[3] = 1; 24627ec681f3Smrg break; 24637ec681f3Smrg case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT: 24647ec681f3Smrg case VK_BORDER_COLOR_INT_CUSTOM_EXT: 24657ec681f3Smrg assert(custom_border_color_create_info != NULL); 24667ec681f3Smrg memcpy(&sampler->border_color, 24677ec681f3Smrg &custom_border_color_create_info->customBorderColor, 24687ec681f3Smrg sizeof(union pipe_color_union)); 24697ec681f3Smrg break; 24707ec681f3Smrg } 24717ec681f3Smrg 24727ec681f3Smrg sampler->reduction_mode = VK_SAMPLER_REDUCTION_MODE_WEIGHTED_AVERAGE; 24737ec681f3Smrg if (reduction_mode_create_info) 24747ec681f3Smrg sampler->reduction_mode = reduction_mode_create_info->reductionMode; 24757ec681f3Smrg 24767ec681f3Smrg *pSampler = lvp_sampler_to_handle(sampler); 24777ec681f3Smrg 24787ec681f3Smrg return VK_SUCCESS; 24797ec681f3Smrg} 24807ec681f3Smrg 24817ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_DestroySampler( 24827ec681f3Smrg VkDevice _device, 24837ec681f3Smrg VkSampler _sampler, 24847ec681f3Smrg const VkAllocationCallbacks* pAllocator) 24857ec681f3Smrg{ 24867ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 24877ec681f3Smrg LVP_FROM_HANDLE(lvp_sampler, sampler, _sampler); 24887ec681f3Smrg 24897ec681f3Smrg if (!_sampler) 24907ec681f3Smrg return; 24917ec681f3Smrg vk_object_base_finish(&sampler->base); 24927ec681f3Smrg vk_free2(&device->vk.alloc, pAllocator, sampler); 24937ec681f3Smrg} 24947ec681f3Smrg 24957ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_CreateSamplerYcbcrConversionKHR( 24967ec681f3Smrg VkDevice device, 24977ec681f3Smrg const VkSamplerYcbcrConversionCreateInfo* pCreateInfo, 24987ec681f3Smrg const VkAllocationCallbacks* pAllocator, 24997ec681f3Smrg VkSamplerYcbcrConversion* pYcbcrConversion) 25007ec681f3Smrg{ 25017ec681f3Smrg return VK_ERROR_OUT_OF_HOST_MEMORY; 25027ec681f3Smrg} 25037ec681f3Smrg 25047ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_DestroySamplerYcbcrConversionKHR( 25057ec681f3Smrg VkDevice device, 25067ec681f3Smrg VkSamplerYcbcrConversion ycbcrConversion, 25077ec681f3Smrg const VkAllocationCallbacks* pAllocator) 25087ec681f3Smrg{ 25097ec681f3Smrg} 25107ec681f3Smrg 25117ec681f3Smrg/* vk_icd.h does not declare this function, so we declare it here to 25127ec681f3Smrg * suppress Wmissing-prototypes. 25137ec681f3Smrg */ 25147ec681f3SmrgPUBLIC VKAPI_ATTR VkResult VKAPI_CALL 25157ec681f3Smrgvk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion); 25167ec681f3Smrg 25177ec681f3SmrgPUBLIC VKAPI_ATTR VkResult VKAPI_CALL 25187ec681f3Smrgvk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) 25197ec681f3Smrg{ 25207ec681f3Smrg /* For the full details on loader interface versioning, see 25217ec681f3Smrg * <https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/blob/master/loader/LoaderAndLayerInterface.md>. 25227ec681f3Smrg * What follows is a condensed summary, to help you navigate the large and 25237ec681f3Smrg * confusing official doc. 25247ec681f3Smrg * 25257ec681f3Smrg * - Loader interface v0 is incompatible with later versions. We don't 25267ec681f3Smrg * support it. 25277ec681f3Smrg * 25287ec681f3Smrg * - In loader interface v1: 25297ec681f3Smrg * - The first ICD entrypoint called by the loader is 25307ec681f3Smrg * vk_icdGetInstanceProcAddr(). The ICD must statically expose this 25317ec681f3Smrg * entrypoint. 25327ec681f3Smrg * - The ICD must statically expose no other Vulkan symbol unless it is 25337ec681f3Smrg * linked with -Bsymbolic. 25347ec681f3Smrg * - Each dispatchable Vulkan handle created by the ICD must be 25357ec681f3Smrg * a pointer to a struct whose first member is VK_LOADER_DATA. The 25367ec681f3Smrg * ICD must initialize VK_LOADER_DATA.loadMagic to ICD_LOADER_MAGIC. 25377ec681f3Smrg * - The loader implements vkCreate{PLATFORM}SurfaceKHR() and 25387ec681f3Smrg * vkDestroySurfaceKHR(). The ICD must be capable of working with 25397ec681f3Smrg * such loader-managed surfaces. 25407ec681f3Smrg * 25417ec681f3Smrg * - Loader interface v2 differs from v1 in: 25427ec681f3Smrg * - The first ICD entrypoint called by the loader is 25437ec681f3Smrg * vk_icdNegotiateLoaderICDInterfaceVersion(). The ICD must 25447ec681f3Smrg * statically expose this entrypoint. 25457ec681f3Smrg * 25467ec681f3Smrg * - Loader interface v3 differs from v2 in: 25477ec681f3Smrg * - The ICD must implement vkCreate{PLATFORM}SurfaceKHR(), 25487ec681f3Smrg * vkDestroySurfaceKHR(), and other API which uses VKSurfaceKHR, 25497ec681f3Smrg * because the loader no longer does so. 25507ec681f3Smrg * 25517ec681f3Smrg * - Loader interface v4 differs from v3 in: 25527ec681f3Smrg * - The ICD must implement vk_icdGetPhysicalDeviceProcAddr(). 25537ec681f3Smrg */ 25547ec681f3Smrg *pSupportedVersion = MIN2(*pSupportedVersion, 4u); 25557ec681f3Smrg return VK_SUCCESS; 25567ec681f3Smrg} 25577ec681f3Smrg 25587ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_CreatePrivateDataSlotEXT( 25597ec681f3Smrg VkDevice _device, 25607ec681f3Smrg const VkPrivateDataSlotCreateInfoEXT* pCreateInfo, 25617ec681f3Smrg const VkAllocationCallbacks* pAllocator, 25627ec681f3Smrg VkPrivateDataSlotEXT* pPrivateDataSlot) 25637ec681f3Smrg{ 25647ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 25657ec681f3Smrg return vk_private_data_slot_create(&device->vk, pCreateInfo, pAllocator, 25667ec681f3Smrg pPrivateDataSlot); 25677ec681f3Smrg} 25687ec681f3Smrg 25697ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_DestroyPrivateDataSlotEXT( 25707ec681f3Smrg VkDevice _device, 25717ec681f3Smrg VkPrivateDataSlotEXT privateDataSlot, 25727ec681f3Smrg const VkAllocationCallbacks* pAllocator) 25737ec681f3Smrg{ 25747ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 25757ec681f3Smrg vk_private_data_slot_destroy(&device->vk, privateDataSlot, pAllocator); 25767ec681f3Smrg} 25777ec681f3Smrg 25787ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_SetPrivateDataEXT( 25797ec681f3Smrg VkDevice _device, 25807ec681f3Smrg VkObjectType objectType, 25817ec681f3Smrg uint64_t objectHandle, 25827ec681f3Smrg VkPrivateDataSlotEXT privateDataSlot, 25837ec681f3Smrg uint64_t data) 25847ec681f3Smrg{ 25857ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 25867ec681f3Smrg return vk_object_base_set_private_data(&device->vk, objectType, 25877ec681f3Smrg objectHandle, privateDataSlot, 25887ec681f3Smrg data); 25897ec681f3Smrg} 25907ec681f3Smrg 25917ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetPrivateDataEXT( 25927ec681f3Smrg VkDevice _device, 25937ec681f3Smrg VkObjectType objectType, 25947ec681f3Smrg uint64_t objectHandle, 25957ec681f3Smrg VkPrivateDataSlotEXT privateDataSlot, 25967ec681f3Smrg uint64_t* pData) 25977ec681f3Smrg{ 25987ec681f3Smrg LVP_FROM_HANDLE(lvp_device, device, _device); 25997ec681f3Smrg vk_object_base_get_private_data(&device->vk, objectType, objectHandle, 26007ec681f3Smrg privateDataSlot, pData); 26017ec681f3Smrg} 26027ec681f3Smrg 26037ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceExternalFenceProperties( 26047ec681f3Smrg VkPhysicalDevice physicalDevice, 26057ec681f3Smrg const VkPhysicalDeviceExternalFenceInfo *pExternalFenceInfo, 26067ec681f3Smrg VkExternalFenceProperties *pExternalFenceProperties) 26077ec681f3Smrg{ 26087ec681f3Smrg pExternalFenceProperties->exportFromImportedHandleTypes = 0; 26097ec681f3Smrg pExternalFenceProperties->compatibleHandleTypes = 0; 26107ec681f3Smrg pExternalFenceProperties->externalFenceFeatures = 0; 26117ec681f3Smrg} 26127ec681f3Smrg 26137ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceExternalSemaphoreProperties( 26147ec681f3Smrg VkPhysicalDevice physicalDevice, 26157ec681f3Smrg const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, 26167ec681f3Smrg VkExternalSemaphoreProperties *pExternalSemaphoreProperties) 26177ec681f3Smrg{ 26187ec681f3Smrg pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0; 26197ec681f3Smrg pExternalSemaphoreProperties->compatibleHandleTypes = 0; 26207ec681f3Smrg pExternalSemaphoreProperties->externalSemaphoreFeatures = 0; 26217ec681f3Smrg} 26227ec681f3Smrg 26237ec681f3Smrgstatic const VkTimeDomainEXT lvp_time_domains[] = { 26247ec681f3Smrg VK_TIME_DOMAIN_DEVICE_EXT, 26257ec681f3Smrg VK_TIME_DOMAIN_CLOCK_MONOTONIC_EXT, 26267ec681f3Smrg}; 26277ec681f3Smrg 26287ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_GetPhysicalDeviceCalibrateableTimeDomainsEXT( 26297ec681f3Smrg VkPhysicalDevice physicalDevice, 26307ec681f3Smrg uint32_t *pTimeDomainCount, 26317ec681f3Smrg VkTimeDomainEXT *pTimeDomains) 26327ec681f3Smrg{ 26337ec681f3Smrg int d; 26347ec681f3Smrg VK_OUTARRAY_MAKE_TYPED(VkTimeDomainEXT, out, pTimeDomains, 26357ec681f3Smrg pTimeDomainCount); 26367ec681f3Smrg 26377ec681f3Smrg for (d = 0; d < ARRAY_SIZE(lvp_time_domains); d++) { 26387ec681f3Smrg vk_outarray_append_typed(VkTimeDomainEXT, &out, i) { 26397ec681f3Smrg *i = lvp_time_domains[d]; 26407ec681f3Smrg } 26417ec681f3Smrg } 26427ec681f3Smrg 26437ec681f3Smrg return vk_outarray_status(&out); 26447ec681f3Smrg} 26457ec681f3Smrg 26467ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL lvp_GetCalibratedTimestampsEXT( 26477ec681f3Smrg VkDevice device, 26487ec681f3Smrg uint32_t timestampCount, 26497ec681f3Smrg const VkCalibratedTimestampInfoEXT *pTimestampInfos, 26507ec681f3Smrg uint64_t *pTimestamps, 26517ec681f3Smrg uint64_t *pMaxDeviation) 26527ec681f3Smrg{ 26537ec681f3Smrg *pMaxDeviation = 1; 26547ec681f3Smrg 26557ec681f3Smrg uint64_t now = os_time_get_nano(); 26567ec681f3Smrg for (unsigned i = 0; i < timestampCount; i++) { 26577ec681f3Smrg pTimestamps[i] = now; 26587ec681f3Smrg } 26597ec681f3Smrg return VK_SUCCESS; 26607ec681f3Smrg} 26617ec681f3Smrg 26627ec681f3SmrgVKAPI_ATTR void VKAPI_CALL lvp_GetDeviceGroupPeerMemoryFeaturesKHR( 26637ec681f3Smrg VkDevice device, 26647ec681f3Smrg uint32_t heapIndex, 26657ec681f3Smrg uint32_t localDeviceIndex, 26667ec681f3Smrg uint32_t remoteDeviceIndex, 26677ec681f3Smrg VkPeerMemoryFeatureFlags *pPeerMemoryFeatures) 26687ec681f3Smrg{ 26697ec681f3Smrg *pPeerMemoryFeatures = 0; 26707ec681f3Smrg} 2671