From c08ca7baba7b397986291fad5f8a881465234e89 Mon Sep 17 00:00:00 2001 From: Mostafa Faheem Date: Sat, 22 Aug 2026 13:57:26 +0300 Subject: [PATCH 1/6] ggml-openvino : support RELU, POOL_2D, QUICK_GEGLU, and ROLL ops --- .../openvino/op/glu_geglu_quick.cpp | 64 +++++++++++++++++++ .../src/ggml-openvino/openvino/op/pool_2d.cpp | 55 ++++++++++++++++ ggml/src/ggml-openvino/openvino/op/roll.cpp | 36 +++++++++++ ggml/src/ggml-openvino/openvino/op_table.cpp | 5 ++ ggml/src/ggml-openvino/openvino/op_table.h | 3 + 5 files changed, 163 insertions(+) create mode 100644 ggml/src/ggml-openvino/openvino/op/glu_geglu_quick.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/pool_2d.cpp create mode 100644 ggml/src/ggml-openvino/openvino/op/roll.cpp diff --git a/ggml/src/ggml-openvino/openvino/op/glu_geglu_quick.cpp b/ggml/src/ggml-openvino/openvino/op/glu_geglu_quick.cpp new file mode 100644 index 00000000000..c6d64aed43a --- /dev/null +++ b/ggml/src/ggml-openvino/openvino/op/glu_geglu_quick.cpp @@ -0,0 +1,64 @@ +#include "../node_context.h" +#include "../op_table.h" +#include "../utils.h" + +#include +#include +#include +#include +#include +#include + +namespace ov { +namespace frontend { +namespace ggml { +namespace op { + +OutputVector translate_glu_geglu_quick(const NodeContext & context) { + num_inputs_check(context, 1, 2); + + ov::Output src0; + ov::Output src1; + if (context.get_input_size() == 2) { + src0 = process_view_input_new(context, 0); + src1 = process_view_input_new(context, 1); + } else { + // split along last axis, nc = ne[0] / 2 + auto combined = process_view_input_new(context, 0); + auto combined_shape = combined.get_partial_shape(); + int64_t last_dim_val = combined_shape[combined_shape.rank().get_length() - 1].get_length(); + int64_t nc = last_dim_val / 2; + + auto axis = ov::op::v0::Constant::create(ov::element::i64, {1}, {-1}); + auto step = ov::op::v0::Constant::create(ov::element::i64, {1}, {1}); + auto start0 = ov::op::v0::Constant::create(ov::element::i64, {1}, {0}); + auto stop0 = ov::op::v0::Constant::create(ov::element::i64, {1}, {nc}); + auto start1 = ov::op::v0::Constant::create(ov::element::i64, {1}, {nc}); + auto stop1 = ov::op::v0::Constant::create(ov::element::i64, {1}, {2 * nc}); + + src0 = std::make_shared(combined, start0, stop0, step, axis); + src1 = std::make_shared(combined, start1, stop1, step, axis); + } + + int32_t * params = context.get_output_op_params(); + const int32_t swapped = params[1]; + if (swapped) { + std::swap(src0, src1); + } + + // GELU_QUICK(x) = x * sigmoid(1.702 * x) + // Create the constant in the same type as src0 to avoid f16/f32 mismatch. + auto input_type = src0.get_element_type(); + auto coef = ov::op::v0::Constant::create(input_type, ov::Shape{}, {1.702f}); + auto scaled = std::make_shared(src0, coef); + auto sigmoid = std::make_shared(scaled); + auto gated = std::make_shared(src0, sigmoid); + auto res = std::make_shared(gated, src1); + + return rename_outputs_with_suffix({res}, context.get_name()); +} + +} // namespace op +} // namespace ggml +} // namespace frontend +} // namespace ov diff --git a/ggml/src/ggml-openvino/openvino/op/pool_2d.cpp b/ggml/src/ggml-openvino/openvino/op/pool_2d.cpp new file mode 100644 index 00000000000..daca0abf3b5 --- /dev/null +++ b/ggml/src/ggml-openvino/openvino/op/pool_2d.cpp @@ -0,0 +1,55 @@ +#include "../node_context.h" +#include "../op_table.h" +#include "../utils.h" +#include "ggml.h" + +#include +#include +#include + +namespace ov { +namespace frontend { +namespace ggml { +namespace op { + +OutputVector translate_pool_2d(const NodeContext & context) { + num_inputs_check(context, 1, 1); + const int32_t * params = context.get_output_op_params(); + + const int op = params[0]; + const int k0 = params[1]; + const int k1 = params[2]; + const int s0 = params[3]; + const int s1 = params[4]; + const int p0 = params[5]; + const int p1 = params[6]; + + const ggml_op_pool op_type = static_cast(op); + ov::Output input = context.get_input(0); + ov::Strides strides{static_cast(s1), static_cast(s0)}; + ov::Shape pads_begin{static_cast(p1), static_cast(p0)}; + ov::Shape pads_end{static_cast(p1), static_cast(p0)}; + ov::Shape kernel{static_cast(k1), static_cast(k0)}; + ov::Output res; + + switch (op_type) { + case GGML_OP_POOL_MAX: + { + res = std::make_shared(input, strides, pads_begin, pads_end, kernel); + break; + } + case GGML_OP_POOL_AVG: + { + res = std::make_shared(input, strides, pads_begin, pads_end, kernel, false); + break; + } + default: + break; + } + return rename_outputs_with_suffix({res}, context.get_name()); +} + +} // namespace op +} // namespace ggml +} // namespace frontend +} // namespace ov diff --git a/ggml/src/ggml-openvino/openvino/op/roll.cpp b/ggml/src/ggml-openvino/openvino/op/roll.cpp new file mode 100644 index 00000000000..e8d1b8e50b3 --- /dev/null +++ b/ggml/src/ggml-openvino/openvino/op/roll.cpp @@ -0,0 +1,36 @@ +#include "../node_context.h" +#include "../op_table.h" +#include "../utils.h" + +#include +#include + +namespace ov { +namespace frontend { +namespace ggml { +namespace op { + +OutputVector translate_roll(const NodeContext & context) { + num_inputs_check(context, 1, 1); + const int32_t * params = context.get_output_op_params(); + + int64_t s0 = params[0]; + int64_t s1 = params[1]; + int64_t s2 = params[2]; + int64_t s3 = params[3]; + + auto input = context.get_input(0); + + auto shift = ov::op::v0::Constant::create( + ov::element::i64, ov::Shape{4}, std::vector{s3, s2, s1, s0}); + auto axes = ov::op::v0::Constant::create( + ov::element::i64, ov::Shape{4}, std::vector{0, 1, 2, 3}); + + auto roll = std::make_shared(input, shift, axes); + return rename_outputs_with_suffix({roll}, context.get_name()); +} + +} // namespace op +} // namespace ggml +} // namespace frontend +} // namespace ov diff --git a/ggml/src/ggml-openvino/openvino/op_table.cpp b/ggml/src/ggml-openvino/openvino/op_table.cpp index 3c26fe83b1a..171db602e4a 100644 --- a/ggml/src/ggml-openvino/openvino/op_table.cpp +++ b/ggml/src/ggml-openvino/openvino/op_table.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ std::unordered_map get_supported_ops() { {"GGML_OP_SUB", op::translate_1to1_match_2_inputs}, {"GGML_OP_TRANSPOSE", op::translate_transpose }, {"GGML_UNARY_OP_GELU", op::translate_1to1_match_1_input }, + {"GGML_GLU_OP_GEGLU_QUICK", op::translate_glu_geglu_quick }, {"GGML_UNARY_OP_SIGMOID", op::translate_1to1_match_1_input }, {"GGML_UNARY_OP_SILU", op::translate_unary_silu }, {"GGML_UNARY_OP_SOFTPLUS", op::translate_unary_softplus }, @@ -55,6 +57,7 @@ std::unordered_map get_supported_ops() { {"GGML_UNARY_OP_SIGMOID", op::translate_1to1_match_1_input }, {"GGML_UNARY_OP_EXP", op::translate_1to1_match_1_input }, {"GGML_UNARY_OP_NEG", op::translate_1to1_match_1_input }, + {"GGML_UNARY_OP_RELU", op::translate_1to1_match_1_input }, {"GGML_OP_VIEW", op::translate_view }, {"GGML_GLU_OP_SWIGLU", op::translate_glu_swiglu }, {"GGML_GLU_OP_SWIGLU_OAI", op::translate_glu_swiglu_oai }, @@ -72,6 +75,8 @@ std::unordered_map get_supported_ops() { {"GGML_OP_DIAG", op::translate_diag }, {"GGML_OP_TRI", op::translate_tri }, {"GGML_OP_SET", op::translate_set }, + {"GGML_OP_POOL_2D", op::translate_pool_2d }, + {"GGML_OP_ROLL", op::translate_roll }, // solve_tri has accuracy issues on GPU // {"GGML_OP_SOLVE_TRI", op::translate_solve_tri }, }; diff --git a/ggml/src/ggml-openvino/openvino/op_table.h b/ggml/src/ggml-openvino/openvino/op_table.h index d4b9292d637..0a81a57a667 100644 --- a/ggml/src/ggml-openvino/openvino/op_table.h +++ b/ggml/src/ggml-openvino/openvino/op_table.h @@ -38,6 +38,7 @@ GGML_OP_CONVERTER(translate_view); GGML_OP_CONVERTER(translate_glu_swiglu); GGML_OP_CONVERTER(translate_glu_swiglu_oai); GGML_OP_CONVERTER(translate_glu_geglu); +GGML_OP_CONVERTER(translate_glu_geglu_quick); GGML_OP_CONVERTER(translate_set_rows); GGML_OP_CONVERTER(translate_cpy); GGML_OP_CONVERTER(translate_argsort); @@ -53,6 +54,8 @@ GGML_OP_CONVERTER(translate_set); GGML_OP_CONVERTER(translate_diag); GGML_OP_CONVERTER(translate_tri); GGML_OP_CONVERTER(translate_solve_tri); +GGML_OP_CONVERTER(translate_pool_2d); +GGML_OP_CONVERTER(translate_roll); } // namespace op From 22204af9e61b4b9575686ac78bdb26fb275dfd8a Mon Sep 17 00:00:00 2001 From: Mostafa Faheem Date: Sat, 22 Aug 2026 14:02:21 +0300 Subject: [PATCH 2/6] reorder op table --- ggml/src/ggml-openvino/openvino/op_table.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ggml/src/ggml-openvino/openvino/op_table.cpp b/ggml/src/ggml-openvino/openvino/op_table.cpp index 171db602e4a..9c9d8eeac78 100644 --- a/ggml/src/ggml-openvino/openvino/op_table.cpp +++ b/ggml/src/ggml-openvino/openvino/op_table.cpp @@ -49,7 +49,6 @@ std::unordered_map get_supported_ops() { {"GGML_OP_SUB", op::translate_1to1_match_2_inputs}, {"GGML_OP_TRANSPOSE", op::translate_transpose }, {"GGML_UNARY_OP_GELU", op::translate_1to1_match_1_input }, - {"GGML_GLU_OP_GEGLU_QUICK", op::translate_glu_geglu_quick }, {"GGML_UNARY_OP_SIGMOID", op::translate_1to1_match_1_input }, {"GGML_UNARY_OP_SILU", op::translate_unary_silu }, {"GGML_UNARY_OP_SOFTPLUS", op::translate_unary_softplus }, @@ -62,6 +61,7 @@ std::unordered_map get_supported_ops() { {"GGML_GLU_OP_SWIGLU", op::translate_glu_swiglu }, {"GGML_GLU_OP_SWIGLU_OAI", op::translate_glu_swiglu_oai }, {"GGML_GLU_OP_GEGLU", op::translate_glu_geglu }, + {"GGML_GLU_OP_GEGLU_QUICK", op::translate_glu_geglu_quick }, {"GGML_OP_SET_ROWS", op::translate_set_rows }, {"GGML_OP_CPY", op::translate_cpy }, {"GGML_OP_FLASH_ATTN_EXT", op::translate_flash_attn_ext }, From dd38ce17bffaaa76c16f4f0a7eb3e728b6193480 Mon Sep 17 00:00:00 2001 From: Mostafa Faheem Date: Sat, 22 Aug 2026 19:39:57 +0300 Subject: [PATCH 3/6] exclude GPU/NPU failing POOL_2D case --- ggml/src/ggml-openvino/ggml-openvino.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/ggml/src/ggml-openvino/ggml-openvino.cpp b/ggml/src/ggml-openvino/ggml-openvino.cpp index d237cb8f8f9..d7336685488 100644 --- a/ggml/src/ggml-openvino/ggml-openvino.cpp +++ b/ggml/src/ggml-openvino/ggml-openvino.cpp @@ -1146,6 +1146,20 @@ static ggml_openvino_op_support is_op_supported_case(const ggml_tensor * op) { } break; } + case GGML_OP_POOL_2D: { + const auto& name = ggml_openvino_get_device_name(); + if (name == "GPU" || name == "NPU") { + const int32_t * params = op->op_params; + const int k0 = params[1]; + const int k1 = params[2]; + const int p0 = params[5]; + const int p1 = params[6]; + if ((p0 > 0 || p1 > 0) && (k0 < 3 || k1 < 3)) { + return true; + } + } + break; + } case GGML_OP_SUM_ROWS: { if (op->src[0]->op == GGML_OP_PERMUTE) { return {false, "SUM_ROWS with PERMUTE input is not supported"}; From 352d27c6c39406e645706a1f398f746058555dfa Mon Sep 17 00:00:00 2001 From: Mostafa Faheem Date: Sat, 22 Aug 2026 20:51:33 +0300 Subject: [PATCH 4/6] move op type detection to compute_op_case --- ggml/src/ggml-openvino/ggml-decoder.cpp | 17 +++++++++++++++++ ggml/src/ggml-openvino/openvino/op/pool_2d.cpp | 10 ++++------ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/ggml/src/ggml-openvino/ggml-decoder.cpp b/ggml/src/ggml-openvino/ggml-decoder.cpp index 4d30798b74e..006e005cb7a 100644 --- a/ggml/src/ggml-openvino/ggml-decoder.cpp +++ b/ggml/src/ggml-openvino/ggml-decoder.cpp @@ -420,6 +420,23 @@ int GgmlOvDecoder::compute_op_case(const ggml_tensor * node) const { } break; } + case GGML_OP_POOL_2D: { + const ggml_op_pool pool_mode = static_cast(node->op_params[0]); + switch (pool_mode) { + case GGML_OP_POOL_MAX: { + op_case = 1; + break; + } + case GGML_OP_POOL_AVG: { + op_case = 2; + break; + } + default: + op_case = 0; + break; + } + break; + } case GGML_OP_CPY: { if (node->src[0]->op == GGML_OP_VIEW) { if (node->src[0]->src[0]->op == GGML_OP_GATED_DELTA_NET) { diff --git a/ggml/src/ggml-openvino/openvino/op/pool_2d.cpp b/ggml/src/ggml-openvino/openvino/op/pool_2d.cpp index daca0abf3b5..82bff6b898b 100644 --- a/ggml/src/ggml-openvino/openvino/op/pool_2d.cpp +++ b/ggml/src/ggml-openvino/openvino/op/pool_2d.cpp @@ -1,7 +1,6 @@ #include "../node_context.h" #include "../op_table.h" #include "../utils.h" -#include "ggml.h" #include #include @@ -16,7 +15,6 @@ OutputVector translate_pool_2d(const NodeContext & context) { num_inputs_check(context, 1, 1); const int32_t * params = context.get_output_op_params(); - const int op = params[0]; const int k0 = params[1]; const int k1 = params[2]; const int s0 = params[3]; @@ -24,7 +22,7 @@ OutputVector translate_pool_2d(const NodeContext & context) { const int p0 = params[5]; const int p1 = params[6]; - const ggml_op_pool op_type = static_cast(op); + const int op_case = context.get_op_case(); ov::Output input = context.get_input(0); ov::Strides strides{static_cast(s1), static_cast(s0)}; ov::Shape pads_begin{static_cast(p1), static_cast(p0)}; @@ -32,13 +30,13 @@ OutputVector translate_pool_2d(const NodeContext & context) { ov::Shape kernel{static_cast(k1), static_cast(k0)}; ov::Output res; - switch (op_type) { - case GGML_OP_POOL_MAX: + switch (op_case) { + case 1: // GGML_OP_POOL_MAX { res = std::make_shared(input, strides, pads_begin, pads_end, kernel); break; } - case GGML_OP_POOL_AVG: + case 2: // GGML_OP_POOL_AVG { res = std::make_shared(input, strides, pads_begin, pads_end, kernel, false); break; From ea751225b12cd4a04612a8730ff7f9197bf580ec Mon Sep 17 00:00:00 2001 From: Mostafa Faheem Date: Sun, 23 Aug 2026 07:47:14 +0300 Subject: [PATCH 5/6] Relax rope supported cases --- ggml/src/ggml-openvino/ggml-openvino.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/ggml/src/ggml-openvino/ggml-openvino.cpp b/ggml/src/ggml-openvino/ggml-openvino.cpp index d7336685488..f5041ef67e6 100644 --- a/ggml/src/ggml-openvino/ggml-openvino.cpp +++ b/ggml/src/ggml-openvino/ggml-openvino.cpp @@ -1281,9 +1281,14 @@ static ggml_openvino_op_support is_op_supported_case(const ggml_tensor * op) { return {false, "ROPE with type " + std::string(ggml_type_name(op->type)) + " is not supported"}; } if (op->src[0]->op == GGML_OP_VIEW) { - if (op->src[0]->view_src->ne[1] != op->src[0]->ne[2]) { - return {false, "ROPE with src[0]->view_src->ne[1] " + std::to_string(op->src[0]->view_src->ne[1]) + - " != src[0]->ne[2] " + std::to_string(op->src[0]->ne[2]) + " is not supported"}; + const struct ggml_tensor * view = op->src[0]; + const struct ggml_tensor * view_src = view->view_src; + if (view_src->ne[1] != view->ne[1] || view_src->ne[2] != view->ne[2] || view_src->ne[3] != view->ne[3]) { + return {false, "ROPE with view_src->ne [" + std::to_string(view_src->ne[1]) + ", " + + std::to_string(view_src->ne[2]) + ", " + std::to_string(view_src->ne[3]) + + "] != view->ne [" + std::to_string(view->ne[1]) + ", " + + std::to_string(view->ne[2]) + ", " + std::to_string(view->ne[3]) + + "] is not supported"}; } } if (mode == GGML_ROPE_TYPE_IMROPE && From 6251c7ae1de5e1c856fa9b6bcc71466cfd705710 Mon Sep 17 00:00:00 2001 From: Mostafa Faheem Date: Thu, 27 Aug 2026 11:24:00 +0300 Subject: [PATCH 6/6] Fix pool case --- ggml/src/ggml-openvino/ggml-openvino.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ggml/src/ggml-openvino/ggml-openvino.cpp b/ggml/src/ggml-openvino/ggml-openvino.cpp index f5041ef67e6..4b1789713d1 100644 --- a/ggml/src/ggml-openvino/ggml-openvino.cpp +++ b/ggml/src/ggml-openvino/ggml-openvino.cpp @@ -1148,14 +1148,14 @@ static ggml_openvino_op_support is_op_supported_case(const ggml_tensor * op) { } case GGML_OP_POOL_2D: { const auto& name = ggml_openvino_get_device_name(); - if (name == "GPU" || name == "NPU") { + if (name == "GPU") { const int32_t * params = op->op_params; const int k0 = params[1]; const int k1 = params[2]; const int p0 = params[5]; const int p1 = params[6]; if ((p0 > 0 || p1 > 0) && (k0 < 3 || k1 < 3)) { - return true; + return {false, "POOL_2D with padding and kernel size < 3 is not supported on " + name}; } } break;