@@ -691,6 +691,7 @@ struct vk_device_struct {
691691 uint32_t coopmat_int_k;
692692
693693 bool coopmat2;
694+ bool coopmat2_bf16_support {};
694695 bool coopmat2_decode_vector;
695696
696697 bool pipeline_executable_properties_support {};
@@ -3139,7 +3140,7 @@ struct vk_fa_tuning_params {
31393140};
31403141
31413142static bool ggml_vk_flash_attn_scalar_shmem_support(const vk_device& device, const vk_fa_tuning_params& params, uint32_t hsk, uint32_t hsv, bool f32acc, ggml_type k_type, ggml_type v_type);
3142- static bool ggml_vk_flash_attn_coopmat_shmem_support(const vk_device& device, const vk_fa_tuning_params& params, uint32_t hsk, uint32_t hsv, bool f32acc);
3143+ static bool ggml_vk_flash_attn_coopmat_shmem_support(const vk_device& device, const vk_fa_tuning_params& params, uint32_t hsk, uint32_t hsv, bool f32acc, ggml_type k_type = GGML_TYPE_F16 );
31433144
31443145static vk_fa_tuning_params get_fa_tuning_params_scalar(const vk_device& device, uint32_t hsk, uint32_t hsv, uint32_t n_rows, uint32_t n_kv, ggml_type k_type, ggml_type v_type, bool f32acc) {
31453146
@@ -3279,6 +3280,13 @@ static vk_fa_tuning_params get_fa_tuning_params(const vk_device& device, uint32_
32793280 FaCodePath path = device->coopmat2 ? FA_COOPMAT2 :
32803281 device->coopmat1_fa_support ? FA_COOPMAT1 : FA_SCALAR;
32813282
3283+ if (path == FA_COOPMAT2 && k_type == GGML_TYPE_BF16 && !device->coopmat2_bf16_support) {
3284+ path = FA_COOPMAT1;
3285+ }
3286+ if (path == FA_COOPMAT1 && k_type == GGML_TYPE_BF16 && !device->coopmat_bf16_support) {
3287+ path = FA_SCALAR;
3288+ }
3289+
32823290 if (path == FA_COOPMAT1 && device->architecture == vk_device_architecture::NVIDIA_TURING) {
32833291 // Nvidia compiler bug, see https://github.com/ggml-org/llama.cpp/pull/19075#issuecomment-3820716090
32843292 path = FA_SCALAR;
@@ -3288,7 +3296,7 @@ static vk_fa_tuning_params get_fa_tuning_params(const vk_device& device, uint32_
32883296 bool shape_ok = (f32acc && device->coopmat_support_16x16x16_f32acc) ||
32893297 (!f32acc && device->coopmat_support_16x16x16_f16acc);
32903298 const vk_fa_tuning_params params = get_fa_tuning_params_coopmat1(device, hsk, hsv, n_rows, n_kv, k_type, v_type, f32acc);
3291- bool shmem_ok = ggml_vk_flash_attn_coopmat_shmem_support(device, params, hsk, hsv, f32acc);
3299+ bool shmem_ok = ggml_vk_flash_attn_coopmat_shmem_support(device, params, hsk, hsv, f32acc, k_type );
32923300
32933301 if (!shape_ok || !shmem_ok) {
32943302 path = FA_SCALAR;
@@ -3334,8 +3342,8 @@ static vk_fa_pipeline_state get_fa_pipeline_state(const vk_device& device, const
33343342
33353343static std::vector<uint32_t> get_fa_spec_constants(const vk_fa_pipeline_state& state) {
33363344 const auto fa_block_bytes = [](ggml_type t) -> uint32_t {
3337- // decodeBufF32 uses a block of vec4s for a better memory access pattern.
3338- return t == GGML_TYPE_F32 ? 16u : (uint32_t) ggml_type_size(t);
3345+ if (t == GGML_TYPE_F32) return 16u;
3346+ return (uint32_t) ggml_type_size(t);
33393347 };
33403348 return {
33413349 /* 0 WorkGroupSize */ state.workgroup_size,
@@ -3849,10 +3857,16 @@ static void ggml_vk_load_shaders(vk_device& device) {
38493857 const uint32_t fa_sgs = fa.first.subgroup_size;
38503858 const bool fa_ds = fa.first.subgroup_size == 0;
38513859
3860+ const bool bf16_kv = fa.first.k_type == GGML_TYPE_BF16;
38523861 const bool use_mmq = ggml_vk_fa_scalar_uses_mmq(device, fa.first.k_type);
38533862 const void * spv_data = nullptr;
38543863 size_t spv_size = 0;
3855- if (use_mmq) {
3864+ const char *name = nullptr;
3865+ if (bf16_kv) {
3866+ spv_data = flash_attn_f32_f16_fp32_data;
3867+ spv_size = flash_attn_f32_f16_fp32_len;
3868+ name = aligned ? "flash_attn_f32_bf16_aligned" : "flash_attn_f32_bf16";
3869+ } else if (use_mmq) {
38563870#if defined(GGML_VULKAN_INTEGER_DOT_GLSLC_SUPPORT)
38573871 if (device->fp16) {
38583872 if (f32acc) { spv_data = flash_attn_f32_f16_int8_data; spv_size = flash_attn_f32_f16_int8_len; }
@@ -3862,6 +3876,7 @@ static void ggml_vk_load_shaders(vk_device& device) {
38623876 spv_size = flash_attn_f32_f16_fp32_int8_len;
38633877 }
38643878#endif
3879+ name = aligned ? "flash_attn_f32_f16_aligned" : "flash_attn_f32_f16";
38653880 } else {
38663881 if (device->fp16) {
38673882 if (f32acc) { spv_data = flash_attn_f32_f16_data; spv_size = flash_attn_f32_f16_len; }
@@ -3870,8 +3885,8 @@ static void ggml_vk_load_shaders(vk_device& device) {
38703885 spv_data = flash_attn_f32_f16_fp32_data;
38713886 spv_size = flash_attn_f32_f16_fp32_len;
38723887 }
3888+ name = aligned ? "flash_attn_f32_f16_aligned" : "flash_attn_f32_f16";
38733889 }
3874- const char *name = aligned ? "flash_attn_f32_f16_aligned" : "flash_attn_f32_f16";
38753890 ggml_vk_create_pipeline(device, fa.second, name, spv_size, spv_data, "main", 7,
38763891 sizeof(vk_flash_attn_push_constants), {Br, 1, 1},
38773892 get_fa_spec_constants(fa.first), aligned ? Bc : 1, true,
@@ -3889,11 +3904,25 @@ static void ggml_vk_load_shaders(vk_device& device) {
38893904 const uint32_t fa_sgs = fa.first.subgroup_size;
38903905 const bool fa_ds = fa.first.subgroup_size == 0;
38913906
3907+ const bool bf16_kv = fa.first.k_type == GGML_TYPE_BF16;
3908+
38923909 const void * spv_data;
38933910 size_t spv_size;
3894- if (f32acc) { spv_data = flash_attn_f32_f16_cm1_data; spv_size = flash_attn_f32_f16_cm1_len; }
3895- else { spv_data = flash_attn_f32_f16_f16acc_cm1_data; spv_size = flash_attn_f32_f16_f16acc_cm1_len; }
3896- const char *name = aligned ? "flash_attn_f32_f16_aligned_cm1" : "flash_attn_f32_f16_cm1";
3911+ const char *name;
3912+ if (bf16_kv) {
3913+ #if defined(VK_KHR_shader_bfloat16) && defined(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT)
3914+ if (!device->coopmat_bf16_support) continue;
3915+ spv_data = flash_attn_f32_f16_bf16_cm1_data;
3916+ spv_size = flash_attn_f32_f16_bf16_cm1_len;
3917+ name = aligned ? "flash_attn_f32_bf16_aligned_cm1" : "flash_attn_f32_bf16_cm1";
3918+ #else
3919+ continue;
3920+ #endif
3921+ } else {
3922+ if (f32acc) { spv_data = flash_attn_f32_f16_cm1_data; spv_size = flash_attn_f32_f16_cm1_len; }
3923+ else { spv_data = flash_attn_f32_f16_f16acc_cm1_data; spv_size = flash_attn_f32_f16_f16acc_cm1_len; }
3924+ name = aligned ? "flash_attn_f32_f16_aligned_cm1" : "flash_attn_f32_f16_cm1";
3925+ }
38973926 ggml_vk_create_pipeline(device, fa.second, name, spv_size, spv_data, "main", 7,
38983927 sizeof(vk_flash_attn_push_constants), {Br, 1, 1},
38993928 get_fa_spec_constants(fa.first), aligned ? Bc : 1, true,
@@ -3911,10 +3940,20 @@ static void ggml_vk_load_shaders(vk_device& device) {
39113940 const bool aligned = fa.first.aligned;
39123941 const bool f32acc = fa.first.f32acc;
39133942
3943+ const bool bf16_kv = fa.first.k_type == GGML_TYPE_BF16;
39143944 const void * spv_data;
39153945 size_t spv_size;
39163946 const char * name;
3917- if (aligned) {
3947+ if (bf16_kv) {
3948+ #if defined(VK_KHR_shader_bfloat16) && defined(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT)
3949+ if (!device->coopmat2_bf16_support) continue;
3950+ spv_data = flash_attn_f32_f16_bf16_cm2_data;
3951+ spv_size = flash_attn_f32_f16_bf16_cm2_len;
3952+ name = aligned ? "flash_attn_f32_bf16_aligned_cm2" : "flash_attn_f32_bf16_cm2";
3953+ #else
3954+ continue;
3955+ #endif
3956+ } else if (aligned) {
39183957 if (f32acc) { spv_data = flash_attn_f32_f16_cm2_data; spv_size = flash_attn_f32_f16_cm2_len; name = "flash_attn_f32_f16_aligned_f32acc_cm2"; }
39193958 else { spv_data = flash_attn_f32_f16_f16acc_cm2_data; spv_size = flash_attn_f32_f16_f16acc_cm2_len; name = "flash_attn_f32_f16_aligned_f16acc_cm2"; }
39203959 } else {
@@ -5784,46 +5823,72 @@ static vk_device ggml_vk_get_device(size_t idx) {
57845823 found_fp16_256 = false,
57855824 found_fp32_128 = false,
57865825 found_fp32_256 = false;
5826+ bool found_bf16_128 = false,
5827+ found_bf16_256 = false;
57875828 // need to support fp16*fp16 with fp16/fp32 accumulator, for workgroupsize 128
57885829 // with 32x16x16 and 256 with 32x32x16.
57895830 for (auto &prop : flexible_dimensions) {
57905831 if (prop.saturatingAccumulation == VK_FALSE &&
5791- prop.scope == VK_SCOPE_WORKGROUP_KHR &&
5792- prop.AType == VK_COMPONENT_TYPE_FLOAT16_KHR &&
5793- prop.BType == VK_COMPONENT_TYPE_FLOAT16_KHR) {
5794-
5795- if (prop.workgroupInvocations == 128 &&
5796- prop.MGranularity <= 32 &&
5797- prop.NGranularity <= 16 &&
5798- prop.KGranularity <= 16) {
5799- if (prop.CType == VK_COMPONENT_TYPE_FLOAT16_KHR &&
5800- prop.ResultType == VK_COMPONENT_TYPE_FLOAT16_KHR) {
5801- found_fp16_128 = true;
5832+ prop.scope == VK_SCOPE_WORKGROUP_KHR) {
5833+
5834+ if (prop.AType == VK_COMPONENT_TYPE_FLOAT16_KHR &&
5835+ prop.BType == VK_COMPONENT_TYPE_FLOAT16_KHR) {
5836+
5837+ if (prop.workgroupInvocations == 128 &&
5838+ prop.MGranularity <= 32 &&
5839+ prop.NGranularity <= 16 &&
5840+ prop.KGranularity <= 16) {
5841+ if (prop.CType == VK_COMPONENT_TYPE_FLOAT16_KHR &&
5842+ prop.ResultType == VK_COMPONENT_TYPE_FLOAT16_KHR) {
5843+ found_fp16_128 = true;
5844+ }
5845+ if (prop.CType == VK_COMPONENT_TYPE_FLOAT32_KHR &&
5846+ prop.ResultType == VK_COMPONENT_TYPE_FLOAT32_KHR) {
5847+ found_fp32_128 = true;
5848+ }
58025849 }
5803- if (prop.CType == VK_COMPONENT_TYPE_FLOAT32_KHR &&
5804- prop.ResultType == VK_COMPONENT_TYPE_FLOAT32_KHR) {
5805- found_fp32_128 = true;
5850+ if (prop.workgroupInvocations == 256 &&
5851+ prop.MGranularity <= 32 &&
5852+ prop.NGranularity <= 32 &&
5853+ prop.KGranularity <= 16) {
5854+ if (prop.CType == VK_COMPONENT_TYPE_FLOAT16_KHR &&
5855+ prop.ResultType == VK_COMPONENT_TYPE_FLOAT16_KHR) {
5856+ found_fp16_256 = true;
5857+ }
5858+ if (prop.CType == VK_COMPONENT_TYPE_FLOAT32_KHR &&
5859+ prop.ResultType == VK_COMPONENT_TYPE_FLOAT32_KHR) {
5860+ found_fp32_256 = true;
5861+ }
58065862 }
58075863 }
5808- if (prop.workgroupInvocations == 256 &&
5809- prop.MGranularity <= 32 &&
5810- prop.NGranularity <= 32 &&
5811- prop.KGranularity <= 16) {
5812- if (prop.CType == VK_COMPONENT_TYPE_FLOAT16_KHR &&
5813- prop.ResultType == VK_COMPONENT_TYPE_FLOAT16_KHR) {
5814- found_fp16_256 = true;
5864+
5865+ #if defined(VK_KHR_shader_bfloat16) && defined(GGML_VULKAN_BFLOAT16_GLSLC_SUPPORT)
5866+ if (prop.AType == VK_COMPONENT_TYPE_BFLOAT16_KHR &&
5867+ prop.BType == VK_COMPONENT_TYPE_BFLOAT16_KHR &&
5868+ prop.CType == VK_COMPONENT_TYPE_FLOAT32_KHR &&
5869+ prop.ResultType == VK_COMPONENT_TYPE_FLOAT32_KHR) {
5870+
5871+ if (prop.workgroupInvocations == 128 &&
5872+ prop.MGranularity <= 32 &&
5873+ prop.NGranularity <= 16 &&
5874+ prop.KGranularity <= 16) {
5875+ found_bf16_128 = true;
58155876 }
5816- if (prop.CType == VK_COMPONENT_TYPE_FLOAT32_KHR &&
5817- prop.ResultType == VK_COMPONENT_TYPE_FLOAT32_KHR) {
5818- found_fp32_256 = true;
5877+ if (prop.workgroupInvocations == 256 &&
5878+ prop.MGranularity <= 32 &&
5879+ prop.NGranularity <= 32 &&
5880+ prop.KGranularity <= 16) {
5881+ found_bf16_256 = true;
58195882 }
58205883 }
5884+ #endif
58215885 }
58225886 }
58235887 if (found_fp16_128 && found_fp16_256 &&
58245888 found_fp32_128 && found_fp32_256 &&
58255889 coopmat2_props.cooperativeMatrixFlexibleDimensionsMaxDimension >= 512) {
58265890 device->coopmat2 = true;
5891+ device->coopmat2_bf16_support = found_bf16_128 && found_bf16_256;
58275892 device->coopmat2_decode_vector = coopmat2_decode_vector_support && coopmat2_decode_vector_features.cooperativeMatrixDecodeVector;
58285893 }
58295894 }
@@ -9448,7 +9513,8 @@ static bool ggml_vk_flash_attn_scalar_shmem_support(const vk_device& device, con
94489513 const uint32_t Br = params.block_rows;
94499514 const uint32_t Bc = params.block_cols;
94509515
9451- const uint32_t float_type_size = device->fp16 ? sizeof(ggml_fp16_t) : sizeof(float);
9516+ // BF16 uses the fp32 shader (FLOAT_TYPE=float)
9517+ const uint32_t float_type_size = (device->fp16 && k_type != GGML_TYPE_BF16) ? sizeof(ggml_fp16_t) : sizeof(float);
94529518
94539519 const bool mmq = ggml_vk_fa_scalar_uses_mmq(device, k_type);
94549520
@@ -9489,7 +9555,7 @@ static bool ggml_vk_flash_attn_scalar_shmem_support(const vk_device& device, con
94899555 return supported;
94909556}
94919557
9492- static bool ggml_vk_flash_attn_coopmat_shmem_support(const vk_device& device, const vk_fa_tuning_params& params, uint32_t hsk, uint32_t hsv, bool f32acc) {
9558+ static bool ggml_vk_flash_attn_coopmat_shmem_support(const vk_device& device, const vk_fa_tuning_params& params, uint32_t hsk, uint32_t hsv, bool f32acc, ggml_type k_type ) {
94939559 // Needs to be kept up to date on shader changes
94949560 const uint32_t Br = params.block_rows;
94959561 const uint32_t Bc = params.block_cols;
@@ -9519,8 +9585,10 @@ static bool ggml_vk_flash_attn_coopmat_shmem_support(const vk_device& device, co
95199585 const uint32_t vsh_stride = MatBc / 4 * row_split;
95209586 const uint32_t ksh = ((kvshstride >= vsh_stride) ? (Bc * kvshstride) : (Bc * vsh_stride)) * f16vec4;
95219587
9588+ // BF16 PVMat accumulator is f32 (no bf16 accumulator support), so pvsh is vec4 (16 bytes)
9589+ const uint32_t pvsh_elem_size = (k_type == GGML_TYPE_BF16) ? 16u : f16vec4;
95229590 const uint32_t osh_stride = params.row_split * MatBr / 4;
9523- const uint32_t pvsh = MatBc * osh_stride * f16vec4 ;
9591+ const uint32_t pvsh = MatBc * osh_stride * pvsh_elem_size ;
95249592
95259593 const uint32_t slope = Br * acctype;
95269594
@@ -9589,7 +9657,7 @@ static void ggml_vk_flash_attn(ggml_backend_vk_context * ctx, vk_context& subctx
95899657 uint32_t workgroups_y = (uint32_t)neq2;
95909658 uint32_t workgroups_z = (uint32_t)neq3;
95919659
9592- const bool f32acc = !ctx->device->fp16 || dst->op_params[3] == GGML_PREC_F32;
9660+ const bool f32acc = !ctx->device->fp16 || dst->op_params[3] == GGML_PREC_F32 || k->type == GGML_TYPE_BF16 ;
95939661
95949662 // For scalar/coopmat1 FA, we can use the "large" size to accommodate qga.
95959663 // For coopmat2 FA, we always use the small size (which is still pretty large for gqa).
@@ -16400,6 +16468,7 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
1640016468 switch (t) {
1640116469 case GGML_TYPE_F32:
1640216470 case GGML_TYPE_F16:
16471+ case GGML_TYPE_BF16:
1640316472 case GGML_TYPE_Q8_0:
1640416473 case GGML_TYPE_Q5_1:
1640516474 case GGML_TYPE_Q5_0:
@@ -16415,6 +16484,9 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
1641516484 if (!fa_kv_ok(op->src[1]->type) || !fa_kv_ok(op->src[2]->type)) {
1641616485 return false;
1641716486 }
16487+ if ((op->src[1]->type == GGML_TYPE_BF16) != (op->src[2]->type == GGML_TYPE_BF16)) {
16488+ return false;
16489+ }
1641816490 if (!coopmat2 && !(device->subgroup_shuffle && device->subgroup_vote)) {
1641916491 // scalar/coopmat1 FA uses subgroupShuffle/subgroupAll
1642016492 return false;
0 commit comments