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