? Loading fortune...
wl/vkgears/0001-static-mesa-wayland.patch
$ cat 0001-static-mesa-wayland.patch
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1b1dfa3..078471f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -12,30 +12,24 @@ endif (HAVE_LIB_M)
 
 find_package(PkgConfig)
 pkg_check_modules(GLFW3 glfw3)
-pkg_check_modules(VULKAN vulkan)
 
 # Find OpenGL library
 include(FindOpenGL)
 
-# Find Vulkan library
-include(FindVulkan)
-if (NOT Vulkan_GLSLANG_VALIDATOR_EXECUTABLE)
-    find_program (GLSL_LANG_VALIDATOR NAMES glslangValidator PATHS ${VULKAN_SDK}/bin)
-    set(Vulkan_GLSLANG_VALIDATOR_EXECUTABLE "${GLSL_LANG_VALIDATOR}")
-endif()
+find_program(GLSLANG_VALIDATOR NAMES glslangValidator PATHS ${VULKAN_SDK}/bin)
 
 # set defaults for options
-set (OPENGL_EXAMPLES_DEFAULT ${OpenGL_OpenGL_FOUND})
-set (VULKAN_EXAMPLES_DEFAULT ${Vulkan_FOUND})
-if(NOT Vulkan_GLSLANG_VALIDATOR_EXECUTABLE)
+set (OPENGL_EXAMPLES_DEFAULT OFF)
+set (VULKAN_EXAMPLES_DEFAULT ON)
+if(NOT GLSLANG_VALIDATOR)
     set (VULKAN_EXAMPLES_DEFAULT OFF)
 endif()
 
 # user configurable options
 option(OPENGL_EXAMPLES "Build OpenGL examples" ${OPENGL_EXAMPLES_DEFAULT})
 option(VULKAN_EXAMPLES "Build Vulkan examples" ${VULKAN_EXAMPLES_DEFAULT})
-option(EXTERNAL_GLFW "Use external GLFW project" ON)
-option(EXTERNAL_GLAD "Use external GLAD project" ON)
+option(EXTERNAL_GLFW "Use external GLFW project" OFF)
+option(EXTERNAL_GLAD "Use external GLAD project" OFF)
 
 message(STATUS "OPENGL_EXAMPLES = ${OPENGL_EXAMPLES}")
 message(STATUS "VULKAN_EXAMPLES = ${VULKAN_EXAMPLES}")
@@ -69,7 +63,7 @@ if (EXTERNAL_GLFW)
     list(APPEND GLFW_LIBS_ALL ${GLFW_LIBRARIES} ${EXTRA_LIBS})
 else ()
     add_definitions(${GLFW3_CFLAGS})
-    list(APPEND GLFW_LIBS_ALL ${GLFW3_LDFLAGS} ${EXTRA_LIBS})
+    list(APPEND GLFW_LIBS_ALL ${GLFW3_STATIC_LDFLAGS} ${EXTRA_LIBS})
 endif ()
 
 # Support for external glad
@@ -111,6 +105,33 @@ if (OPENGL_EXAMPLES)
 endif (OPENGL_EXAMPLES)
 
 if (VULKAN_EXAMPLES)
+    find_library(MESA_STATIC_VULKAN NAMES vulkan_lvp_static REQUIRED)
+    find_package(Threads REQUIRED)
+    find_program(LLVM_CONFIG llvm-config REQUIRED)
+    execute_process(
+        COMMAND ${LLVM_CONFIG} --libs
+        OUTPUT_VARIABLE LLVM_LIBS
+        OUTPUT_STRIP_TRAILING_WHITESPACE
+    )
+    separate_arguments(LLVM_LIBS)
+
+    find_library(LIBZ z)
+    find_library(LIBZSTD zstd)
+    find_library(LIBUNWIND unwind)
+    find_library(LIBDRM drm)
+    find_library(LIBEXPAT expat)
+    find_library(LIBDISPLAY_INFO display-info)
+    find_library(LIBWAYLAND_CLIENT wayland-client)
+    find_library(LIBUDEV udev)
+    find_library(LIBSENSORS sensors)
+    find_library(LIBSPIRVTOOLS_OPT SPIRV-Tools-opt)
+    find_library(LIBSPIRVTOOLS SPIRV-Tools)
+    find_library(LIBSPIRVTOOLS_LINK SPIRV-Tools-link)
+
+    if (EXISTS "${CMAKE_SOURCE_DIR}/../include/vulkan/vulkan.h")
+        include_directories("${CMAKE_SOURCE_DIR}/../include")
+    endif ()
+
     file(GLOB_RECURSE VERTEX_SHADER_SOURCE "${SHADER_DIR}/*.v450.vert")
     file(GLOB_RECURSE FRAGMENT_SHADER_SOURCE "${SHADER_DIR}/*.v450.frag")
     set(SHADER_SOURCE ${VERTEX_SHADER_SOURCE} ${FRAGMENT_SHADER_SOURCE})
@@ -118,15 +139,38 @@ if (VULKAN_EXAMPLES)
 
     foreach(shader ${SHADER_SOURCE})
         add_custom_command(OUTPUT ${shader}.spv DEPENDS ${shader}
-            COMMAND ${Vulkan_GLSLANG_VALIDATOR_EXECUTABLE} -V ${shader} -o ${shader}.spv)
+            COMMAND ${GLSLANG_VALIDATOR} -V ${shader} -o ${shader}.spv)
         list(APPEND SHADERS ${shader}.spv)
     endforeach(shader)
-
-    include_directories(${Vulkan_INCLUDE_DIRS})
+    set(VK1_GEARS_VULKAN_LIBS
+        ${MESA_STATIC_VULKAN}
+        ${LLVM_LIBS}
+        stdc++
+        Threads::Threads
+        ${EXTRA_LIBS}
+    )
+    foreach(lib IN ITEMS
+        LIBZSTD
+        LIBZ
+        LIBUNWIND
+        LIBDRM
+        LIBEXPAT
+        LIBDISPLAY_INFO
+        LIBWAYLAND_CLIENT
+        LIBUDEV
+        LIBSENSORS
+        LIBSPIRVTOOLS_OPT
+        LIBSPIRVTOOLS
+        LIBSPIRVTOOLS_LINK
+    )
+        if (${lib})
+            list(APPEND VK1_GEARS_VULKAN_LIBS ${${lib}})
+        endif ()
+    endforeach()
 
     message("-- Adding: vk1_gears")
     add_executable(vk1_gears src/vk1_gears.c ${SHADERS})
-    target_link_libraries(vk1_gears ${Vulkan_LIBRARIES} ${GLFW_LIBS_ALL})
+    target_link_libraries(vk1_gears ${VK1_GEARS_VULKAN_LIBS} ${GLFW_LIBS_ALL})
 
     if (EXTERNAL_GLFW)
         add_dependencies(vk1_gears GLFW-build)
diff --git a/src/vk1_gears.c b/src/vk1_gears.c
index 8e6e63d..8f79ffc 100644
--- a/src/vk1_gears.c
+++ b/src/vk1_gears.c
@@ -40,6 +40,7 @@
 #include <string.h>
 #include <assert.h>
 #include <errno.h>
+#include <limits.h>
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -47,8 +48,16 @@
 
 #include "linmath.h"
 
-#include <vulkan/vulkan_core.h>
+#define VK_USE_PLATFORM_WAYLAND_KHR
+#define GLFW_INCLUDE_NONE
+#define GLFW_EXPOSE_NATIVE_WAYLAND
+#include <vulkan/vulkan.h>
 #include <GLFW/glfw3.h>
+#include <GLFW/glfw3native.h>
+
+#ifndef VKGEARS_SHADER_DIR
+#define VKGEARS_SHADER_DIR "/usr/share/vkgears/shaders"
+#endif
 
 static const char* frag_shader_filename = "shaders/gears.v450.frag.spv";
 static const char* vert_shader_filename = "shaders/gears.v450.vert.spv";
@@ -142,6 +151,7 @@ typedef struct gears_app
     VkFormat format;
     VkColorSpaceKHR color_space;
     VkSurfaceCapabilitiesKHR surface_capabilities;
+    VkExtent2D swapchain_extent;
     VkSwapchainKHR swapchain;
     VkSampleCountFlags sample_count;
     uint32_t swapchain_image_count;
@@ -493,12 +503,22 @@ static void gears_parse_options(gears_app *app, const int argc, const char **arg
 
 static void gears_init_glfw(gears_app *app)
 {
+    glfwSetErrorCallback(gears_glfw_error);
+#ifdef GLFW_PLATFORM_WAYLAND
+    glfwInitHint(GLFW_PLATFORM, GLFW_PLATFORM_WAYLAND);
+#endif
     if (!glfwInit()) {
-        panic("glfwInit failed\n");
+        const char *error_desc = NULL;
+        int error_code = glfwGetError(&error_desc);
+        panic("glfwInit failed: code=%d desc=%s\n",
+              error_code,
+              error_desc ? error_desc : "(null)");
     }
-    if (!glfwVulkanSupported()) {
-        panic("glfwVulkanSupported failed\n");
+#ifdef GLFW_PLATFORM_WAYLAND
+    if (glfwGetPlatform() != GLFW_PLATFORM_WAYLAND) {
+        panic("glfw did not initialize a wayland backend\n");
     }
+#endif
 }
 
 static void gears_destroy_window(gears_app *app)
@@ -510,7 +530,6 @@ static void gears_destroy_window(gears_app *app)
 static void gears_create_window(gears_app *app)
 {
     glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
-    glfwSetErrorCallback(gears_glfw_error);
     app->window = glfwCreateWindow(app->width, app->height, "VK1 Gears",
         NULL, NULL);
     if (!app->window) {
@@ -547,12 +566,9 @@ static int check_layers(VkLayerProperties *instance_layers,
 
 static void gears_create_instance(gears_app *app)
 {
-    uint32_t required_extension_count = 0;
     uint32_t instance_count = 0;
-    uint32_t validation_layer_count = 0;
     uint32_t enabled_extensions_count = 0;
     uint32_t enabled_layer_count = 0;
-    const char **required_extensions = NULL;
     const char *extension_names[64];
     const char *layer_names[64];
 
@@ -585,15 +601,9 @@ static void gears_create_instance(gears_app *app)
         free(instance_layers);
     }
 
-    required_extensions =
-        glfwGetRequiredInstanceExtensions(&required_extension_count);
-    if (!required_extensions) {
-        panic("glfwGetRequiredInstanceExtensions failed\n");
-    }
-    for (size_t i = 0; i < required_extension_count; i++) {
-        extension_names[enabled_extensions_count++] = required_extensions[i];
-        assert(enabled_extensions_count < 64);
-    }
+    extension_names[enabled_extensions_count++] = VK_KHR_SURFACE_EXTENSION_NAME;
+    extension_names[enabled_extensions_count++] = VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME;
+    assert(enabled_extensions_count < 64);
 
     const VkApplicationInfo ai = {
         .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
@@ -624,8 +634,20 @@ static void gears_destroy_surface(gears_app *app)
 
 static void gears_create_surface(gears_app *app)
 {
-    VK_CALL(glfwCreateWindowSurface
-        (app->instance, app->window, NULL, &app->surface));
+    struct wl_display *display = glfwGetWaylandDisplay();
+    struct wl_surface *surface = glfwGetWaylandWindow(app->window);
+    if (!display || !surface) {
+        panic("GLFW did not expose Wayland display/surface\n");
+    }
+
+    const VkWaylandSurfaceCreateInfoKHR wsci = {
+        .sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
+        .pNext = NULL,
+        .flags = 0,
+        .display = display,
+        .surface = surface,
+    };
+    VK_CALL(vkCreateWaylandSurfaceKHR(app->instance, &wsci, NULL, &app->surface));
 }
 
 static void gears_find_physical_device(gears_app *app)
@@ -766,8 +788,35 @@ static void gears_create_swapchain(gears_app *app)
         (app->physdev, app->surface, &app->surface_capabilities));
 
     glfwGetFramebufferSize(app->window, &app->width, &app->height);
-    assert(app->surface_capabilities.currentExtent.width == app->width);
-    assert(app->surface_capabilities.currentExtent.height == app->height);
+    if (app->surface_capabilities.currentExtent.width == UINT32_MAX) {
+        app->swapchain_extent.width = app->width;
+        app->swapchain_extent.height = app->height;
+
+        if (app->swapchain_extent.width <
+            app->surface_capabilities.minImageExtent.width) {
+            app->swapchain_extent.width =
+                app->surface_capabilities.minImageExtent.width;
+        }
+        if (app->swapchain_extent.width >
+            app->surface_capabilities.maxImageExtent.width) {
+            app->swapchain_extent.width =
+                app->surface_capabilities.maxImageExtent.width;
+        }
+        if (app->swapchain_extent.height <
+            app->surface_capabilities.minImageExtent.height) {
+            app->swapchain_extent.height =
+                app->surface_capabilities.minImageExtent.height;
+        }
+        if (app->swapchain_extent.height >
+            app->surface_capabilities.maxImageExtent.height) {
+            app->swapchain_extent.height =
+                app->surface_capabilities.maxImageExtent.height;
+        }
+    } else {
+        app->swapchain_extent = app->surface_capabilities.currentExtent;
+        assert(app->swapchain_extent.width == (uint32_t) app->width);
+        assert(app->swapchain_extent.height == (uint32_t) app->height);
+    }
 
     if (app->surface_capabilities.maxImageCount != 0 &&
         min_image_count > app->surface_capabilities.maxImageCount) {
@@ -784,10 +833,6 @@ static void gears_create_swapchain(gears_app *app)
     }
 
     /* create swapchain */
-    const VkExtent2D swapchain_extent = {
-        app->surface_capabilities.currentExtent.width,
-        app->surface_capabilities.currentExtent.height
-    };
     const VkSwapchainCreateInfoKHR sci = {
         .sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
         .pNext = NULL,
@@ -797,8 +842,8 @@ static void gears_create_swapchain(gears_app *app)
         .imageFormat = app->format,
         .imageColorSpace = app->color_space,
         .imageExtent = {
-            .width = swapchain_extent.width,
-            .height = swapchain_extent.height,
+            .width = app->swapchain_extent.width,
+            .height = app->swapchain_extent.height,
         },
         .imageArrayLayers = 1,
         .imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
@@ -895,7 +940,11 @@ static void gears_create_image(gears_app *app, gears_image_buffer *imbuf,
         .flags = 0,
         .imageType = VK_IMAGE_TYPE_2D,
         .format = imbuf->format,
-        .extent = { app->width, app->height, 1 },
+        .extent = {
+            app->swapchain_extent.width,
+            app->swapchain_extent.height,
+            1
+        },
         .mipLevels = 1,
         .arrayLayers = 1,
         .samples = sample_count,
@@ -1208,8 +1257,8 @@ static void gears_create_frame_buffers(gears_app *app)
         .renderPass = app->render_pass,
         .attachmentCount = app->multisampling_enable ? 3 : 2,
         .pAttachments = attachments,
-        .width = app->width,
-        .height = app->height,
+        .width = app->swapchain_extent.width,
+        .height = app->swapchain_extent.height,
         .layers = 1,
     };
 
@@ -1246,10 +1295,18 @@ static VkShaderModule gears_create_shader_from_file(gears_app *app,
     char *buf;
     size_t nread;
     VkShaderModule module;
+    char installed_filename[PATH_MAX];
 
     if ((f = fopen(filename, "r")) == NULL) {
-        panic("gears_create_shader_from_file: open: %s: %s",
-            filename, strerror(errno));
+        snprintf(installed_filename, sizeof(installed_filename), "%s/%s",
+            VKGEARS_SHADER_DIR, strrchr(filename, '/') ?
+            strrchr(filename, '/') + 1 : filename);
+        f = fopen(installed_filename, "r");
+        if (f == NULL) {
+            panic("gears_create_shader_from_file: open: %s: %s",
+                installed_filename, strerror(errno));
+        }
+        filename = installed_filename;
     }
     if (fstat(fileno(f), &statbuf) < 0) {
         panic("gears_create_shader_from_file: stat: %s: %s",
@@ -1854,20 +1911,20 @@ static void gears_record_command_buffers(gears_app *app, size_t j)
         .renderPass = app->render_pass,
         .renderArea.offset.x = 0,
         .renderArea.offset.y = 0,
-        .renderArea.extent = app->surface_capabilities.currentExtent,
+        .renderArea.extent = app->swapchain_extent,
         .clearValueCount = 3,
         .pClearValues = clear_values,
     };
 
     VkRect2D scissor = {
-        .extent = app->surface_capabilities.currentExtent
+        .extent = app->swapchain_extent
     };
 
     VkViewport viewport = {
         .x = 0,
-        .y = (float)app->surface_capabilities.currentExtent.height,
-        .height = -(float)app->surface_capabilities.currentExtent.height,
-        .width = (float)app->surface_capabilities.currentExtent.width,
+        .y = (float)app->swapchain_extent.height,
+        .height = -(float)app->swapchain_extent.height,
+        .width = (float)app->swapchain_extent.width,
         .minDepth = 0.0f,
         .maxDepth = 1.0f,
     };