From 88ca0818e25a633bb67dc2d6591ab30c2eb1cad5 Mon Sep 17 00:00:00 2001 From: "Nakasaka, Masato" Date: Mon, 29 Jun 2026 22:34:49 -0700 Subject: [PATCH 1/6] Removed crash guard for Intel Crash fixed from driver 32.0.101.8860 --- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index ea9191873282..2f4ce9464fbd 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -5238,8 +5238,7 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) { ggml_vk_create_pipeline(device, device->pipeline_argmax_f32, "argmax_f32", argmax_f32_len, argmax_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); ggml_vk_create_pipeline(device, device->pipeline_sum_rows_f32, "sum_rows_f32", sum_rows_f32_len, sum_rows_f32_data, "main", 2, sizeof(vk_op_sum_rows_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - // Intel Arc B390 was observed segfaulting with this shader. - if (device->subgroup_basic && device->subgroup_shuffle && device->vendor_id != VK_VENDOR_ID_INTEL) { + if (device->subgroup_basic && device->subgroup_shuffle) { int idx = 0; for (uint32_t n : {64, 128, 256, 512}) { if (device->subgroup_size <= n) { @@ -5247,8 +5246,7 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) { } ++idx; } - } else if (device->driver_id != vk::DriverId::eIntelProprietaryWindows) { - // Disabled on Intel Windows due to a driver bug: https://github.com/ggml-org/llama.cpp/pull/23964#issuecomment-4598226147 + } else { int idx = 0; for (uint32_t n : {64, 128, 256, 512}) { const uint32_t block_size = std::min(device->subgroup_size, n); From 1c32a6e8201a73e833d173bc816a89e7ad4d9ae7 Mon Sep 17 00:00:00 2001 From: "Nakasaka, Masato" Date: Mon, 13 Jul 2026 02:08:50 -0700 Subject: [PATCH 2/6] Added driver version check for windows --- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 87 +++++++++++++++++++++++----- 1 file changed, 74 insertions(+), 13 deletions(-) diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index 5a7b4d31677d..8f646fedc93f 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -49,6 +49,7 @@ typedef struct VkPhysicalDeviceCooperativeMatrixDecodeVectorFeaturesNV { #endif #include +#include #include #include #include @@ -132,6 +133,60 @@ typedef struct VkPhysicalDeviceShaderMixedFloatDotProductFeaturesVALVE { #define CEIL_DIV(M, N) (((M) / (N)) + (((M) % (N)) != 0)) static bool is_pow2(uint32_t x) { return x > 1 && (x & (x-1)) == 0; } +static bool ggml_vk_parse_intel_windows_driver_version(const std::string & driver_info, int & major, int & minor) { +#if defined(_WIN32) + // Require exactly one separator and non-empty major/minor components. + const size_t dot = driver_info.find('.'); + if (dot == std::string::npos || dot == 0 || dot + 1 >= driver_info.size()) { + return false; + } + + // Reject inputs with more than one '.' to keep strict xxx.yyyy parsing. + if (driver_info.find('.', dot + 1) != std::string::npos) { + return false; + } + + const char * major_begin = driver_info.data(); + const char * major_end = major_begin + dot; + const char * minor_begin = major_end + 1; + const char * minor_end = driver_info.data() + driver_info.size(); + + auto major_result = std::from_chars(major_begin, major_end, major); + if (major_result.ec != std::errc() || major_result.ptr != major_end || major < 0) { + return false; + } + + auto minor_result = std::from_chars(minor_begin, minor_end, minor); + if (minor_result.ec != std::errc() || minor_result.ptr != minor_end || minor < 0) { + return false; + } + + return true; +#else + (void) driver_info; + (void) major; + (void) minor; + return false; +#endif +} + +static bool ggml_vk_intel_windows_driver_newer_than(const std::string & driver_info, int threshold_major, int threshold_minor) { +#if defined(_WIN32) + int major = 0; + int minor = 0; + if (!ggml_vk_parse_intel_windows_driver_version(driver_info, major, minor)) { + return false; + } + + return major > threshold_major || (major == threshold_major && minor >= threshold_minor); +#else + (void) driver_info; + (void) threshold_major; + (void) threshold_minor; + return true; +#endif +} + #define VK_VENDOR_ID_AMD 0x1002 #define VK_VENDOR_ID_APPLE 0x106b #define VK_VENDOR_ID_INTEL 0x8086 @@ -683,6 +738,7 @@ struct vk_device_struct { vk::Device device; uint32_t vendor_id; vk::DriverId driver_id; + std::string driver_info; vk_device_architecture architecture; vk_queue compute_queue; vk_queue transfer_queue; @@ -5351,20 +5407,24 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) { ggml_vk_create_pipeline(device, device->pipeline_argmax_f32, "argmax_f32", argmax_f32_len, argmax_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); ggml_vk_create_pipeline(device, device->pipeline_sum_rows_f32, "sum_rows_f32", sum_rows_f32_len, sum_rows_f32_data, "main", 2, sizeof(vk_op_sum_rows_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); - if (device->subgroup_basic && device->subgroup_shuffle) { - int idx = 0; - for (uint32_t n : {64, 128, 256, 512}) { - if (device->subgroup_size <= n) { - ggml_vk_create_pipeline(device, device->pipeline_fwht_f32[idx], "fwht_f32", fwht_f32_len, fwht_f32_data, "main", 2, sizeof(vk_op_fwht_push_constants), {1, 1, 1}, { device->subgroup_size, n }, 1, true, true, device->subgroup_size); + const bool can_use_fwht = device->driver_id != vk::DriverId::eIntelProprietaryWindows || + ggml_vk_intel_windows_driver_newer_than(device->driver_info, 101, 8860); + if (can_use_fwht) { + if (device->subgroup_basic && device->subgroup_shuffle) { + int idx = 0; + for (uint32_t n : {64, 128, 256, 512}) { + if (device->subgroup_size <= n) { + ggml_vk_create_pipeline(device, device->pipeline_fwht_f32[idx], "fwht_f32", fwht_f32_len, fwht_f32_data, "main", 2, sizeof(vk_op_fwht_push_constants), {1, 1, 1}, { device->subgroup_size, n }, 1, true, true, device->subgroup_size); + } + ++idx; + } + } else { + int idx = 0; + for (uint32_t n : {64, 128, 256, 512}) { + const uint32_t block_size = std::min(device->subgroup_size, n); + ggml_vk_create_pipeline(device, device->pipeline_fwht_f32[idx], "fwht_shmem_f32", fwht_shmem_f32_len, fwht_shmem_f32_data, "main", 2, sizeof(vk_op_fwht_push_constants), {1, 1, 1}, { block_size, n }, 1); + ++idx; } - ++idx; - } - } else { - int idx = 0; - for (uint32_t n : {64, 128, 256, 512}) { - const uint32_t block_size = std::min(device->subgroup_size, n); - ggml_vk_create_pipeline(device, device->pipeline_fwht_f32[idx], "fwht_shmem_f32", fwht_shmem_f32_len, fwht_shmem_f32_data, "main", 2, sizeof(vk_op_fwht_push_constants), {1, 1, 1}, { block_size, n }, 1); - ++idx; } } @@ -5912,6 +5972,7 @@ static vk_device ggml_vk_get_device(size_t idx) { device->properties = props2.properties; device->vendor_id = device->properties.vendorID; device->driver_id = driver_props.driverID; + device->driver_info = driver_props.driverInfo.data(); if (device->driver_id == vk::DriverId::eMoltenvk) { // Disable external_memory_host until https://github.com/KhronosGroup/MoltenVK/pull/2622 From ffdce7d6f5ddd5ff243924b06e9d6d12b801ef08 Mon Sep 17 00:00:00 2001 From: "Nakasaka, Masato" Date: Tue, 14 Jul 2026 00:25:53 -0700 Subject: [PATCH 3/6] Change to convert from driverVersion rather than string --- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 55 ++++------------------------ 1 file changed, 7 insertions(+), 48 deletions(-) diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index 8f646fedc93f..63dce18d987c 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -49,7 +49,6 @@ typedef struct VkPhysicalDeviceCooperativeMatrixDecodeVectorFeaturesNV { #endif #include -#include #include #include #include @@ -133,54 +132,15 @@ typedef struct VkPhysicalDeviceShaderMixedFloatDotProductFeaturesVALVE { #define CEIL_DIV(M, N) (((M) / (N)) + (((M) % (N)) != 0)) static bool is_pow2(uint32_t x) { return x > 1 && (x & (x-1)) == 0; } -static bool ggml_vk_parse_intel_windows_driver_version(const std::string & driver_info, int & major, int & minor) { +static bool ggml_vk_intel_windows_driver_equals_or_newer_than(uint32_t driver_version, int threshold_major, int threshold_minor) { #if defined(_WIN32) - // Require exactly one separator and non-empty major/minor components. - const size_t dot = driver_info.find('.'); - if (dot == std::string::npos || dot == 0 || dot + 1 >= driver_info.size()) { - return false; - } - - // Reject inputs with more than one '.' to keep strict xxx.yyyy parsing. - if (driver_info.find('.', dot + 1) != std::string::npos) { - return false; - } - - const char * major_begin = driver_info.data(); - const char * major_end = major_begin + dot; - const char * minor_begin = major_end + 1; - const char * minor_end = driver_info.data() + driver_info.size(); - - auto major_result = std::from_chars(major_begin, major_end, major); - if (major_result.ec != std::errc() || major_result.ptr != major_end || major < 0) { - return false; - } - - auto minor_result = std::from_chars(minor_begin, minor_end, minor); - if (minor_result.ec != std::errc() || minor_result.ptr != minor_end || minor < 0) { - return false; - } - - return true; -#else - (void) driver_info; - (void) major; - (void) minor; - return false; -#endif -} - -static bool ggml_vk_intel_windows_driver_newer_than(const std::string & driver_info, int threshold_major, int threshold_minor) { -#if defined(_WIN32) - int major = 0; - int minor = 0; - if (!ggml_vk_parse_intel_windows_driver_version(driver_info, major, minor)) { - return false; - } + // Intel Windows encodes xxx.yyyy as [31:14].[13:0]. + const int major = int(driver_version >> 14); + const int minor = int(driver_version & 0x3fff); return major > threshold_major || (major == threshold_major && minor >= threshold_minor); #else - (void) driver_info; + (void) driver_version; (void) threshold_major; (void) threshold_minor; return true; @@ -738,7 +698,6 @@ struct vk_device_struct { vk::Device device; uint32_t vendor_id; vk::DriverId driver_id; - std::string driver_info; vk_device_architecture architecture; vk_queue compute_queue; vk_queue transfer_queue; @@ -5407,8 +5366,9 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) { ggml_vk_create_pipeline(device, device->pipeline_argmax_f32, "argmax_f32", argmax_f32_len, argmax_f32_data, "main", 2, sizeof(vk_op_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); ggml_vk_create_pipeline(device, device->pipeline_sum_rows_f32, "sum_rows_f32", sum_rows_f32_len, sum_rows_f32_data, "main", 2, sizeof(vk_op_sum_rows_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); + // Intel Windows driver older than 32.0.101.8860 will crash when using fwht kernels on Xe2+ GPUS so we gate that here const bool can_use_fwht = device->driver_id != vk::DriverId::eIntelProprietaryWindows || - ggml_vk_intel_windows_driver_newer_than(device->driver_info, 101, 8860); + (device->architecture == vk_device_architecture::INTEL_XE2 && ggml_vk_intel_windows_driver_equals_or_newer_than(device->properties.driverVersion, 101, 8860)); if (can_use_fwht) { if (device->subgroup_basic && device->subgroup_shuffle) { int idx = 0; @@ -5972,7 +5932,6 @@ static vk_device ggml_vk_get_device(size_t idx) { device->properties = props2.properties; device->vendor_id = device->properties.vendorID; device->driver_id = driver_props.driverID; - device->driver_info = driver_props.driverInfo.data(); if (device->driver_id == vk::DriverId::eMoltenvk) { // Disable external_memory_host until https://github.com/KhronosGroup/MoltenVK/pull/2622 From 1cb2b48a5b56f1a8da0a3d249a651e77ee226f6c Mon Sep 17 00:00:00 2001 From: "Nakasaka, Masato" Date: Tue, 14 Jul 2026 00:34:03 -0700 Subject: [PATCH 4/6] No need to use signed --- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index 63dce18d987c..16d5ab1343ec 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -132,11 +132,11 @@ typedef struct VkPhysicalDeviceShaderMixedFloatDotProductFeaturesVALVE { #define CEIL_DIV(M, N) (((M) / (N)) + (((M) % (N)) != 0)) static bool is_pow2(uint32_t x) { return x > 1 && (x & (x-1)) == 0; } -static bool ggml_vk_intel_windows_driver_equals_or_newer_than(uint32_t driver_version, int threshold_major, int threshold_minor) { +static bool ggml_vk_intel_windows_driver_equals_or_newer_than(uint32_t driver_version, uint32_t threshold_major, uint32_t threshold_minor) { #if defined(_WIN32) // Intel Windows encodes xxx.yyyy as [31:14].[13:0]. - const int major = int(driver_version >> 14); - const int minor = int(driver_version & 0x3fff); + const uint32_t major = driver_version >> 14; + const uint32_t minor = driver_version & 0x3fff; return major > threshold_major || (major == threshold_major && minor >= threshold_minor); #else From 6736cd3596f18025f80e9afe9e9f034b8b1755d4 Mon Sep 17 00:00:00 2001 From: "Nakasaka, Masato" Date: Tue, 14 Jul 2026 00:42:08 -0700 Subject: [PATCH 5/6] Refactor --- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 34 +++++++++++++--------------- 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index 16d5ab1343ec..e3ee54d8cb0a 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -140,9 +140,9 @@ static bool ggml_vk_intel_windows_driver_equals_or_newer_than(uint32_t driver_ve return major > threshold_major || (major == threshold_major && minor >= threshold_minor); #else - (void) driver_version; - (void) threshold_major; - (void) threshold_minor; + GGML_UNUSED(driver_version); + GGML_UNUSED(threshold_major); + GGML_UNUSED(threshold_minor); return true; #endif } @@ -5369,22 +5369,20 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) { // Intel Windows driver older than 32.0.101.8860 will crash when using fwht kernels on Xe2+ GPUS so we gate that here const bool can_use_fwht = device->driver_id != vk::DriverId::eIntelProprietaryWindows || (device->architecture == vk_device_architecture::INTEL_XE2 && ggml_vk_intel_windows_driver_equals_or_newer_than(device->properties.driverVersion, 101, 8860)); - if (can_use_fwht) { - if (device->subgroup_basic && device->subgroup_shuffle) { - int idx = 0; - for (uint32_t n : {64, 128, 256, 512}) { - if (device->subgroup_size <= n) { - ggml_vk_create_pipeline(device, device->pipeline_fwht_f32[idx], "fwht_f32", fwht_f32_len, fwht_f32_data, "main", 2, sizeof(vk_op_fwht_push_constants), {1, 1, 1}, { device->subgroup_size, n }, 1, true, true, device->subgroup_size); - } - ++idx; - } - } else { - int idx = 0; - for (uint32_t n : {64, 128, 256, 512}) { - const uint32_t block_size = std::min(device->subgroup_size, n); - ggml_vk_create_pipeline(device, device->pipeline_fwht_f32[idx], "fwht_shmem_f32", fwht_shmem_f32_len, fwht_shmem_f32_data, "main", 2, sizeof(vk_op_fwht_push_constants), {1, 1, 1}, { block_size, n }, 1); - ++idx; + if (can_use_fwht && device->subgroup_basic && device->subgroup_shuffle) { + int idx = 0; + for (uint32_t n : {64, 128, 256, 512}) { + if (device->subgroup_size <= n) { + ggml_vk_create_pipeline(device, device->pipeline_fwht_f32[idx], "fwht_f32", fwht_f32_len, fwht_f32_data, "main", 2, sizeof(vk_op_fwht_push_constants), {1, 1, 1}, { device->subgroup_size, n }, 1, true, true, device->subgroup_size); } + ++idx; + } + } else if (can_use_fwht) { + int idx = 0; + for (uint32_t n : {64, 128, 256, 512}) { + const uint32_t block_size = std::min(device->subgroup_size, n); + ggml_vk_create_pipeline(device, device->pipeline_fwht_f32[idx], "fwht_shmem_f32", fwht_shmem_f32_len, fwht_shmem_f32_data, "main", 2, sizeof(vk_op_fwht_push_constants), {1, 1, 1}, { block_size, n }, 1); + ++idx; } } From df5b98821f16c9e4d7039266779a2c78845e2e8b Mon Sep 17 00:00:00 2001 From: "Nakasaka, Masato" Date: Tue, 14 Jul 2026 01:39:50 -0700 Subject: [PATCH 6/6] allow GPU other than Xe2+ --- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index e3ee54d8cb0a..25a723e626e0 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -5368,6 +5368,7 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) { ggml_vk_create_pipeline(device, device->pipeline_sum_rows_f32, "sum_rows_f32", sum_rows_f32_len, sum_rows_f32_data, "main", 2, sizeof(vk_op_sum_rows_push_constants), {1, 1, 1}, { device->subgroup_size }, 1); // Intel Windows driver older than 32.0.101.8860 will crash when using fwht kernels on Xe2+ GPUS so we gate that here const bool can_use_fwht = device->driver_id != vk::DriverId::eIntelProprietaryWindows || + device->architecture != vk_device_architecture::INTEL_XE2 || (device->architecture == vk_device_architecture::INTEL_XE2 && ggml_vk_intel_windows_driver_equals_or_newer_than(device->properties.driverVersion, 101, 8860)); if (can_use_fwht && device->subgroup_basic && device->subgroup_shuffle) { int idx = 0;