@@ -723,6 +723,7 @@ struct vk_device_struct {
723723 bool uma;
724724 bool prefer_host_memory;
725725 bool float_controls_rte_fp16;
726+ bool float_controls_denorm_preserve_fp16;
726727 bool subgroup_basic;
727728 bool subgroup_arithmetic;
728729 bool subgroup_shuffle;
@@ -868,8 +869,9 @@ struct vk_device_struct {
868869 vk_pipeline pipeline_cpy_f32_quant[GGML_TYPE_COUNT];
869870 vk_pipeline pipeline_cpy_quant_f32[GGML_TYPE_COUNT];
870871 vk_pipeline pipeline_cpy_transpose_16, pipeline_cpy_transpose_32;
871- vk_pipeline pipeline_set_rows_i32[GGML_TYPE_COUNT];
872- vk_pipeline pipeline_set_rows_i64[GGML_TYPE_COUNT];
872+ // [src0 0=fp32,1=fp16][dst]
873+ vk_pipeline pipeline_set_rows_i32[2][GGML_TYPE_COUNT];
874+ vk_pipeline pipeline_set_rows_i64[2][GGML_TYPE_COUNT];
873875 vk_pipeline pipeline_norm_f32;
874876 vk_pipeline pipeline_group_norm_f32;
875877 vk_pipeline pipeline_rms_norm_f32;
@@ -2595,10 +2597,10 @@ static void ggml_vk_create_pipeline_func(vk_device& device, vk_pipeline& pipelin
25952597
25962598 vk::ShaderModuleCreateInfo shader_module_create_info({}, spv_size, reinterpret_cast<const uint32_t *>(spv_data));
25972599
2598- // Patch SPIR-V to enable RTE rounding for FP16 , avoiding the need for
2599- // separate shader variants compiled with -DRTE16 .
2600+ // Patch SPIR-V to enable supported FP16 float controls , avoiding the need
2601+ // for separate shader variants.
26002602 std::vector<uint32_t> spirv;
2601- if (device->float_controls_rte_fp16) {
2603+ if (device->float_controls_rte_fp16 || device->float_controls_denorm_preserve_fp16 ) {
26022604 const uint32_t* spv_words = reinterpret_cast<const uint32_t *>(spv_data);
26032605 size_t word_count = spv_size / sizeof(uint32_t);
26042606 spirv.assign(spv_words, spv_words + word_count);
@@ -2635,9 +2637,17 @@ static void ggml_vk_create_pipeline_func(vk_device& device, vk_pipeline& pipelin
26352637
26362638 // Insert from latest position first so earlier indices stay valid.
26372639
2638- // OpExecutionMode %entrypoint RoundingModeRTE 16
2639- uint32_t exec_mode[] = { (4u << spv::WordCountShift) | spv::OpExecutionMode, entry_point_id, spv::ExecutionModeRoundingModeRTE, 16 };
2640- spirv.insert(spirv.begin() + exec_insert_pos, std::begin(exec_mode), std::end(exec_mode));
2640+ if (device->float_controls_rte_fp16) {
2641+ // OpExecutionMode %entrypoint RoundingModeRTE 16
2642+ uint32_t exec_mode[] = { (4u << spv::WordCountShift) | spv::OpExecutionMode, entry_point_id, spv::ExecutionModeRoundingModeRTE, 16 };
2643+ spirv.insert(spirv.begin() + exec_insert_pos, std::begin(exec_mode), std::end(exec_mode));
2644+ }
2645+
2646+ if (device->float_controls_denorm_preserve_fp16) {
2647+ // OpExecutionMode %entrypoint DenormPreserve 16
2648+ uint32_t exec_mode[] = { (4u << spv::WordCountShift) | spv::OpExecutionMode, entry_point_id, spv::ExecutionModeDenormPreserve, 16 };
2649+ spirv.insert(spirv.begin() + exec_insert_pos, std::begin(exec_mode), std::end(exec_mode));
2650+ }
26412651
26422652 // OpExtension "SPV_KHR_float_controls"
26432653 const char ext_str[] = "SPV_KHR_float_controls";
@@ -2647,9 +2657,17 @@ static void ggml_vk_create_pipeline_func(vk_device& device, vk_pipeline& pipelin
26472657 memcpy(&extension[1], ext_str, sizeof(ext_str));
26482658 spirv.insert(spirv.begin() + ext_insert_pos, extension.begin(), extension.end());
26492659
2650- // OpCapability RoundingModeRTE
2651- uint32_t capability[] = { (2u << spv::WordCountShift) | spv::OpCapability, spv::CapabilityRoundingModeRTE };
2652- spirv.insert(spirv.begin() + cap_insert_pos, std::begin(capability), std::end(capability));
2660+ if (device->float_controls_rte_fp16) {
2661+ // OpCapability RoundingModeRTE
2662+ uint32_t capability[] = { (2u << spv::WordCountShift) | spv::OpCapability, spv::CapabilityRoundingModeRTE };
2663+ spirv.insert(spirv.begin() + cap_insert_pos, std::begin(capability), std::end(capability));
2664+ }
2665+
2666+ if (device->float_controls_denorm_preserve_fp16) {
2667+ // OpCapability DenormPreserve
2668+ uint32_t capability[] = { (2u << spv::WordCountShift) | spv::OpCapability, spv::CapabilityDenormPreserve };
2669+ spirv.insert(spirv.begin() + cap_insert_pos, std::begin(capability), std::end(capability));
2670+ }
26532671
26542672 shader_module_create_info = vk::ShaderModuleCreateInfo({}, spirv.size() * sizeof(uint32_t), spirv.data());
26552673 }
@@ -5187,20 +5205,22 @@ static void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) {
51875205 ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_Q8_0], "cpy_f32_q8_0", cpy_f32_q8_0_len, cpy_f32_q8_0_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1);
51885206 ggml_vk_create_pipeline(device, device->pipeline_cpy_f32_quant[GGML_TYPE_IQ4_NL], "cpy_f32_iq4_nl", cpy_f32_iq4_nl_len, cpy_f32_iq4_nl_data, "main", 2, sizeof(vk_op_unary_push_constants), {32, 1, 1}, {}, 1);
51895207
5190- #define SET_ROWS(itype) \
5191- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_F32], "set_rows_f32" #itype, set_rows_f32 ## itype ## _len, set_rows_f32 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5192- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_F16], "set_rows_f16" #itype, set_rows_f16 ## itype ## _len, set_rows_f16 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5193- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_BF16], "set_rows_bf16" #itype, set_rows_bf16 ## itype ## _len, set_rows_bf16 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5194- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_Q1_0], "set_rows_q1_0" #itype, set_rows_q1_0 ## itype ## _len, set_rows_q1_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5195- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_Q4_0], "set_rows_q4_0" #itype, set_rows_q4_0 ## itype ## _len, set_rows_q4_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5196- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_Q4_1], "set_rows_q4_1" #itype, set_rows_q4_1 ## itype ## _len, set_rows_q4_1 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5197- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_Q5_0], "set_rows_q5_0" #itype, set_rows_q5_0 ## itype ## _len, set_rows_q5_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5198- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_Q5_1], "set_rows_q5_1" #itype, set_rows_q5_1 ## itype ## _len, set_rows_q5_1 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5199- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_Q8_0], "set_rows_q8_0" #itype, set_rows_q8_0 ## itype ## _len, set_rows_q8_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5200- ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [GGML_TYPE_IQ4_NL], "set_rows_iq4_nl" #itype, set_rows_iq4_nl ## itype ## _len, set_rows_iq4_nl ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true);
5201-
5202- SET_ROWS(_i32)
5203- SET_ROWS(_i64)
5208+ #define SET_ROWS(src_idx, src, itype) \
5209+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_F32], "set_rows_" #src "_f32" #itype, set_rows_ ## src ## _f32 ## itype ## _len, set_rows_ ## src ## _f32 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5210+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_F16], "set_rows_" #src "_f16" #itype, set_rows_ ## src ## _f16 ## itype ## _len, set_rows_ ## src ## _f16 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5211+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_BF16], "set_rows_" #src "_bf16" #itype, set_rows_ ## src ## _bf16 ## itype ## _len, set_rows_ ## src ## _bf16 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5212+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_Q1_0], "set_rows_" #src "_q1_0" #itype, set_rows_ ## src ## _q1_0 ## itype ## _len, set_rows_ ## src ## _q1_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5213+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_Q4_0], "set_rows_" #src "_q4_0" #itype, set_rows_ ## src ## _q4_0 ## itype ## _len, set_rows_ ## src ## _q4_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5214+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_Q4_1], "set_rows_" #src "_q4_1" #itype, set_rows_ ## src ## _q4_1 ## itype ## _len, set_rows_ ## src ## _q4_1 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5215+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_Q5_0], "set_rows_" #src "_q5_0" #itype, set_rows_ ## src ## _q5_0 ## itype ## _len, set_rows_ ## src ## _q5_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5216+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_Q5_1], "set_rows_" #src "_q5_1" #itype, set_rows_ ## src ## _q5_1 ## itype ## _len, set_rows_ ## src ## _q5_1 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5217+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_Q8_0], "set_rows_" #src "_q8_0" #itype, set_rows_ ## src ## _q8_0 ## itype ## _len, set_rows_ ## src ## _q8_0 ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true); \
5218+ ggml_vk_create_pipeline(device, device->pipeline_set_rows ## itype [src_idx][GGML_TYPE_IQ4_NL], "set_rows_" #src "_iq4_nl" #itype, set_rows_ ## src ## _iq4_nl ## itype ## _len, set_rows_ ## src ## _iq4_nl ## itype ## _data, "main", 3, sizeof(vk_op_binary_push_constants), {1, 1, 1}, {1}, 1, true);
5219+
5220+ SET_ROWS(0, f32, _i32)
5221+ SET_ROWS(0, f32, _i64)
5222+ SET_ROWS(1, f16, _i32)
5223+ SET_ROWS(1, f16, _i64)
52045224#undef SET_ROWS
52055225
52065226
@@ -6031,6 +6051,7 @@ static vk_device ggml_vk_get_device(size_t idx) {
60316051 device->shader_core_count = 0;
60326052 }
60336053 device->float_controls_rte_fp16 = vk12_props.shaderRoundingModeRTEFloat16;
6054+ device->float_controls_denorm_preserve_fp16 = vk12_props.shaderDenormPreserveFloat16;
60346055
60356056 device->subgroup_basic = (vk11_props.subgroupSupportedStages & vk::ShaderStageFlagBits::eCompute) &&
60366057 (vk11_props.subgroupSupportedOperations & vk::SubgroupFeatureFlagBits::eBasic);
@@ -10843,10 +10864,17 @@ static vk_pipeline ggml_vk_op_get_pipeline(ggml_backend_vk_context * ctx, const
1084310864 case GGML_OP_DUP:
1084410865 return ggml_vk_get_cpy_pipeline(ctx, src0, dst, dst->type);
1084510866 case GGML_OP_SET_ROWS:
10846- if (src1->type == GGML_TYPE_I64) {
10847- return ctx->device->pipeline_set_rows_i64[dst->type];
10848- } else {
10849- return ctx->device->pipeline_set_rows_i32[dst->type];
10867+ {
10868+ if (src0->type != GGML_TYPE_F32 && src0->type != GGML_TYPE_F16) {
10869+ return nullptr;
10870+ }
10871+ const int src_idx = src0->type == GGML_TYPE_F16;
10872+ if (src1->type == GGML_TYPE_I64) {
10873+ return ctx->device->pipeline_set_rows_i64[src_idx][dst->type];
10874+ } else if (src1->type == GGML_TYPE_I32) {
10875+ return ctx->device->pipeline_set_rows_i32[src_idx][dst->type];
10876+ }
10877+ return nullptr;
1085010878 }
1085110879 case GGML_OP_SILU_BACK:
1085210880 if (src0->type == GGML_TYPE_F32 && src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32) {
@@ -17500,24 +17528,25 @@ static bool ggml_backend_vk_device_supports_op(ggml_backend_dev_t dev, const ggm
1750017528 return op->type == GGML_TYPE_F32 && op->src[0]->type == GGML_TYPE_F32;
1750117529 case GGML_OP_SET_ROWS:
1750217530 {
17503- if (op->src[0]->type == GGML_TYPE_F32) {
17504- switch (op->type) {
17505- case GGML_TYPE_F32:
17506- case GGML_TYPE_F16:
17507- case GGML_TYPE_BF16:
17508- case GGML_TYPE_Q1_0:
17509- case GGML_TYPE_Q4_0:
17510- case GGML_TYPE_Q4_1:
17511- case GGML_TYPE_Q5_0:
17512- case GGML_TYPE_Q5_1:
17513- case GGML_TYPE_Q8_0:
17514- case GGML_TYPE_IQ4_NL:
17515- return true;
17516- default:
17517- return false;
17518- }
17531+ if ((op->src[0]->type != GGML_TYPE_F32 && op->src[0]->type != GGML_TYPE_F16) ||
17532+ (op->src[1]->type != GGML_TYPE_I32 && op->src[1]->type != GGML_TYPE_I64)) {
17533+ return false;
17534+ }
17535+ switch (op->type) {
17536+ case GGML_TYPE_F32:
17537+ case GGML_TYPE_F16:
17538+ case GGML_TYPE_BF16:
17539+ case GGML_TYPE_Q1_0:
17540+ case GGML_TYPE_Q4_0:
17541+ case GGML_TYPE_Q4_1:
17542+ case GGML_TYPE_Q5_0:
17543+ case GGML_TYPE_Q5_1:
17544+ case GGML_TYPE_Q8_0:
17545+ case GGML_TYPE_IQ4_NL:
17546+ return true;
17547+ default:
17548+ return false;
1751917549 }
17520- return false;
1752117550 }
1752217551 case GGML_OP_CONT:
1752317552 case GGML_OP_CPY:
0 commit comments