? Loading fortune...
lib/mesa/0001-static-lavapipe.patch
$ cat 0001-static-lavapipe.patch
diff --git a/meson.build b/meson.build
index 5eaae977f67..5ec25c87921 100644
--- a/meson.build
+++ b/meson.build
@@ -2104,21 +2104,11 @@ if build_machine.system() == 'windows'
     prog_bison = find_program('bison', 'yacc', required : needs_flex_bison, disabler : true)
   endif
 else
-  prog_bison = find_program('bison', required : false)
+  # fuck gnu!!!!
+  prog_bison = find_program('byacc', required : needs_flex_bison, disabler : true)
+  yacc_is_bison = false
 
-  if not prog_bison.found()
-    prog_bison = find_program('byacc', required : needs_flex_bison, disabler : true)
-    yacc_is_bison = false
-  endif
-
-  # Disable deprecated keyword warnings, since we have to use them for
-  # old-bison compat.  See discussion in
-  # https://gitlab.freedesktop.org/mesa/mesa/merge_requests/2161
-  if find_program('bison', required : false, version : '> 2.3').found()
-    prog_bison = [prog_bison, '-Wno-deprecated']
-  endif
-
-  prog_flex = find_program('flex', required : needs_flex_bison, disabler : true)
+  prog_flex = find_program('reflex', required : needs_flex_bison, disabler : true)
   prog_flex_cpp = prog_flex
 endif
 
diff --git a/src/gallium/frontends/lavapipe/lvp_device.c b/src/gallium/frontends/lavapipe/lvp_device.c
index 187f17ccf1b..96450dc7be2 100644
--- a/src/gallium/frontends/lavapipe/lvp_device.c
+++ b/src/gallium/frontends/lavapipe/lvp_device.c
@@ -27,6 +27,7 @@
 
 #include "pipe-loader/pipe_loader.h"
 #include "git_sha1.h"
+#include "vk_common_entrypoints.h"
 #include "vk_cmd_enqueue_entrypoints.h"
 #include "vk_sampler.h"
 #include "vk_util.h"
@@ -1421,11 +1422,56 @@ lvp_physical_device_init(struct lvp_physical_device *device,
 {
    VkResult result;
 
-   struct vk_physical_device_dispatch_table dispatch_table;
+   struct vk_physical_device_dispatch_table dispatch_table = {0};
    vk_physical_device_dispatch_table_from_entrypoints(
       &dispatch_table, &lvp_physical_device_entrypoints, true);
    vk_physical_device_dispatch_table_from_entrypoints(
       &dispatch_table, &wsi_physical_device_entrypoints, false);
+   dispatch_table.GetPhysicalDeviceFeatures2 = vk_common_GetPhysicalDeviceFeatures2;
+   dispatch_table.GetPhysicalDeviceFeatures2KHR =
+      (PFN_vkGetPhysicalDeviceFeatures2KHR)vk_common_GetPhysicalDeviceFeatures2;
+   dispatch_table.GetPhysicalDeviceProperties2 = lvp_GetPhysicalDeviceProperties2;
+   dispatch_table.GetPhysicalDeviceProperties2KHR = lvp_GetPhysicalDeviceProperties2;
+   dispatch_table.GetPhysicalDeviceFormatProperties2 =
+      lvp_GetPhysicalDeviceFormatProperties2;
+   dispatch_table.GetPhysicalDeviceFormatProperties2KHR =
+      (PFN_vkGetPhysicalDeviceFormatProperties2KHR)
+      lvp_GetPhysicalDeviceFormatProperties2;
+   dispatch_table.GetPhysicalDeviceImageFormatProperties2 =
+      lvp_GetPhysicalDeviceImageFormatProperties2;
+   dispatch_table.GetPhysicalDeviceImageFormatProperties2KHR =
+      (PFN_vkGetPhysicalDeviceImageFormatProperties2KHR)
+      lvp_GetPhysicalDeviceImageFormatProperties2;
+   dispatch_table.GetPhysicalDeviceQueueFamilyProperties2 =
+      lvp_GetPhysicalDeviceQueueFamilyProperties2;
+   dispatch_table.GetPhysicalDeviceQueueFamilyProperties2KHR =
+      (PFN_vkGetPhysicalDeviceQueueFamilyProperties2KHR)
+      lvp_GetPhysicalDeviceQueueFamilyProperties2;
+   dispatch_table.GetPhysicalDeviceMemoryProperties2 =
+      lvp_GetPhysicalDeviceMemoryProperties2;
+   dispatch_table.GetPhysicalDeviceMemoryProperties2KHR =
+      (PFN_vkGetPhysicalDeviceMemoryProperties2KHR)
+      lvp_GetPhysicalDeviceMemoryProperties2;
+   dispatch_table.GetPhysicalDeviceSparseImageFormatProperties2 =
+      lvp_GetPhysicalDeviceSparseImageFormatProperties2;
+   dispatch_table.GetPhysicalDeviceSparseImageFormatProperties2KHR =
+      (PFN_vkGetPhysicalDeviceSparseImageFormatProperties2KHR)
+      lvp_GetPhysicalDeviceSparseImageFormatProperties2;
+   dispatch_table.GetPhysicalDeviceExternalBufferProperties =
+      lvp_GetPhysicalDeviceExternalBufferProperties;
+   dispatch_table.GetPhysicalDeviceExternalBufferPropertiesKHR =
+      (PFN_vkGetPhysicalDeviceExternalBufferPropertiesKHR)
+      lvp_GetPhysicalDeviceExternalBufferProperties;
+   dispatch_table.GetPhysicalDeviceExternalFenceProperties =
+      lvp_GetPhysicalDeviceExternalFenceProperties;
+   dispatch_table.GetPhysicalDeviceExternalFencePropertiesKHR =
+      (PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR)
+      lvp_GetPhysicalDeviceExternalFenceProperties;
+   dispatch_table.GetPhysicalDeviceExternalSemaphoreProperties =
+      lvp_GetPhysicalDeviceExternalSemaphoreProperties;
+   dispatch_table.GetPhysicalDeviceExternalSemaphorePropertiesKHR =
+      (PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR)
+      lvp_GetPhysicalDeviceExternalSemaphoreProperties;
    result = vk_physical_device_init(&device->vk, &instance->vk,
                                     NULL, NULL, NULL, &dispatch_table);
    if (result != VK_SUCCESS) {
@@ -1642,6 +1688,13 @@ lvp_device_get_cache_uuid(void *uuid)
       memcpy(uuid, PACKAGE_VERSION, MIN2(strlen(PACKAGE_VERSION), VK_UUID_SIZE));
 }
 
+VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceProperties2(
+   VkPhysicalDevice                            physicalDevice,
+   VkPhysicalDeviceProperties2                *pProperties)
+{
+   vk_common_GetPhysicalDeviceProperties2(physicalDevice, pProperties);
+}
+
 VKAPI_ATTR void VKAPI_CALL lvp_GetPhysicalDeviceQueueFamilyProperties2(
    VkPhysicalDevice                            physicalDevice,
    uint32_t*                                   pCount,
@@ -1887,12 +1940,43 @@ VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDevice(
    device->poison_mem = debug_get_bool_option("LVP_POISON_MEMORY", false);
    device->print_cmds = debug_get_bool_option("LVP_CMD_DEBUG", false);
 
-   struct vk_device_dispatch_table dispatch_table;
+   struct vk_device_dispatch_table dispatch_table = {0};
    vk_device_dispatch_table_from_entrypoints(&dispatch_table,
       &lvp_device_entrypoints, true);
    lvp_add_enqueue_cmd_entrypoints(&dispatch_table);
    vk_device_dispatch_table_from_entrypoints(&dispatch_table,
       &wsi_device_entrypoints, false);
+   dispatch_table.CreateCommandPool = vk_common_CreateCommandPool;
+   dispatch_table.AllocateCommandBuffers = vk_common_AllocateCommandBuffers;
+   dispatch_table.CreateFence = vk_common_CreateFence;
+   dispatch_table.DestroyFence = vk_common_DestroyFence;
+   dispatch_table.ResetFences = vk_common_ResetFences;
+   dispatch_table.GetFenceStatus = vk_common_GetFenceStatus;
+   dispatch_table.WaitForFences = vk_common_WaitForFences;
+   dispatch_table.CreateSemaphore = vk_common_CreateSemaphore;
+   dispatch_table.DestroySemaphore = vk_common_DestroySemaphore;
+   dispatch_table.CreateShaderModule = vk_common_CreateShaderModule;
+   dispatch_table.DestroyShaderModule = vk_common_DestroyShaderModule;
+   dispatch_table.CreateRenderPass = vk_common_CreateRenderPass;
+   dispatch_table.CreateRenderPass2 = vk_common_CreateRenderPass2;
+   dispatch_table.CreateRenderPass2KHR =
+      (PFN_vkCreateRenderPass2KHR)vk_common_CreateRenderPass2;
+   dispatch_table.DestroyRenderPass = vk_common_DestroyRenderPass;
+   dispatch_table.CreateQueryPool = lvp_CreateQueryPool;
+   dispatch_table.DestroyQueryPool = lvp_DestroyQueryPool;
+   dispatch_table.CreateFramebuffer = vk_common_CreateFramebuffer;
+   dispatch_table.DestroyFramebuffer = vk_common_DestroyFramebuffer;
+   dispatch_table.DestroyCommandPool = vk_common_DestroyCommandPool;
+   dispatch_table.FreeCommandBuffers = vk_common_FreeCommandBuffers;
+   dispatch_table.FreeMemory = lvp_FreeMemory;
+   dispatch_table.MapMemory = vk_common_MapMemory;
+   dispatch_table.BindBufferMemory = vk_common_BindBufferMemory;
+   dispatch_table.BindImageMemory = vk_common_BindImageMemory;
+   dispatch_table.GetImageSubresourceLayout = vk_common_GetImageSubresourceLayout;
+   dispatch_table.CmdPipelineBarrier = vk_common_CmdPipelineBarrier;
+   dispatch_table.CmdCopyImage = vk_common_CmdCopyImage;
+   dispatch_table.CmdCopyImageToBuffer = vk_common_CmdCopyImageToBuffer;
+   dispatch_table.CmdWriteTimestamp = vk_common_CmdWriteTimestamp;
    VkResult result = vk_device_init(&device->vk,
                                     &physical_device->vk,
                                     &dispatch_table, pCreateInfo,
diff --git a/src/gallium/frontends/lavapipe/lvp_wsi.c b/src/gallium/frontends/lavapipe/lvp_wsi.c
index 83e96597033..5d439a7a80f 100644
--- a/src/gallium/frontends/lavapipe/lvp_wsi.c
+++ b/src/gallium/frontends/lavapipe/lvp_wsi.c
@@ -44,7 +44,7 @@ lvp_init_wsi(struct lvp_physical_device *physical_device)
    if (result != VK_SUCCESS)
       return result;
 
-   physical_device->wsi_device.wants_linear = true;
+   physical_device->wsi_device.wants_linear = false;
    physical_device->vk.wsi_device = &physical_device->wsi_device;
 
    return VK_SUCCESS;
diff --git a/src/gallium/targets/lavapipe/meson.build b/src/gallium/targets/lavapipe/meson.build
index 41de1e5a0f1..8b1697f571d 100644
--- a/src/gallium/targets/lavapipe/meson.build
+++ b/src/gallium/targets/lavapipe/meson.build
@@ -1,4 +1,48 @@
 
+static_lvp_shim = custom_target(
+  'lvp_static_shim',
+  input : [files('lvp_static_shim_gen.py'), vk_api_xml],
+  output : 'lvp_static_shim.c',
+  command : [
+    prog_python, '@INPUT0@', '--xml', '@INPUT1@',
+    '--out-c', '@OUTPUT@',
+    '--beta', with_vulkan_beta.to_string(),
+  ],
+  depend_files : vk_entrypoints_gen_depend_files,
+)
+
+libvulkan_lvp_static = static_library(
+  'vulkan_lvp_static',
+  [ 'lavapipe_target.c', static_lvp_shim ],
+  include_directories : [ inc_include, inc_src, inc_util, inc_gallium, inc_gallium_aux, inc_gallium_winsys, inc_gallium_drivers, inc_llvmpipe, include_directories('../../frontends/lavapipe') ],
+  link_whole : [
+    liblavapipe_st,
+    libpipe_loader_static,
+    libloader,
+    _libmesa_util,
+    libmesa_util_clflush,
+    libmesa_util_clflushopt,
+    libmesa_util_simd,
+    blake3,
+    _libmesa_util_c11,
+    _libxmlconfig,
+    libgallium,
+    _libnir,
+    libcompiler,
+    libwsw,
+    libws_null,
+    libllvmpipe,
+    libvulkan_util,
+    libloader_wayland_helper,
+    libvtn,
+  ],
+  gnu_symbol_visibility : 'hidden',
+  override_options : ['b_lundef=@0@'.format(host_machine.system() == 'darwin' ? 'false' : get_option('b_lundef').to_string())],
+  dependencies : [ driver_llvmpipe, idep_mesautil, idep_nir, idep_vulkan_util,
+                   idep_vulkan_wsi, idep_vulkan_runtime, lvp_deps ],
+  install : false,
+)
+
 
 libvulkan_lvp = shared_library(
   'vulkan_lvp',
diff --git a/src/gallium/targets/lavapipe/lvp_static_shim_gen.py b/src/gallium/targets/lavapipe/lvp_static_shim_gen.py
new file mode 100644
index 00000000000..bf07f8549cc
--- /dev/null
+++ b/src/gallium/targets/lavapipe/lvp_static_shim_gen.py
@@ -0,0 +1,182 @@
+#!/usr/bin/env python3
+
+import argparse
+import os
+import sys
+
+
+def _import_vk_entrypoints():
+    util_dir = os.path.normpath(
+        os.path.join(os.path.dirname(__file__), "..", "..", "..", "vulkan", "util")
+    )
+    sys.path.insert(0, util_dir)
+    from vk_entrypoints import get_entrypoints_from_xml
+
+    return get_entrypoints_from_xml
+
+
+def decl_params(entrypoint):
+    return ", ".join(p.decl for p in entrypoint.params) or "void"
+
+
+def call_params(entrypoint):
+    return ", ".join(p.name for p in entrypoint.params)
+
+
+def lookup_helper(entrypoint):
+    if not entrypoint.params:
+        return "lvp_static_lookup_global", None
+
+    first_param = entrypoint.params[0]
+    if first_param.type not in (
+        "VkInstance",
+        "VkPhysicalDevice",
+        "VkDevice",
+        "VkQueue",
+        "VkCommandBuffer",
+    ):
+        return "lvp_static_lookup_global", None
+
+    if first_param.type == "VkInstance":
+        return "lvp_static_lookup_instance", first_param.name
+    if first_param.type == "VkPhysicalDevice":
+        return "lvp_static_lookup_physical_device", first_param.name
+    if first_param.type == "VkDevice":
+        return "lvp_static_lookup_device", first_param.name
+    if first_param.type == "VkQueue":
+        return "lvp_static_lookup_queue", first_param.name
+    if first_param.type == "VkCommandBuffer":
+        return "lvp_static_lookup_command_buffer", first_param.name
+
+    raise ValueError(f"Unhandled dispatch type for vk{entrypoint.name}")
+
+
+def emit_wrapper(entrypoint):
+    body = []
+
+    if entrypoint.name == "GetInstanceProcAddr":
+        body.append(
+            "   return lvp_GetInstanceProcAddr(instance, pName);\n"
+        )
+    elif entrypoint.name == "GetDeviceProcAddr":
+        body.append(
+            "   VK_FROM_HANDLE(vk_device, vk_device, device);\n"
+            "   return vk_device_get_proc_addr(vk_device, pName);\n"
+        )
+    else:
+        helper, handle_name = lookup_helper(entrypoint)
+        if handle_name is None:
+            body.append(
+                f'   PFN_vk{entrypoint.name} proc = (PFN_vk{entrypoint.name})'
+                f'{helper}("vk{entrypoint.name}");\n'
+            )
+        else:
+            body.append(
+                f'   PFN_vk{entrypoint.name} proc = (PFN_vk{entrypoint.name})'
+                f'{helper}({handle_name}, "vk{entrypoint.name}");\n'
+            )
+        body.append("   assert(proc != NULL);\n")
+
+        params = call_params(entrypoint)
+        if entrypoint.return_type == "void":
+            body.append(f"   proc({params});\n")
+        else:
+            body.append(f"   return proc({params});\n")
+
+    return "".join(body)
+
+
+def render(entrypoints):
+    out = []
+    out.append("/* this file generated from lvp_static_shim_gen.py; don't edit directly */\n\n")
+    out.append('#include "lvp_private.h"\n\n')
+    out.append(
+        "static PFN_vkVoidFunction\n"
+        "lvp_static_lookup_global(const char *name)\n"
+        "{\n"
+        "   return lvp_GetInstanceProcAddr(VK_NULL_HANDLE, name);\n"
+        "}\n\n"
+    )
+    out.append(
+        "static PFN_vkVoidFunction\n"
+        "lvp_static_lookup_instance(VkInstance instance, const char *name)\n"
+        "{\n"
+        "   return lvp_GetInstanceProcAddr(instance, name);\n"
+        "}\n\n"
+    )
+    out.append(
+        "static PFN_vkVoidFunction\n"
+        "lvp_static_lookup_physical_device(VkPhysicalDevice physicalDevice,\n"
+        "                                 const char *name)\n"
+        "{\n"
+        "   VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);\n"
+        "   return vk_instance_get_physical_device_proc_addr(pdevice->instance, name);\n"
+        "}\n\n"
+    )
+    out.append(
+        "static PFN_vkVoidFunction\n"
+        "lvp_static_lookup_device(VkDevice device, const char *name)\n"
+        "{\n"
+        "   VK_FROM_HANDLE(vk_device, vk_device, device);\n"
+        "   return vk_device_get_proc_addr(vk_device, name);\n"
+        "}\n\n"
+    )
+    out.append(
+        "static PFN_vkVoidFunction\n"
+        "lvp_static_lookup_queue(VkQueue queue, const char *name)\n"
+        "{\n"
+        "   VK_FROM_HANDLE(vk_queue, vk_queue, queue);\n"
+        "   return vk_device_get_proc_addr(vk_queue->base.device, name);\n"
+        "}\n\n"
+    )
+    out.append(
+        "static PFN_vkVoidFunction\n"
+        "lvp_static_lookup_command_buffer(VkCommandBuffer commandBuffer,\n"
+        "                                 const char *name)\n"
+        "{\n"
+        "   VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, commandBuffer);\n"
+        "   return vk_device_get_proc_addr(cmd_buffer->base.device, name);\n"
+        "}\n\n"
+    )
+
+    for entrypoint in entrypoints:
+        if entrypoint.guard is not None:
+            out.append(f"#ifdef {entrypoint.guard}\n")
+
+        params = decl_params(entrypoint)
+        out.append(
+            f"PUBLIC VKAPI_ATTR {entrypoint.return_type} VKAPI_CALL\n"
+            f"vk{entrypoint.name}({params})\n"
+            "{\n"
+        )
+        out.append(emit_wrapper(entrypoint))
+        out.append("}\n")
+
+        if entrypoint.guard is not None:
+            out.append(f"#endif /* {entrypoint.guard} */\n")
+        out.append("\n")
+
+    return "".join(out)
+
+
+def main():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--out-c", required=True)
+    parser.add_argument(
+        "--xml",
+        required=True,
+        action="append",
+        dest="xml_files",
+    )
+    parser.add_argument("--beta", required=True)
+    args = parser.parse_args()
+
+    get_entrypoints_from_xml = _import_vk_entrypoints()
+    entrypoints = get_entrypoints_from_xml(args.xml_files, args.beta)
+
+    with open(args.out_c, "w", encoding="utf-8") as out_c:
+        out_c.write(render(entrypoints))
+
+
+if __name__ == "__main__":
+    main()