diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000000..842052ece7c --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,265 @@ +name: CI + +on: + push: + branches: [wrapper, PR] + pull_request: + branches: [wrapper] + +jobs: + build-wrapper: + name: Build Vulkan Wrapper (x86_64) + runs-on: ubuntu-24.04 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install system dependencies + run: | + sudo apt-get update + sudo apt-get install -y \ + meson ninja-build \ + python3 python3-mako python3-ply python3-yaml \ + glslang-tools \ + libvulkan-dev \ + libwayland-dev libwayland-egl-backend-dev wayland-protocols \ + libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxcb1-dev libxcb-dri2-0-dev \ + libxcb-dri3-dev libxcb-present-dev libxcb-shm0-dev libxcb-randr0-dev \ + libxcb-keysyms1-dev libxshmfence-dev libxxf86vm-dev libxrandr-dev \ + libdrm-dev libelf-dev \ + libexpat1-dev \ + zlib1g-dev \ + cmake git \ + clang + + - name: Build SPIRV-Tools for host + run: | + git clone --depth 1 --branch v2024.4.rc2 https://github.com/KhronosGroup/SPIRV-Tools.git /tmp/SPIRV-Tools + cd /tmp/SPIRV-Tools + python3 utils/git-sync-deps + mkdir build && cd build + cmake .. -DCMAKE_BUILD_TYPE=Release -DSPIRV_SKIP_TESTS=ON + cmake --build . --config Release -j$(nproc) --target SPIRV-Tools-static SPIRV-Tools-opt + mkdir -p $GITHUB_WORKSPACE/src/vulkan/wrapper/lib + cp source/libSPIRV-Tools.a $GITHUB_WORKSPACE/src/vulkan/wrapper/lib/ + cp source/opt/libSPIRV-Tools-opt.a $GITHUB_WORKSPACE/src/vulkan/wrapper/lib/ + mkdir -p $GITHUB_WORKSPACE/src/vulkan/wrapper/include/spirv-tools + cp -r /tmp/SPIRV-Tools/include/* $GITHUB_WORKSPACE/src/vulkan/wrapper/include/spirv-tools/ + + - name: Configure Mesa (wrapper only) + env: + CC: clang + CXX: clang++ + run: | + STUB_ARGS="-D__INTRODUCED_IN(x)= -D__ANDROID_API__=26 -D__TERMUX__" + STUB_C="$STUB_ARGS -include sys/syscall.h" + STUB_CXX="$STUB_ARGS -DNULL=nullptr" + meson setup _build \ + -Dvulkan-drivers=wrapper \ + -Dgallium-drivers= \ + -Dandroid-stub=true \ + -Dplatforms=x11,wayland \ + -Dglx=disabled \ + -Degl=disabled \ + -Dgbm=disabled \ + -Dopengl=false \ + -Dgles1=disabled \ + -Dgles2=disabled \ + -Dllvm=disabled \ + -Dshared-glapi=disabled \ + -Dbuildtype=release \ + -Dc_args="$STUB_C" \ + -Dcpp_args="$STUB_CXX" + + - name: Build + run: | + ninja -C _build src/vulkan/wrapper/libvulkan_wrapper.so + + - name: Upload wrapper artifacts + if: success() + uses: actions/upload-artifact@v4 + with: + name: vulkan-wrapper + path: | + _build/src/vulkan/wrapper/libvulkan_wrapper.so + _build/src/vulkan/wrapper/wrapper_icd.*.json + + - name: Report build artifacts + if: always() + run: | + echo "=== Build log ===" + cat _build/meson-logs/meson-log.txt | tail -100 || true + echo "=== Built files ===" + find _build/src/vulkan/wrapper -name '*.so' -o -name '*.json' 2>/dev/null || true + + build-wrapper-arm64-ndk: + name: Build Vulkan Wrapper (ARM64 Android NDK) + runs-on: ubuntu-24.04 + + env: + NDK_VERSION: r27c + ANDROID_API: 26 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Install build tools + run: | + sudo apt-get update + sudo apt-get install -y \ + meson ninja-build \ + python3 python3-mako python3-ply python3-yaml \ + glslang-tools \ + cmake git \ + unzip wget + + - name: Setup Android NDK + run: | + wget -q https://dl.google.com/android/repository/android-ndk-${NDK_VERSION}-linux.zip -O /tmp/ndk.zip + unzip -q /tmp/ndk.zip -d /tmp + echo "ANDROID_NDK_HOME=/tmp/android-ndk-${NDK_VERSION}" >> $GITHUB_ENV + NDK_TC="/tmp/android-ndk-${NDK_VERSION}/toolchains/llvm/prebuilt/linux-x86_64" + echo "${NDK_TC}/bin" >> $GITHUB_PATH + echo "NDK_TOOLCHAIN=${NDK_TC}" >> $GITHUB_ENV + # Verify toolchain + ${NDK_TC}/bin/aarch64-linux-android${ANDROID_API}-clang --version + + - name: Build SPIRV-Tools for Android aarch64 (custom fork) + run: | + git clone --depth 1 https://github.com/BlueInstruction/SPIRV-Tools.git /tmp/SPIRV-Tools + cd /tmp/SPIRV-Tools + python3 utils/git-sync-deps + mkdir build && cd build + cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DSPIRV_SKIP_TESTS=ON \ + -DCMAKE_SYSTEM_NAME=Android \ + -DCMAKE_SYSTEM_VERSION=${ANDROID_API} \ + -DCMAKE_ANDROID_ARCH_ABI=arm64-v8a \ + -DCMAKE_ANDROID_NDK=${ANDROID_NDK_HOME} \ + -DCMAKE_ANDROID_STL_TYPE=c++_static + cmake --build . --config Release -j$(nproc) --target SPIRV-Tools-static SPIRV-Tools-opt + mkdir -p $GITHUB_WORKSPACE/src/vulkan/wrapper/lib + cp source/libSPIRV-Tools.a $GITHUB_WORKSPACE/src/vulkan/wrapper/lib/ + cp source/opt/libSPIRV-Tools-opt.a $GITHUB_WORKSPACE/src/vulkan/wrapper/lib/ + # Do NOT overwrite the patched headers — they contain custom pass declarations + # Only copy headers that don't already exist in the repo + find /tmp/SPIRV-Tools/include -type f | while read src; do + rel="${src#/tmp/SPIRV-Tools/include/}" + dst="$GITHUB_WORKSPACE/src/vulkan/wrapper/include/spirv-tools/$rel" + if [ ! -f "$dst" ]; then + mkdir -p "$(dirname "$dst")" + cp "$src" "$dst" + fi + done + + - name: Download Termux prebuilt packages for aarch64 + run: | + set -e + SYSROOT=$GITHUB_WORKSPACE/_sysroot + mkdir -p $SYSROOT + + # Termux package base URL for aarch64 + TERMUX_REPO="https://packages.termux.dev/apt/termux-main/pool/main" + + # Download and extract .deb packages (contains headers + .so + .pc files) + download_termux_pkg() { + local pkg=$1 letter=$2 + local url="${TERMUX_REPO}/${letter}/${pkg}" + echo "Downloading ${pkg}..." + wget -q "$url" -O /tmp/pkg.deb + cd /tmp && ar x pkg.deb && tar xf data.tar.* -C $SYSROOT --strip-components=3 ./data/data/com.termux/files/usr/ 2>/dev/null || tar xf data.tar.* -C $SYSROOT --strip-components=4 2>/dev/null || true + rm -f /tmp/pkg.deb /tmp/data.tar.* /tmp/control.tar.* /tmp/debian-binary + } + + # Core X11/XCB libraries needed by libvulkan_wrapper.so + download_termux_pkg "libdrm_2.4.124-1_aarch64.deb" "libd" + download_termux_pkg "libdrm-dev_2.4.124-1_aarch64.deb" "libd" + download_termux_pkg "libx11_1.8.10_aarch64.deb" "libx" + download_termux_pkg "libx11-dev_1.8.10_aarch64.deb" "libx" + download_termux_pkg "libxcb_1.17.0_aarch64.deb" "libx" + download_termux_pkg "libxcb-dev_1.17.0_aarch64.deb" "libx" + download_termux_pkg "libxau_1.0.11-1_aarch64.deb" "libx" + download_termux_pkg "libxau-dev_1.0.11-1_aarch64.deb" "libx" + download_termux_pkg "libxdmcp_1.1.5_aarch64.deb" "libx" + download_termux_pkg "libxdmcp-dev_1.1.5_aarch64.deb" "libx" + download_termux_pkg "libxext_1.3.6_aarch64.deb" "libx" + download_termux_pkg "libxext-dev_1.3.6_aarch64.deb" "libx" + download_termux_pkg "libxrandr_1.5.4_aarch64.deb" "libx" + download_termux_pkg "libxrandr-dev_1.5.4_aarch64.deb" "libx" + download_termux_pkg "libxrender_0.9.11_aarch64.deb" "libx" + download_termux_pkg "libxrender-dev_0.9.11_aarch64.deb" "libx" + download_termux_pkg "libxshmfence_1.3.2_aarch64.deb" "libx" + download_termux_pkg "libxshmfence-dev_1.3.2_aarch64.deb" "libx" + download_termux_pkg "libxfixes_6.0.1_aarch64.deb" "libx" + download_termux_pkg "libxfixes-dev_6.0.1_aarch64.deb" "libx" + download_termux_pkg "libxxf86vm_1.1.5-1_aarch64.deb" "libx" + download_termux_pkg "libxxf86vm-dev_1.1.5-1_aarch64.deb" "libx" + download_termux_pkg "xorgproto_2024.1_aarch64.deb" "xorg" + download_termux_pkg "libelf_0.192_aarch64.deb" "libe" + download_termux_pkg "libelf-dev_0.192_aarch64.deb" "libe" + download_termux_pkg "libexpat_2.6.4_aarch64.deb" "libe" + download_termux_pkg "libexpat-dev_2.6.4_aarch64.deb" "libe" + download_termux_pkg "libwayland_1.23.1_aarch64.deb" "libw" + download_termux_pkg "libwayland-dev_1.23.1_aarch64.deb" "libw" + download_termux_pkg "wayland-protocols_1.38_aarch64.deb" "wayl" + + echo "=== Installed sysroot contents ===" + find $SYSROOT/lib/pkgconfig -name '*.pc' 2>/dev/null | sort || true + ls -la $SYSROOT/lib/*.so* 2>/dev/null | head -20 || true + + - name: Configure Mesa (wrapper only, Android NDK aarch64) + run: | + STUB_ARGS="-D__INTRODUCED_IN(x)= -D__ANDROID_API__=${ANDROID_API} -D__TERMUX__ -DHAVE_CUSTOM_SPIRV_PASSES" + STUB_C="$STUB_ARGS" + STUB_CXX="$STUB_ARGS -DNULL=nullptr" + PKG_CONFIG_LIBDIR=$GITHUB_WORKSPACE/_sysroot/lib/pkgconfig:$GITHUB_WORKSPACE/_sysroot/share/pkgconfig \ + meson setup _build \ + --cross-file cross/aarch64-linux-android.txt \ + -Dvulkan-drivers=wrapper \ + -Dgallium-drivers= \ + -Dandroid-stub=true \ + -Dplatforms=x11 \ + -Dglx=disabled \ + -Degl=disabled \ + -Dgbm=disabled \ + -Dopengl=false \ + -Dgles1=disabled \ + -Dgles2=disabled \ + -Dllvm=disabled \ + -Dshared-glapi=disabled \ + -Dbuildtype=release \ + -Dc_args="$STUB_C" \ + -Dcpp_args="$STUB_CXX" + + - name: Build + run: | + ninja -C _build src/vulkan/wrapper/libvulkan_wrapper.so + + - name: Verify Android ARM64 binary + run: | + file _build/src/vulkan/wrapper/libvulkan_wrapper.so + ${NDK_TOOLCHAIN}/bin/llvm-readelf -h _build/src/vulkan/wrapper/libvulkan_wrapper.so + echo "=== Dynamic dependencies ===" + ${NDK_TOOLCHAIN}/bin/llvm-readelf -d _build/src/vulkan/wrapper/libvulkan_wrapper.so | grep NEEDED || true + echo "=== File size ===" + ls -lh _build/src/vulkan/wrapper/libvulkan_wrapper.so + + - name: Upload Android ARM64 wrapper artifacts + if: success() + uses: actions/upload-artifact@v4 + with: + name: vulkan-wrapper-android-arm64 + path: | + _build/src/vulkan/wrapper/libvulkan_wrapper.so + _build/src/vulkan/wrapper/wrapper_icd.*.json + + - name: Report build artifacts + if: always() + run: | + echo "=== Build log (last 200 lines) ===" + cat _build/meson-logs/meson-log.txt | tail -200 || true + echo "=== Built files ===" + find _build/src/vulkan/wrapper -name '*.so' -o -name '*.json' 2>/dev/null || true diff --git a/cross/aarch64-linux-android.txt b/cross/aarch64-linux-android.txt new file mode 100644 index 00000000000..19f4f92b541 --- /dev/null +++ b/cross/aarch64-linux-android.txt @@ -0,0 +1,22 @@ +# Meson cross file for Android NDK aarch64 (ARM64) +# NDK_TOOLCHAIN env var must point to the NDK toolchain bin directory +# e.g. $ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64 + +[binaries] +c = 'aarch64-linux-android26-clang' +cpp = 'aarch64-linux-android26-clang++' +ar = 'llvm-ar' +strip = 'llvm-strip' +pkgconfig = 'pkg-config' + +[built-in options] +c_args = ['-fPIC'] +cpp_args = ['-fPIC'] +c_link_args = ['-fPIC'] +cpp_link_args = ['-fPIC', '-static-libstdc++'] + +[host_machine] +system = 'android' +cpu_family = 'aarch64' +cpu = 'aarch64' +endian = 'little' diff --git a/cross/aarch64-linux-gnu.txt b/cross/aarch64-linux-gnu.txt new file mode 100644 index 00000000000..db3a068f464 --- /dev/null +++ b/cross/aarch64-linux-gnu.txt @@ -0,0 +1,12 @@ +[binaries] +c = 'aarch64-linux-gnu-gcc' +cpp = 'aarch64-linux-gnu-g++' +ar = 'aarch64-linux-gnu-ar' +strip = 'aarch64-linux-gnu-strip' +pkgconfig = 'pkg-config' + +[host_machine] +system = 'linux' +cpu_family = 'aarch64' +cpu = 'aarch64' +endian = 'little' diff --git a/include/android_stub/cutils/trace.h b/include/android_stub/cutils/trace.h index 24c6ae62905..2e99cf258e3 100644 --- a/include/android_stub/cutils/trace.h +++ b/include/android_stub/cutils/trace.h @@ -18,7 +18,12 @@ #define _LIBS_CUTILS_TRACE_H #include +#ifdef __cplusplus +#include +using std::atomic_bool; +#else #include +#endif #include #include #include diff --git a/src/vulkan/wrapper/artifacts.cpp b/src/vulkan/wrapper/artifacts.cpp index 51b075364ef..407f878ea20 100644 --- a/src/vulkan/wrapper/artifacts.cpp +++ b/src/vulkan/wrapper/artifacts.cpp @@ -5,6 +5,12 @@ #include "wrapper_checks.h" #include "vk_printers.h" +#ifndef __ANDROID__ +#include +extern char *program_invocation_short_name; +static inline const char *getprogname() { return program_invocation_short_name; } +#endif + #define XXH_INLINE_ALL #include "util/xxhash.h" diff --git a/src/vulkan/wrapper/spirv_edit.cpp b/src/vulkan/wrapper/spirv_edit.cpp index 7d4311abe84..43eb7f83afd 100644 --- a/src/vulkan/wrapper/spirv_edit.cpp +++ b/src/vulkan/wrapper/spirv_edit.cpp @@ -13,6 +13,16 @@ extern "C" { #include "spirv-tools/spirv-tools/optimizer.hpp" #include "spirv-tools/spirv-tools/libspirv.hpp" +// Stub out custom SPIRV-Tools passes that only exist in the patched fork. +// These are no-ops for CI builds using upstream SPIRV-Tools v2024.4.rc2. +#ifndef HAVE_CUSTOM_SPIRV_PASSES +namespace spvtools { +static inline Optimizer::PassToken CreateRemoveClipCullDistPass() { return CreateNullPass(); } +static inline Optimizer::PassToken CreateFixMaliSpecConstantCompositePass() { return CreateNullPass(); } +static inline Optimizer::PassToken CreateMaliOptimizationBarrierPass() { return CreateNullPass(); } +} +#endif + extern "C" void log_disassembly_to_cmd_log(const uint32_t* spirv_binary, size_t spirv_word_count) { spvtools::SpirvTools tools(SPV_ENV_VULKAN_1_1_SPIRV_1_4); diff --git a/src/vulkan/wrapper/spirv_edit.h b/src/vulkan/wrapper/spirv_edit.h index 76cf57ae251..7e9c0dec0e9 100644 --- a/src/vulkan/wrapper/spirv_edit.h +++ b/src/vulkan/wrapper/spirv_edit.h @@ -2,6 +2,7 @@ #include #include +#include #ifdef __cplusplus extern "C" { diff --git a/src/vulkan/wrapper/vk_entrypoints.py b/src/vulkan/wrapper/vk_entrypoints.py index 32d497e4dd2..030949ff457 100644 --- a/src/vulkan/wrapper/vk_entrypoints.py +++ b/src/vulkan/wrapper/vk_entrypoints.py @@ -132,7 +132,7 @@ def print_param(command, param, mode='input', log='VK_CMD_LOG_UNCONDITIONAL', vk output.append(f" for (uint32_t i = 0; i < {count}; i++) {{") output.append(f" {log}(\" {param.name}[%d]: {param.type} = %lx (id=%d)\", i, (int64_t){param.name}[i], cmd_id);"); output.append(f" }}") - elif param.num_pointers and not is_input and param.type not in ("void", "Display", "xcb_connection_t"): + elif param.num_pointers and not is_input and param.type not in ("void", "Display", "xcb_connection_t", "wl_display"): output.append(f" {log}(\" {token}: *{param.name}: {param.type} = %lx (id=%d)\", (int64_t)*{param.name}, cmd_id);") elif param.num_pointers: output.append(f" {log}(\" {token}: {param.name}: {param.type}{'*' * param.num_pointers} = %lx (id=%d)\", (int64_t){param.name}, cmd_id);") diff --git a/src/vulkan/wrapper/wrapper_checks.h b/src/vulkan/wrapper/wrapper_checks.h index e73d9310568..d929703b325 100644 --- a/src/vulkan/wrapper/wrapper_checks.h +++ b/src/vulkan/wrapper/wrapper_checks.h @@ -18,10 +18,16 @@ #define CHECKV(call) __CHECKV__(wrapper_device_trampolines. call) #define PCHECKV(call) __CHECKV__(wrapper_physical_device_trampolines. call) +#if defined(__clang__) #define __W_WRAP__(call, expr) \ _Static_assert(__builtin_strcmp(__func__, name_of_wrapper_##call) != 0, \ "This WCHECK macro for " #call " cannot be used in the same wrapper, it will cause infinite recursion"); \ expr; +#else +/* GCC does not treat __builtin_strcmp(__func__, ...) as a constant expression */ +#define __W_WRAP__(call, expr) \ + expr; +#endif #define WCHECK(call) ({__W_WRAP__(call, has_device_wrapper_##call ? __CHECK__(wrapper_device_entrypoints. call) : CHECK(call))}) #define WCHECKV(call) {__W_WRAP__(call, { if(has_device_wrapper_##call) { __CHECKV__(wrapper_device_entrypoints. call); } else { CHECKV(call); }})} diff --git a/src/vulkan/wrapper/wrapper_device.c b/src/vulkan/wrapper/wrapper_device.c index 913928a58bd..6f9de382721 100644 --- a/src/vulkan/wrapper/wrapper_device.c +++ b/src/vulkan/wrapper/wrapper_device.c @@ -1028,7 +1028,6 @@ static int FindComputeQueueFamilies(struct wrapper_physical_device* physical_dev WPCHECKV(GetPhysicalDeviceQueueFamilyProperties( (VkPhysicalDevice) physical_device, &queueFamilyCount, queueFamilies)); - int i = 0; for (int i = 0; i < queueFamilyCount; i++) { if (queueFamilies[i].queueFlags & VK_QUEUE_COMPUTE_BIT) { return i; @@ -1331,8 +1330,6 @@ static void CmdComputeShaderForDecompression( bool is_bc6 = wimg->original_format == VK_FORMAT_BC6H_UFLOAT_BLOCK || wimg->original_format == VK_FORMAT_BC6H_SFLOAT_BLOCK; bool is_bc7 = wimg->original_format == VK_FORMAT_BC7_UNORM_BLOCK || wimg->original_format == VK_FORMAT_BC7_SRGB_BLOCK; - VkDescriptorType dstDescriptorType; - // Calculate the buffer size for an image // Normally 4x4 block is compressed to 16 bytes (1bpp), except for BC1 and BC4 (0.5 bpp) uint32_t srcBufferSize = calculate_bc_copy_size(region, 16); @@ -1748,12 +1745,18 @@ WRAPPER_CreateShaderModule(VkDevice device, const VkAllocationCallbacks* pAllocator, VkShaderModule* pShaderModule) { VK_FROM_HANDLE(wrapper_device, wdev, device); + const struct wrapper_driver_info *drv = &wdev->physical->drv_info; + + /* ClipDistance emulation: only needed when the driver doesn't natively support it. + * Turnip v26.0+ and Panfrost generally support shaderClipDistance natively. */ bool needs_clip_distance_emulation = !wdev->physical->base_supported_features.shaderClipDistance && !CHECK_FLAG("DISABLE_CLIP_DISTANCE"); - bool needs_spec_composite_constants_emulation = wdev->physical->driver_properties.driverID == VK_DRIVER_ID_ARM_PROPRIETARY + /* Mali proprietary SpecConstantComposite fix: not needed on Panfrost or Adreno drivers */ + bool needs_spec_composite_constants_emulation = (drv->gpu_vendor == WRAPPER_GPU_VENDOR_MALI_PROPRIETARY) && !CHECK_FLAG("DISABLE_SPEC_COMPOSITE_CONSTANTS"); - bool needs_optimization_barriers = (wdev->physical->driver_properties.driverID == VK_DRIVER_ID_ARM_PROPRIETARY - || wdev->physical->driver_properties.driverID == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) + /* Optimization barriers: only on proprietary drivers, not Mesa Turnip/Panfrost */ + bool needs_optimization_barriers = (drv->gpu_vendor == WRAPPER_GPU_VENDOR_MALI_PROPRIETARY + || drv->gpu_vendor == WRAPPER_GPU_VENDOR_ADRENO_PROPRIETARY) && !CHECK_FLAG("DISABLE_OPTIMIZATION_BARRIERS"); if (CHECK_FLAG("FORCE_CLIP_DISTANCE")) { needs_clip_distance_emulation = true; @@ -1945,6 +1948,6 @@ WRAPPER_CmdPipelineBarrier( CHECKV(CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, - imageMemoryBarrierCount, pImageMemoryBarriers)); + imageMemoryBarrierCount, barriers)); free_temp_objects(&temp); } \ No newline at end of file diff --git a/src/vulkan/wrapper/wrapper_device_memory.c b/src/vulkan/wrapper/wrapper_device_memory.c index f820ba11ed8..6990cf2c361 100644 --- a/src/vulkan/wrapper/wrapper_device_memory.c +++ b/src/vulkan/wrapper/wrapper_device_memory.c @@ -1,15 +1,14 @@ -// #define native_handle_t __native_handle_t -// #define buffer_handle_t __buffer_handle_t +#define buffer_handle_t __wrapper_buffer_handle_t #include "wrapper_private.h" #include "wrapper_entrypoints.h" #include "vk_common_entrypoints.h" -// #undef native_handle_t -// #undef buffer_handle_t +#undef buffer_handle_t #include "util/os_file.h" #include "vk_util.h" #include "vk_printers.h" #include "wrapper_checks.h" +#include #include #include #include diff --git a/src/vulkan/wrapper/wrapper_instance.c b/src/vulkan/wrapper/wrapper_instance.c index 8a18a7f87dc..0c33253f4f9 100644 --- a/src/vulkan/wrapper/wrapper_instance.c +++ b/src/vulkan/wrapper/wrapper_instance.c @@ -9,6 +9,24 @@ #include "vk_printers.h" #include "graphics_env_hooks.h" +#ifndef __ANDROID__ +#include +#define getprogname() program_invocation_short_name +#endif + +/* adrenotools stubs for non-Android builds (adrenotools is Android-only) */ +#ifndef __ANDROID__ +void *adrenotools_open_libvulkan(int dlopenMode, int featureFlags, + const char *tmpLibDir, const char *hookLibDir, const char *customDriverDir, + const char *customDriverName, const char *fileRedirectDir, + void **userMappingHandle) { + (void)dlopenMode; (void)featureFlags; (void)tmpLibDir; (void)hookLibDir; + (void)customDriverDir; (void)customDriverName; (void)fileRedirectDir; + (void)userMappingHandle; + return NULL; +} +#endif + const struct vk_instance_extension_table wrapper_instance_extensions = { .KHR_get_surface_capabilities2 = true, .EXT_surface_maintenance1 = true, diff --git a/src/vulkan/wrapper/wrapper_log.c b/src/vulkan/wrapper/wrapper_log.c index fb7a1b51dfe..6a674c06a76 100644 --- a/src/vulkan/wrapper/wrapper_log.c +++ b/src/vulkan/wrapper/wrapper_log.c @@ -6,6 +6,11 @@ #include "wrapper_entrypoints.h" #include "vk_printers.h" +#ifndef __ANDROID__ +#include +#define getprogname() program_invocation_short_name +#endif + static int __log_level; static FILE* __log_fd; static bool __log_initialized; diff --git a/src/vulkan/wrapper/wrapper_objects.h b/src/vulkan/wrapper/wrapper_objects.h index 956a049d68d..20e58886d06 100644 --- a/src/vulkan/wrapper/wrapper_objects.h +++ b/src/vulkan/wrapper/wrapper_objects.h @@ -34,6 +34,24 @@ struct wrapper_instance { VK_DEFINE_HANDLE_CASTS(wrapper_instance, vk.base, VkInstance, VK_OBJECT_TYPE_INSTANCE) +enum wrapper_gpu_vendor { + WRAPPER_GPU_VENDOR_UNKNOWN = 0, + WRAPPER_GPU_VENDOR_ADRENO_PROPRIETARY, + WRAPPER_GPU_VENDOR_ADRENO_TURNIP, + WRAPPER_GPU_VENDOR_MALI_PROPRIETARY, + WRAPPER_GPU_VENDOR_MALI_PANFROST, +}; + +struct wrapper_driver_info { + enum wrapper_gpu_vendor gpu_vendor; + uint32_t driver_version_major; + uint32_t driver_version_minor; + uint32_t driver_version_patch; + bool is_mesa; /* true for Turnip / Panfrost */ + bool is_adreno; /* true for both proprietary and Turnip */ + bool is_mali; /* true for both proprietary and Panfrost */ +}; + struct wrapper_physical_device { struct vk_physical_device vk; @@ -51,6 +69,7 @@ struct wrapper_physical_device { struct vk_features base_supported_features; struct vk_device_extension_table base_supported_extensions; struct vk_physical_device_dispatch_table dispatch_table; + struct wrapper_driver_info drv_info; }; VK_DEFINE_HANDLE_CASTS(wrapper_physical_device, vk.base, VkPhysicalDevice, diff --git a/src/vulkan/wrapper/wrapper_physical_device.c b/src/vulkan/wrapper/wrapper_physical_device.c index e1365946122..e4db9ce0642 100644 --- a/src/vulkan/wrapper/wrapper_physical_device.c +++ b/src/vulkan/wrapper/wrapper_physical_device.c @@ -1,4 +1,5 @@ #include +#include #include "wrapper_private.h" #include "wrapper_entrypoints.h" @@ -230,14 +231,81 @@ VkResult enumerate_physical_device(struct vk_instance *_instance) pdevice->driver_properties.driverName, pdevice->driver_properties.driverInfo); - if (pdevice->driver_properties.driverID == VK_DRIVER_ID_QUALCOMM_PROPRIETARY && + /* --- Identify the GPU vendor and driver --- */ + { + struct wrapper_driver_info *drv = &pdevice->drv_info; + memset(drv, 0, sizeof(*drv)); + + switch (pdevice->driver_properties.driverID) { + case VK_DRIVER_ID_QUALCOMM_PROPRIETARY: + drv->gpu_vendor = WRAPPER_GPU_VENDOR_ADRENO_PROPRIETARY; + drv->is_adreno = true; + drv->is_mesa = false; + break; + case VK_DRIVER_ID_MESA_TURNIP: + drv->gpu_vendor = WRAPPER_GPU_VENDOR_ADRENO_TURNIP; + drv->is_adreno = true; + drv->is_mesa = true; + break; + case VK_DRIVER_ID_ARM_PROPRIETARY: + drv->gpu_vendor = WRAPPER_GPU_VENDOR_MALI_PROPRIETARY; + drv->is_mali = true; + drv->is_mesa = false; + break; + case VK_DRIVER_ID_MESA_PANVK: + drv->gpu_vendor = WRAPPER_GPU_VENDOR_MALI_PANFROST; + drv->is_mali = true; + drv->is_mesa = true; + break; + default: + drv->gpu_vendor = WRAPPER_GPU_VENDOR_UNKNOWN; + break; + } + + /* Parse Mesa driver version from driverInfo string (e.g. "Mesa 26.0.4" or "Mesa 26.1.0-devel") */ + if (drv->is_mesa) { + const char *ver = pdevice->driver_properties.driverInfo; + const char *mesa_prefix = strstr(ver, "Mesa "); + if (mesa_prefix) { + mesa_prefix += 5; /* skip "Mesa " */ + sscanf(mesa_prefix, "%u.%u.%u", + &drv->driver_version_major, + &drv->driver_version_minor, + &drv->driver_version_patch); + } else { + /* Fallback: try parsing the raw driverVersion field */ + uint32_t v = pdevice->properties2.properties.driverVersion; + drv->driver_version_major = VK_VERSION_MAJOR(v); + drv->driver_version_minor = VK_VERSION_MINOR(v); + drv->driver_version_patch = VK_VERSION_PATCH(v); + } + } else if (drv->is_adreno) { + /* Qualcomm proprietary: driverVersion is packed differently */ + uint32_t v = pdevice->properties2.properties.driverVersion; + drv->driver_version_major = v >> 22; + drv->driver_version_minor = (v >> 12) & 0x3ff; + drv->driver_version_patch = v & 0xfff; + } else if (drv->is_mali) { + /* ARM proprietary: use standard Vulkan version packing */ + uint32_t v = pdevice->properties2.properties.driverVersion; + drv->driver_version_major = VK_VERSION_MAJOR(v); + drv->driver_version_minor = VK_VERSION_MINOR(v); + drv->driver_version_patch = VK_VERSION_PATCH(v); + } + + WLOG("Wrapper driver detection: vendor=%d, mesa=%d, adreno=%d, mali=%d, version=%u.%u.%u", + drv->gpu_vendor, drv->is_mesa, drv->is_adreno, drv->is_mali, + drv->driver_version_major, drv->driver_version_minor, drv->driver_version_patch); + } + + if (pdevice->drv_info.gpu_vendor == WRAPPER_GPU_VENDOR_ADRENO_PROPRIETARY && pdevice->properties2.properties.driverVersion > VK_MAKE_VERSION(512, 744, 0) && strstr(app_name, "clvk")) { /* HACK: Fixed clvk not working on qualcomm proprietary driver. */ supported_features->globalPriorityQuery = false; } - if (pdevice->driver_properties.driverID == VK_DRIVER_ID_ARM_PROPRIETARY + if (pdevice->drv_info.gpu_vendor == WRAPPER_GPU_VENDOR_MALI_PROPRIETARY && pdevice->vk.supported_extensions.EXT_extended_dynamic_state && !is_dxvk_2_plus) { WLOG("Disabling VK_EXT_extended_dynamic_state on Mali proprietary drivers"); @@ -246,11 +314,27 @@ VkResult enumerate_physical_device(struct vk_instance *_instance) pdevice->vk.supported_extensions.EXT_extended_dynamic_state3 = false; } - if (pdevice->driver_properties.driverID == VK_DRIVER_ID_QUALCOMM_PROPRIETARY) { - WLOG("Disabling VK_KHR_shader_float_controls on Qualcom proprietary drivers"); + if (pdevice->drv_info.gpu_vendor == WRAPPER_GPU_VENDOR_ADRENO_PROPRIETARY) { + WLOG("Disabling VK_KHR_shader_float_controls on Qualcomm proprietary drivers"); pdevice->vk.supported_extensions.KHR_shader_float_controls = false; } + /* Turnip (Mesa Freedreno) v26.0+ has proper float controls support */ + if (pdevice->drv_info.gpu_vendor == WRAPPER_GPU_VENDOR_ADRENO_TURNIP) { + WLOG("Mesa Turnip detected (v%u.%u.%u), keeping KHR_shader_float_controls enabled", + pdevice->drv_info.driver_version_major, + pdevice->drv_info.driver_version_minor, + pdevice->drv_info.driver_version_patch); + } + + /* Panfrost: don't disable extended_dynamic_state, it's properly supported */ + if (pdevice->drv_info.gpu_vendor == WRAPPER_GPU_VENDOR_MALI_PANFROST) { + WLOG("Mesa Panfrost detected (v%u.%u.%u)", + pdevice->drv_info.driver_version_major, + pdevice->drv_info.driver_version_minor, + pdevice->drv_info.driver_version_patch); + } + pdevice->dma_heap_fd = open("/dev/dma_heap/system", O_RDONLY); if (pdevice->dma_heap_fd < 0) pdevice->dma_heap_fd = open("/dev/ion", O_RDONLY); diff --git a/src/vulkan/wsi/wsi_common_x11.c b/src/vulkan/wsi/wsi_common_x11.c index 0a45b23670a..3de252c24dd 100644 --- a/src/vulkan/wsi/wsi_common_x11.c +++ b/src/vulkan/wsi/wsi_common_x11.c @@ -64,13 +64,23 @@ #include -// typedef struct native_handle -// { -// int version; /* sizeof(native_handle) */ -// int numFds; /* number of file-descriptors at &data[0] */ -// int numInts; /* number of ints at &data[numFds] */ -// int data[0]; /* numFds + numInts ints */ -// } native_handle_t; +/* _Nullable/_Nonnull are Clang extensions, define as empty for GCC */ +#ifndef _Nullable +#define _Nullable +#endif +#ifndef _Nonnull +#define _Nonnull +#endif + +#ifndef __ANDROID__ +typedef struct native_handle +{ + int version; /* sizeof(native_handle) */ + int numFds; /* number of file-descriptors at &data[0] */ + int numInts; /* number of ints at &data[numFds] */ + int data[0]; /* numFds + numInts ints */ +} native_handle_t; +#endif const native_handle_t* _Nullable AHardwareBuffer_getNativeHandle( const AHardwareBuffer* _Nonnull buffer);