fix: Support 5D volumetric inputs in ONNX GridSample frontend converter - #19816

Merged
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d
Jun 18, 2026
Merged

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter#19816
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d

Conversation

@mvanhorn

Copy link
Copy Markdown
Contributor

Summary

The Relax ONNX frontend's GridSample._impl_v16 converter unconditionally permutes the grid from ONNX [N,H,W,2] to TVM [N,2,H,W] and calls image.grid_sample with layout="NCHW". For 5D volumetric inputs ([N,C,D,H,W] with grid [N,D,H,W,3]) this crashes at permute_dims with an InternalError ('PermuteDims expects the number of input axes to equal the ndim of the input tensor.

Changes

In GridSample._impl_v16, read data.struct_info.ndim and dispatch on rank. For ndim==4, keep the existing permute_dims(grid,[0,3,1,2]) + grid_sample(layout="NCHW").

Fixes#19688

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request extends the ONNX frontend's GridSample operator to support 5D inputs (NCDHW layout) in addition to the existing 4D inputs (NCHW layout), and adds corresponding unit tests. The feedback suggests using the existing helper function _get_known_tensor_rank(data) to determine the input's dimensionality more robustly and idiomatically, rather than manually checking attributes on struct_info.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of manually checking hasattr(data.struct_info, "ndim") and falling back to len(data.struct_info.shape), it is more robust and idiomatic to use the existing helper function _get_known_tensor_rank(data). This helper is used throughout the codebase and safely handles various expression types (e.g., relax.Constant, relax.ShapeExpr, relax.PrimValue, and relax.TensorStructInfo) while avoiding potential AttributeError or TypeError if struct_info or shape is not fully defined.

ndim=_get_known_tensor_rank(data)

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for 5D inputs in the ONNX GridSample operator, mapping it to the NCDHW layout and permuting the grid dimensions accordingly, along with corresponding unit tests. Feedback suggests using the helper function _get_known_tensor_rank(data) instead of directly accessing data.struct_info to safely retrieve the input tensor's rank and avoid potential AttributeErrors.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Directly accessing data.struct_info can lead to an AttributeError if struct_info is None. It is safer and more consistent with the rest of the codebase to use the helper function _get_known_tensor_rank(data) to retrieve the rank of the input tensor.

Suggested change
ifhasattr(data.struct_info, "ndim"):
ndim=data.struct_info.ndim
else:
ndim=len(data.struct_info.shape)
ndim=_get_known_tensor_rank(data)
ifndimisNone:
raiseValueError("GridSample requires a statically known input rank.")

The ONNX frontend dispatches 5D GridSample to the relax grid_sample op with
layout=NCDHW, and TOPI already implements the 3D compute, but
InferStructInfoGridSample hardcoded NCHW so 5D inputs hit a fatal layout
error during StructInfo inference. Branch on the NCDHW layout and derive the
output spatial extents from grid->values[2:], mirroring the existing
Resize3D inference. The 2D NCHW path is unchanged.

@tlopextlopex left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix! @mvanhorn
I found two issues worth addressing before merge:

  1. 5D mode="cubic" is accepted by the ONNX frontend but is not supported by TOPI.

GridSample._impl_v16 translates ONNX mode="cubic" to method="bicubic" and then sends 5D inputs to relax.op.image.grid_sample(..., layout="NCDHW"). However, the TOPI 3D implementation only supports ("bilinear", "nearest"):

assertmethodin ("bilinear", "nearest"), f"{method} is not supported"

So a valid ONNX 5D cubic GridSample model will import successfully but fail later during legalization/compile. Could we either implement 3D cubic, or explicitly reject ndim == 5 and method == "bicubic" in the frontend with a clear NotImplementedError? A regression test for this case would be good too.

  1. While touching InferStructInfoGridSample, there is an existing 4D shape inference mismatch that this PR could fix.

The ONNX frontend permutes the 4D grid from [N, H_out, W_out, 2] to TOPI layout [N, 2, H_out, W_out], but the 4D inference path still reads:

out_tgt_shape.Set(2, grid_shape->values[1]);
out_tgt_shape.Set(3, grid_shape->values[2]);

For a non-square output grid like [N, 2, 3, 5], this infers [N, C, 2, 3] instead of [N, C, 3, 5]. The current 4D test uses [1, 2, 2, 2], so it does not catch this. Since the 5D branch correctly reads the permuted spatial dims from grid_shape->values[2:], I think the 4D branch should do the same (values[2], values[3]) and add a non-square 4D test.

…rence
- onnx frontend: raise NotImplementedError for 5D mode='cubic' (TOPI 3D
grid_sample supports only bilinear/nearest), instead of importing a model
that fails later at legalization
- InferStructInfoGridSample: 4D branch now reads the permuted grid spatial
dims (values[2]/values[3]) to match the frontend's NCHW permutation; fixes
non-square output shape inference
- tests: add 5D cubic rejection test and non-square 4D output shape test
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks for the careful review! Both addressed in 9518915:

  1. The frontend now raises NotImplementedError for 5D mode="cubic" (4D bicubic is still fine via TOPI's 2D path), so an unsupported volumetric-cubic model fails fast at import with a clear message instead of dying later at legalization. Added a regression test.

  2. Fixed the 4D shape-inference mismatch in InferStructInfoGridSample: the 4D branch now reads the permuted spatial dims (values[2]/values[3]) to match the frontend's [N, 2, H_out, W_out] permutation, mirroring the 5D branch. Added a non-square 4D test ([1, 3, 5, 2] -> [1, 3, 3, 5]) that catches the old values[1]/values[2] bug.

I couldn't run pytest locally (no TVM build here), so I'm relying on CI for the compiled checks.

@tlopex

Copy link
Copy Markdown
Member

LGTM! Thanks for the fix!

@tlopex
tlopex merged commit da52d7d into apache:mainJun 18, 2026
6 checks passed
tlopex added a commit to tlopex/tvm that referenced this pull request Jun 18, 2026
The 5D GridSample change (apache#19816) landed with a clang-format violation on
the structured binding for CheckTensorLayout, which fails the repo-wide
pre-commit lint (clang-format v20.1.8). Reformat to satisfy the hook.
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks @tlopex for the quick merge. Supporting 5D volumetric inputs in the ONNX GridSample converter rounds out that frontend.

@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thank you @tlopex. Supporting 5D volumetric inputs in the ONNX GridSample converter closes a real gap in the Relax frontend.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug][Relax][ONNX] GridSample 5D (volumetric) input crashes the frontend

2 participants

@mvanhorn@tlopex
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter - #19816

Merged
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d
Jun 18, 2026
Merged

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter#19816
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d

Conversation

@mvanhorn

Copy link
Copy Markdown
Contributor

Summary

The Relax ONNX frontend's GridSample._impl_v16 converter unconditionally permutes the grid from ONNX [N,H,W,2] to TVM [N,2,H,W] and calls image.grid_sample with layout="NCHW". For 5D volumetric inputs ([N,C,D,H,W] with grid [N,D,H,W,3]) this crashes at permute_dims with an InternalError ('PermuteDims expects the number of input axes to equal the ndim of the input tensor.

Changes

In GridSample._impl_v16, read data.struct_info.ndim and dispatch on rank. For ndim==4, keep the existing permute_dims(grid,[0,3,1,2]) + grid_sample(layout="NCHW").

Fixes#19688

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request extends the ONNX frontend's GridSample operator to support 5D inputs (NCDHW layout) in addition to the existing 4D inputs (NCHW layout), and adds corresponding unit tests. The feedback suggests using the existing helper function _get_known_tensor_rank(data) to determine the input's dimensionality more robustly and idiomatically, rather than manually checking attributes on struct_info.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of manually checking hasattr(data.struct_info, "ndim") and falling back to len(data.struct_info.shape), it is more robust and idiomatic to use the existing helper function _get_known_tensor_rank(data). This helper is used throughout the codebase and safely handles various expression types (e.g., relax.Constant, relax.ShapeExpr, relax.PrimValue, and relax.TensorStructInfo) while avoiding potential AttributeError or TypeError if struct_info or shape is not fully defined.

ndim=_get_known_tensor_rank(data)

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for 5D inputs in the ONNX GridSample operator, mapping it to the NCDHW layout and permuting the grid dimensions accordingly, along with corresponding unit tests. Feedback suggests using the helper function _get_known_tensor_rank(data) instead of directly accessing data.struct_info to safely retrieve the input tensor's rank and avoid potential AttributeErrors.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Directly accessing data.struct_info can lead to an AttributeError if struct_info is None. It is safer and more consistent with the rest of the codebase to use the helper function _get_known_tensor_rank(data) to retrieve the rank of the input tensor.

Suggested change
ifhasattr(data.struct_info, "ndim"):
ndim=data.struct_info.ndim
else:
ndim=len(data.struct_info.shape)
ndim=_get_known_tensor_rank(data)
ifndimisNone:
raiseValueError("GridSample requires a statically known input rank.")

The ONNX frontend dispatches 5D GridSample to the relax grid_sample op with
layout=NCDHW, and TOPI already implements the 3D compute, but
InferStructInfoGridSample hardcoded NCHW so 5D inputs hit a fatal layout
error during StructInfo inference. Branch on the NCDHW layout and derive the
output spatial extents from grid->values[2:], mirroring the existing
Resize3D inference. The 2D NCHW path is unchanged.

@tlopextlopex left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix! @mvanhorn
I found two issues worth addressing before merge:

  1. 5D mode="cubic" is accepted by the ONNX frontend but is not supported by TOPI.

GridSample._impl_v16 translates ONNX mode="cubic" to method="bicubic" and then sends 5D inputs to relax.op.image.grid_sample(..., layout="NCDHW"). However, the TOPI 3D implementation only supports ("bilinear", "nearest"):

assertmethodin ("bilinear", "nearest"), f"{method} is not supported"

So a valid ONNX 5D cubic GridSample model will import successfully but fail later during legalization/compile. Could we either implement 3D cubic, or explicitly reject ndim == 5 and method == "bicubic" in the frontend with a clear NotImplementedError? A regression test for this case would be good too.

  1. While touching InferStructInfoGridSample, there is an existing 4D shape inference mismatch that this PR could fix.

The ONNX frontend permutes the 4D grid from [N, H_out, W_out, 2] to TOPI layout [N, 2, H_out, W_out], but the 4D inference path still reads:

out_tgt_shape.Set(2, grid_shape->values[1]);
out_tgt_shape.Set(3, grid_shape->values[2]);

For a non-square output grid like [N, 2, 3, 5], this infers [N, C, 2, 3] instead of [N, C, 3, 5]. The current 4D test uses [1, 2, 2, 2], so it does not catch this. Since the 5D branch correctly reads the permuted spatial dims from grid_shape->values[2:], I think the 4D branch should do the same (values[2], values[3]) and add a non-square 4D test.

…rence
- onnx frontend: raise NotImplementedError for 5D mode='cubic' (TOPI 3D
grid_sample supports only bilinear/nearest), instead of importing a model
that fails later at legalization
- InferStructInfoGridSample: 4D branch now reads the permuted grid spatial
dims (values[2]/values[3]) to match the frontend's NCHW permutation; fixes
non-square output shape inference
- tests: add 5D cubic rejection test and non-square 4D output shape test
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks for the careful review! Both addressed in 9518915:

  1. The frontend now raises NotImplementedError for 5D mode="cubic" (4D bicubic is still fine via TOPI's 2D path), so an unsupported volumetric-cubic model fails fast at import with a clear message instead of dying later at legalization. Added a regression test.

  2. Fixed the 4D shape-inference mismatch in InferStructInfoGridSample: the 4D branch now reads the permuted spatial dims (values[2]/values[3]) to match the frontend's [N, 2, H_out, W_out] permutation, mirroring the 5D branch. Added a non-square 4D test ([1, 3, 5, 2] -> [1, 3, 3, 5]) that catches the old values[1]/values[2] bug.

I couldn't run pytest locally (no TVM build here), so I'm relying on CI for the compiled checks.

@tlopex

Copy link
Copy Markdown
Member

LGTM! Thanks for the fix!

@tlopex
tlopex merged commit da52d7d into apache:mainJun 18, 2026
6 checks passed
tlopex added a commit to tlopex/tvm that referenced this pull request Jun 18, 2026
The 5D GridSample change (apache#19816) landed with a clang-format violation on
the structured binding for CheckTensorLayout, which fails the repo-wide
pre-commit lint (clang-format v20.1.8). Reformat to satisfy the hook.
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks @tlopex for the quick merge. Supporting 5D volumetric inputs in the ONNX GridSample converter rounds out that frontend.

@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thank you @tlopex. Supporting 5D volumetric inputs in the ONNX GridSample converter closes a real gap in the Relax frontend.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug][Relax][ONNX] GridSample 5D (volumetric) input crashes the frontend

2 participants

@mvanhorn@tlopex
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter - #19816

Merged
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d
Jun 18, 2026
Merged

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter#19816
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d

Conversation

@mvanhorn

Copy link
Copy Markdown
Contributor

Summary

The Relax ONNX frontend's GridSample._impl_v16 converter unconditionally permutes the grid from ONNX [N,H,W,2] to TVM [N,2,H,W] and calls image.grid_sample with layout="NCHW". For 5D volumetric inputs ([N,C,D,H,W] with grid [N,D,H,W,3]) this crashes at permute_dims with an InternalError ('PermuteDims expects the number of input axes to equal the ndim of the input tensor.

Changes

In GridSample._impl_v16, read data.struct_info.ndim and dispatch on rank. For ndim==4, keep the existing permute_dims(grid,[0,3,1,2]) + grid_sample(layout="NCHW").

Fixes#19688

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request extends the ONNX frontend's GridSample operator to support 5D inputs (NCDHW layout) in addition to the existing 4D inputs (NCHW layout), and adds corresponding unit tests. The feedback suggests using the existing helper function _get_known_tensor_rank(data) to determine the input's dimensionality more robustly and idiomatically, rather than manually checking attributes on struct_info.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of manually checking hasattr(data.struct_info, "ndim") and falling back to len(data.struct_info.shape), it is more robust and idiomatic to use the existing helper function _get_known_tensor_rank(data). This helper is used throughout the codebase and safely handles various expression types (e.g., relax.Constant, relax.ShapeExpr, relax.PrimValue, and relax.TensorStructInfo) while avoiding potential AttributeError or TypeError if struct_info or shape is not fully defined.

ndim=_get_known_tensor_rank(data)

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for 5D inputs in the ONNX GridSample operator, mapping it to the NCDHW layout and permuting the grid dimensions accordingly, along with corresponding unit tests. Feedback suggests using the helper function _get_known_tensor_rank(data) instead of directly accessing data.struct_info to safely retrieve the input tensor's rank and avoid potential AttributeErrors.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Directly accessing data.struct_info can lead to an AttributeError if struct_info is None. It is safer and more consistent with the rest of the codebase to use the helper function _get_known_tensor_rank(data) to retrieve the rank of the input tensor.

Suggested change
ifhasattr(data.struct_info, "ndim"):
ndim=data.struct_info.ndim
else:
ndim=len(data.struct_info.shape)
ndim=_get_known_tensor_rank(data)
ifndimisNone:
raiseValueError("GridSample requires a statically known input rank.")

The ONNX frontend dispatches 5D GridSample to the relax grid_sample op with
layout=NCDHW, and TOPI already implements the 3D compute, but
InferStructInfoGridSample hardcoded NCHW so 5D inputs hit a fatal layout
error during StructInfo inference. Branch on the NCDHW layout and derive the
output spatial extents from grid->values[2:], mirroring the existing
Resize3D inference. The 2D NCHW path is unchanged.

@tlopextlopex left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix! @mvanhorn
I found two issues worth addressing before merge:

  1. 5D mode="cubic" is accepted by the ONNX frontend but is not supported by TOPI.

GridSample._impl_v16 translates ONNX mode="cubic" to method="bicubic" and then sends 5D inputs to relax.op.image.grid_sample(..., layout="NCDHW"). However, the TOPI 3D implementation only supports ("bilinear", "nearest"):

assertmethodin ("bilinear", "nearest"), f"{method} is not supported"

So a valid ONNX 5D cubic GridSample model will import successfully but fail later during legalization/compile. Could we either implement 3D cubic, or explicitly reject ndim == 5 and method == "bicubic" in the frontend with a clear NotImplementedError? A regression test for this case would be good too.

  1. While touching InferStructInfoGridSample, there is an existing 4D shape inference mismatch that this PR could fix.

The ONNX frontend permutes the 4D grid from [N, H_out, W_out, 2] to TOPI layout [N, 2, H_out, W_out], but the 4D inference path still reads:

out_tgt_shape.Set(2, grid_shape->values[1]);
out_tgt_shape.Set(3, grid_shape->values[2]);

For a non-square output grid like [N, 2, 3, 5], this infers [N, C, 2, 3] instead of [N, C, 3, 5]. The current 4D test uses [1, 2, 2, 2], so it does not catch this. Since the 5D branch correctly reads the permuted spatial dims from grid_shape->values[2:], I think the 4D branch should do the same (values[2], values[3]) and add a non-square 4D test.

…rence
- onnx frontend: raise NotImplementedError for 5D mode='cubic' (TOPI 3D
grid_sample supports only bilinear/nearest), instead of importing a model
that fails later at legalization
- InferStructInfoGridSample: 4D branch now reads the permuted grid spatial
dims (values[2]/values[3]) to match the frontend's NCHW permutation; fixes
non-square output shape inference
- tests: add 5D cubic rejection test and non-square 4D output shape test
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks for the careful review! Both addressed in 9518915:

  1. The frontend now raises NotImplementedError for 5D mode="cubic" (4D bicubic is still fine via TOPI's 2D path), so an unsupported volumetric-cubic model fails fast at import with a clear message instead of dying later at legalization. Added a regression test.

  2. Fixed the 4D shape-inference mismatch in InferStructInfoGridSample: the 4D branch now reads the permuted spatial dims (values[2]/values[3]) to match the frontend's [N, 2, H_out, W_out] permutation, mirroring the 5D branch. Added a non-square 4D test ([1, 3, 5, 2] -> [1, 3, 3, 5]) that catches the old values[1]/values[2] bug.

I couldn't run pytest locally (no TVM build here), so I'm relying on CI for the compiled checks.

@tlopex

Copy link
Copy Markdown
Member

LGTM! Thanks for the fix!

@tlopex
tlopex merged commit da52d7d into apache:mainJun 18, 2026
6 checks passed
tlopex added a commit to tlopex/tvm that referenced this pull request Jun 18, 2026
The 5D GridSample change (apache#19816) landed with a clang-format violation on
the structured binding for CheckTensorLayout, which fails the repo-wide
pre-commit lint (clang-format v20.1.8). Reformat to satisfy the hook.
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks @tlopex for the quick merge. Supporting 5D volumetric inputs in the ONNX GridSample converter rounds out that frontend.

@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thank you @tlopex. Supporting 5D volumetric inputs in the ONNX GridSample converter closes a real gap in the Relax frontend.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug][Relax][ONNX] GridSample 5D (volumetric) input crashes the frontend

2 participants

@mvanhorn@tlopex
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter - #19816

Merged
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d
Jun 18, 2026
Merged

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter#19816
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d

Conversation

@mvanhorn

Copy link
Copy Markdown
Contributor

Summary

The Relax ONNX frontend's GridSample._impl_v16 converter unconditionally permutes the grid from ONNX [N,H,W,2] to TVM [N,2,H,W] and calls image.grid_sample with layout="NCHW". For 5D volumetric inputs ([N,C,D,H,W] with grid [N,D,H,W,3]) this crashes at permute_dims with an InternalError ('PermuteDims expects the number of input axes to equal the ndim of the input tensor.

Changes

In GridSample._impl_v16, read data.struct_info.ndim and dispatch on rank. For ndim==4, keep the existing permute_dims(grid,[0,3,1,2]) + grid_sample(layout="NCHW").

Fixes#19688

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request extends the ONNX frontend's GridSample operator to support 5D inputs (NCDHW layout) in addition to the existing 4D inputs (NCHW layout), and adds corresponding unit tests. The feedback suggests using the existing helper function _get_known_tensor_rank(data) to determine the input's dimensionality more robustly and idiomatically, rather than manually checking attributes on struct_info.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of manually checking hasattr(data.struct_info, "ndim") and falling back to len(data.struct_info.shape), it is more robust and idiomatic to use the existing helper function _get_known_tensor_rank(data). This helper is used throughout the codebase and safely handles various expression types (e.g., relax.Constant, relax.ShapeExpr, relax.PrimValue, and relax.TensorStructInfo) while avoiding potential AttributeError or TypeError if struct_info or shape is not fully defined.

ndim=_get_known_tensor_rank(data)

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for 5D inputs in the ONNX GridSample operator, mapping it to the NCDHW layout and permuting the grid dimensions accordingly, along with corresponding unit tests. Feedback suggests using the helper function _get_known_tensor_rank(data) instead of directly accessing data.struct_info to safely retrieve the input tensor's rank and avoid potential AttributeErrors.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Directly accessing data.struct_info can lead to an AttributeError if struct_info is None. It is safer and more consistent with the rest of the codebase to use the helper function _get_known_tensor_rank(data) to retrieve the rank of the input tensor.

Suggested change
ifhasattr(data.struct_info, "ndim"):
ndim=data.struct_info.ndim
else:
ndim=len(data.struct_info.shape)
ndim=_get_known_tensor_rank(data)
ifndimisNone:
raiseValueError("GridSample requires a statically known input rank.")

The ONNX frontend dispatches 5D GridSample to the relax grid_sample op with
layout=NCDHW, and TOPI already implements the 3D compute, but
InferStructInfoGridSample hardcoded NCHW so 5D inputs hit a fatal layout
error during StructInfo inference. Branch on the NCDHW layout and derive the
output spatial extents from grid->values[2:], mirroring the existing
Resize3D inference. The 2D NCHW path is unchanged.

@tlopextlopex left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix! @mvanhorn
I found two issues worth addressing before merge:

  1. 5D mode="cubic" is accepted by the ONNX frontend but is not supported by TOPI.

GridSample._impl_v16 translates ONNX mode="cubic" to method="bicubic" and then sends 5D inputs to relax.op.image.grid_sample(..., layout="NCDHW"). However, the TOPI 3D implementation only supports ("bilinear", "nearest"):

assertmethodin ("bilinear", "nearest"), f"{method} is not supported"

So a valid ONNX 5D cubic GridSample model will import successfully but fail later during legalization/compile. Could we either implement 3D cubic, or explicitly reject ndim == 5 and method == "bicubic" in the frontend with a clear NotImplementedError? A regression test for this case would be good too.

  1. While touching InferStructInfoGridSample, there is an existing 4D shape inference mismatch that this PR could fix.

The ONNX frontend permutes the 4D grid from [N, H_out, W_out, 2] to TOPI layout [N, 2, H_out, W_out], but the 4D inference path still reads:

out_tgt_shape.Set(2, grid_shape->values[1]);
out_tgt_shape.Set(3, grid_shape->values[2]);

For a non-square output grid like [N, 2, 3, 5], this infers [N, C, 2, 3] instead of [N, C, 3, 5]. The current 4D test uses [1, 2, 2, 2], so it does not catch this. Since the 5D branch correctly reads the permuted spatial dims from grid_shape->values[2:], I think the 4D branch should do the same (values[2], values[3]) and add a non-square 4D test.

…rence
- onnx frontend: raise NotImplementedError for 5D mode='cubic' (TOPI 3D
grid_sample supports only bilinear/nearest), instead of importing a model
that fails later at legalization
- InferStructInfoGridSample: 4D branch now reads the permuted grid spatial
dims (values[2]/values[3]) to match the frontend's NCHW permutation; fixes
non-square output shape inference
- tests: add 5D cubic rejection test and non-square 4D output shape test
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks for the careful review! Both addressed in 9518915:

  1. The frontend now raises NotImplementedError for 5D mode="cubic" (4D bicubic is still fine via TOPI's 2D path), so an unsupported volumetric-cubic model fails fast at import with a clear message instead of dying later at legalization. Added a regression test.

  2. Fixed the 4D shape-inference mismatch in InferStructInfoGridSample: the 4D branch now reads the permuted spatial dims (values[2]/values[3]) to match the frontend's [N, 2, H_out, W_out] permutation, mirroring the 5D branch. Added a non-square 4D test ([1, 3, 5, 2] -> [1, 3, 3, 5]) that catches the old values[1]/values[2] bug.

I couldn't run pytest locally (no TVM build here), so I'm relying on CI for the compiled checks.

@tlopex

Copy link
Copy Markdown
Member

LGTM! Thanks for the fix!

@tlopex
tlopex merged commit da52d7d into apache:mainJun 18, 2026
6 checks passed
tlopex added a commit to tlopex/tvm that referenced this pull request Jun 18, 2026
The 5D GridSample change (apache#19816) landed with a clang-format violation on
the structured binding for CheckTensorLayout, which fails the repo-wide
pre-commit lint (clang-format v20.1.8). Reformat to satisfy the hook.
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks @tlopex for the quick merge. Supporting 5D volumetric inputs in the ONNX GridSample converter rounds out that frontend.

@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thank you @tlopex. Supporting 5D volumetric inputs in the ONNX GridSample converter closes a real gap in the Relax frontend.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug][Relax][ONNX] GridSample 5D (volumetric) input crashes the frontend

2 participants

@mvanhorn@tlopex
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter - #19816

Merged
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d
Jun 18, 2026
Merged

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter#19816
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d

Conversation

@mvanhorn

Copy link
Copy Markdown
Contributor

Summary

The Relax ONNX frontend's GridSample._impl_v16 converter unconditionally permutes the grid from ONNX [N,H,W,2] to TVM [N,2,H,W] and calls image.grid_sample with layout="NCHW". For 5D volumetric inputs ([N,C,D,H,W] with grid [N,D,H,W,3]) this crashes at permute_dims with an InternalError ('PermuteDims expects the number of input axes to equal the ndim of the input tensor.

Changes

In GridSample._impl_v16, read data.struct_info.ndim and dispatch on rank. For ndim==4, keep the existing permute_dims(grid,[0,3,1,2]) + grid_sample(layout="NCHW").

Fixes#19688

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request extends the ONNX frontend's GridSample operator to support 5D inputs (NCDHW layout) in addition to the existing 4D inputs (NCHW layout), and adds corresponding unit tests. The feedback suggests using the existing helper function _get_known_tensor_rank(data) to determine the input's dimensionality more robustly and idiomatically, rather than manually checking attributes on struct_info.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of manually checking hasattr(data.struct_info, "ndim") and falling back to len(data.struct_info.shape), it is more robust and idiomatic to use the existing helper function _get_known_tensor_rank(data). This helper is used throughout the codebase and safely handles various expression types (e.g., relax.Constant, relax.ShapeExpr, relax.PrimValue, and relax.TensorStructInfo) while avoiding potential AttributeError or TypeError if struct_info or shape is not fully defined.

ndim=_get_known_tensor_rank(data)

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for 5D inputs in the ONNX GridSample operator, mapping it to the NCDHW layout and permuting the grid dimensions accordingly, along with corresponding unit tests. Feedback suggests using the helper function _get_known_tensor_rank(data) instead of directly accessing data.struct_info to safely retrieve the input tensor's rank and avoid potential AttributeErrors.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Directly accessing data.struct_info can lead to an AttributeError if struct_info is None. It is safer and more consistent with the rest of the codebase to use the helper function _get_known_tensor_rank(data) to retrieve the rank of the input tensor.

Suggested change
ifhasattr(data.struct_info, "ndim"):
ndim=data.struct_info.ndim
else:
ndim=len(data.struct_info.shape)
ndim=_get_known_tensor_rank(data)
ifndimisNone:
raiseValueError("GridSample requires a statically known input rank.")

The ONNX frontend dispatches 5D GridSample to the relax grid_sample op with
layout=NCDHW, and TOPI already implements the 3D compute, but
InferStructInfoGridSample hardcoded NCHW so 5D inputs hit a fatal layout
error during StructInfo inference. Branch on the NCDHW layout and derive the
output spatial extents from grid->values[2:], mirroring the existing
Resize3D inference. The 2D NCHW path is unchanged.

@tlopextlopex left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix! @mvanhorn
I found two issues worth addressing before merge:

  1. 5D mode="cubic" is accepted by the ONNX frontend but is not supported by TOPI.

GridSample._impl_v16 translates ONNX mode="cubic" to method="bicubic" and then sends 5D inputs to relax.op.image.grid_sample(..., layout="NCDHW"). However, the TOPI 3D implementation only supports ("bilinear", "nearest"):

assertmethodin ("bilinear", "nearest"), f"{method} is not supported"

So a valid ONNX 5D cubic GridSample model will import successfully but fail later during legalization/compile. Could we either implement 3D cubic, or explicitly reject ndim == 5 and method == "bicubic" in the frontend with a clear NotImplementedError? A regression test for this case would be good too.

  1. While touching InferStructInfoGridSample, there is an existing 4D shape inference mismatch that this PR could fix.

The ONNX frontend permutes the 4D grid from [N, H_out, W_out, 2] to TOPI layout [N, 2, H_out, W_out], but the 4D inference path still reads:

out_tgt_shape.Set(2, grid_shape->values[1]);
out_tgt_shape.Set(3, grid_shape->values[2]);

For a non-square output grid like [N, 2, 3, 5], this infers [N, C, 2, 3] instead of [N, C, 3, 5]. The current 4D test uses [1, 2, 2, 2], so it does not catch this. Since the 5D branch correctly reads the permuted spatial dims from grid_shape->values[2:], I think the 4D branch should do the same (values[2], values[3]) and add a non-square 4D test.

…rence
- onnx frontend: raise NotImplementedError for 5D mode='cubic' (TOPI 3D
grid_sample supports only bilinear/nearest), instead of importing a model
that fails later at legalization
- InferStructInfoGridSample: 4D branch now reads the permuted grid spatial
dims (values[2]/values[3]) to match the frontend's NCHW permutation; fixes
non-square output shape inference
- tests: add 5D cubic rejection test and non-square 4D output shape test
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks for the careful review! Both addressed in 9518915:

  1. The frontend now raises NotImplementedError for 5D mode="cubic" (4D bicubic is still fine via TOPI's 2D path), so an unsupported volumetric-cubic model fails fast at import with a clear message instead of dying later at legalization. Added a regression test.

  2. Fixed the 4D shape-inference mismatch in InferStructInfoGridSample: the 4D branch now reads the permuted spatial dims (values[2]/values[3]) to match the frontend's [N, 2, H_out, W_out] permutation, mirroring the 5D branch. Added a non-square 4D test ([1, 3, 5, 2] -> [1, 3, 3, 5]) that catches the old values[1]/values[2] bug.

I couldn't run pytest locally (no TVM build here), so I'm relying on CI for the compiled checks.

@tlopex

Copy link
Copy Markdown
Member

LGTM! Thanks for the fix!

@tlopex
tlopex merged commit da52d7d into apache:mainJun 18, 2026
6 checks passed
tlopex added a commit to tlopex/tvm that referenced this pull request Jun 18, 2026
The 5D GridSample change (apache#19816) landed with a clang-format violation on
the structured binding for CheckTensorLayout, which fails the repo-wide
pre-commit lint (clang-format v20.1.8). Reformat to satisfy the hook.
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks @tlopex for the quick merge. Supporting 5D volumetric inputs in the ONNX GridSample converter rounds out that frontend.

@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thank you @tlopex. Supporting 5D volumetric inputs in the ONNX GridSample converter closes a real gap in the Relax frontend.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug][Relax][ONNX] GridSample 5D (volumetric) input crashes the frontend

2 participants

@mvanhorn@tlopex
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter - #19816

Merged
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d
Jun 18, 2026
Merged

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter#19816
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d

Conversation

@mvanhorn

Copy link
Copy Markdown
Contributor

Summary

The Relax ONNX frontend's GridSample._impl_v16 converter unconditionally permutes the grid from ONNX [N,H,W,2] to TVM [N,2,H,W] and calls image.grid_sample with layout="NCHW". For 5D volumetric inputs ([N,C,D,H,W] with grid [N,D,H,W,3]) this crashes at permute_dims with an InternalError ('PermuteDims expects the number of input axes to equal the ndim of the input tensor.

Changes

In GridSample._impl_v16, read data.struct_info.ndim and dispatch on rank. For ndim==4, keep the existing permute_dims(grid,[0,3,1,2]) + grid_sample(layout="NCHW").

Fixes#19688

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request extends the ONNX frontend's GridSample operator to support 5D inputs (NCDHW layout) in addition to the existing 4D inputs (NCHW layout), and adds corresponding unit tests. The feedback suggests using the existing helper function _get_known_tensor_rank(data) to determine the input's dimensionality more robustly and idiomatically, rather than manually checking attributes on struct_info.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of manually checking hasattr(data.struct_info, "ndim") and falling back to len(data.struct_info.shape), it is more robust and idiomatic to use the existing helper function _get_known_tensor_rank(data). This helper is used throughout the codebase and safely handles various expression types (e.g., relax.Constant, relax.ShapeExpr, relax.PrimValue, and relax.TensorStructInfo) while avoiding potential AttributeError or TypeError if struct_info or shape is not fully defined.

ndim=_get_known_tensor_rank(data)

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for 5D inputs in the ONNX GridSample operator, mapping it to the NCDHW layout and permuting the grid dimensions accordingly, along with corresponding unit tests. Feedback suggests using the helper function _get_known_tensor_rank(data) instead of directly accessing data.struct_info to safely retrieve the input tensor's rank and avoid potential AttributeErrors.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Directly accessing data.struct_info can lead to an AttributeError if struct_info is None. It is safer and more consistent with the rest of the codebase to use the helper function _get_known_tensor_rank(data) to retrieve the rank of the input tensor.

Suggested change
ifhasattr(data.struct_info, "ndim"):
ndim=data.struct_info.ndim
else:
ndim=len(data.struct_info.shape)
ndim=_get_known_tensor_rank(data)
ifndimisNone:
raiseValueError("GridSample requires a statically known input rank.")

The ONNX frontend dispatches 5D GridSample to the relax grid_sample op with
layout=NCDHW, and TOPI already implements the 3D compute, but
InferStructInfoGridSample hardcoded NCHW so 5D inputs hit a fatal layout
error during StructInfo inference. Branch on the NCDHW layout and derive the
output spatial extents from grid->values[2:], mirroring the existing
Resize3D inference. The 2D NCHW path is unchanged.

@tlopextlopex left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix! @mvanhorn
I found two issues worth addressing before merge:

  1. 5D mode="cubic" is accepted by the ONNX frontend but is not supported by TOPI.

GridSample._impl_v16 translates ONNX mode="cubic" to method="bicubic" and then sends 5D inputs to relax.op.image.grid_sample(..., layout="NCDHW"). However, the TOPI 3D implementation only supports ("bilinear", "nearest"):

assertmethodin ("bilinear", "nearest"), f"{method} is not supported"

So a valid ONNX 5D cubic GridSample model will import successfully but fail later during legalization/compile. Could we either implement 3D cubic, or explicitly reject ndim == 5 and method == "bicubic" in the frontend with a clear NotImplementedError? A regression test for this case would be good too.

  1. While touching InferStructInfoGridSample, there is an existing 4D shape inference mismatch that this PR could fix.

The ONNX frontend permutes the 4D grid from [N, H_out, W_out, 2] to TOPI layout [N, 2, H_out, W_out], but the 4D inference path still reads:

out_tgt_shape.Set(2, grid_shape->values[1]);
out_tgt_shape.Set(3, grid_shape->values[2]);

For a non-square output grid like [N, 2, 3, 5], this infers [N, C, 2, 3] instead of [N, C, 3, 5]. The current 4D test uses [1, 2, 2, 2], so it does not catch this. Since the 5D branch correctly reads the permuted spatial dims from grid_shape->values[2:], I think the 4D branch should do the same (values[2], values[3]) and add a non-square 4D test.

…rence
- onnx frontend: raise NotImplementedError for 5D mode='cubic' (TOPI 3D
grid_sample supports only bilinear/nearest), instead of importing a model
that fails later at legalization
- InferStructInfoGridSample: 4D branch now reads the permuted grid spatial
dims (values[2]/values[3]) to match the frontend's NCHW permutation; fixes
non-square output shape inference
- tests: add 5D cubic rejection test and non-square 4D output shape test
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks for the careful review! Both addressed in 9518915:

  1. The frontend now raises NotImplementedError for 5D mode="cubic" (4D bicubic is still fine via TOPI's 2D path), so an unsupported volumetric-cubic model fails fast at import with a clear message instead of dying later at legalization. Added a regression test.

  2. Fixed the 4D shape-inference mismatch in InferStructInfoGridSample: the 4D branch now reads the permuted spatial dims (values[2]/values[3]) to match the frontend's [N, 2, H_out, W_out] permutation, mirroring the 5D branch. Added a non-square 4D test ([1, 3, 5, 2] -> [1, 3, 3, 5]) that catches the old values[1]/values[2] bug.

I couldn't run pytest locally (no TVM build here), so I'm relying on CI for the compiled checks.

@tlopex

Copy link
Copy Markdown
Member

LGTM! Thanks for the fix!

@tlopex
tlopex merged commit da52d7d into apache:mainJun 18, 2026
6 checks passed
tlopex added a commit to tlopex/tvm that referenced this pull request Jun 18, 2026
The 5D GridSample change (apache#19816) landed with a clang-format violation on
the structured binding for CheckTensorLayout, which fails the repo-wide
pre-commit lint (clang-format v20.1.8). Reformat to satisfy the hook.
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks @tlopex for the quick merge. Supporting 5D volumetric inputs in the ONNX GridSample converter rounds out that frontend.

@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thank you @tlopex. Supporting 5D volumetric inputs in the ONNX GridSample converter closes a real gap in the Relax frontend.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug][Relax][ONNX] GridSample 5D (volumetric) input crashes the frontend

2 participants

@mvanhorn@tlopex
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter - #19816

Merged
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d
Jun 18, 2026
Merged

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter#19816
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d

Conversation

@mvanhorn

Copy link
Copy Markdown
Contributor

Summary

The Relax ONNX frontend's GridSample._impl_v16 converter unconditionally permutes the grid from ONNX [N,H,W,2] to TVM [N,2,H,W] and calls image.grid_sample with layout="NCHW". For 5D volumetric inputs ([N,C,D,H,W] with grid [N,D,H,W,3]) this crashes at permute_dims with an InternalError ('PermuteDims expects the number of input axes to equal the ndim of the input tensor.

Changes

In GridSample._impl_v16, read data.struct_info.ndim and dispatch on rank. For ndim==4, keep the existing permute_dims(grid,[0,3,1,2]) + grid_sample(layout="NCHW").

Fixes#19688

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request extends the ONNX frontend's GridSample operator to support 5D inputs (NCDHW layout) in addition to the existing 4D inputs (NCHW layout), and adds corresponding unit tests. The feedback suggests using the existing helper function _get_known_tensor_rank(data) to determine the input's dimensionality more robustly and idiomatically, rather than manually checking attributes on struct_info.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of manually checking hasattr(data.struct_info, "ndim") and falling back to len(data.struct_info.shape), it is more robust and idiomatic to use the existing helper function _get_known_tensor_rank(data). This helper is used throughout the codebase and safely handles various expression types (e.g., relax.Constant, relax.ShapeExpr, relax.PrimValue, and relax.TensorStructInfo) while avoiding potential AttributeError or TypeError if struct_info or shape is not fully defined.

ndim=_get_known_tensor_rank(data)

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for 5D inputs in the ONNX GridSample operator, mapping it to the NCDHW layout and permuting the grid dimensions accordingly, along with corresponding unit tests. Feedback suggests using the helper function _get_known_tensor_rank(data) instead of directly accessing data.struct_info to safely retrieve the input tensor's rank and avoid potential AttributeErrors.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Directly accessing data.struct_info can lead to an AttributeError if struct_info is None. It is safer and more consistent with the rest of the codebase to use the helper function _get_known_tensor_rank(data) to retrieve the rank of the input tensor.

Suggested change
ifhasattr(data.struct_info, "ndim"):
ndim=data.struct_info.ndim
else:
ndim=len(data.struct_info.shape)
ndim=_get_known_tensor_rank(data)
ifndimisNone:
raiseValueError("GridSample requires a statically known input rank.")

The ONNX frontend dispatches 5D GridSample to the relax grid_sample op with
layout=NCDHW, and TOPI already implements the 3D compute, but
InferStructInfoGridSample hardcoded NCHW so 5D inputs hit a fatal layout
error during StructInfo inference. Branch on the NCDHW layout and derive the
output spatial extents from grid->values[2:], mirroring the existing
Resize3D inference. The 2D NCHW path is unchanged.

@tlopextlopex left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix! @mvanhorn
I found two issues worth addressing before merge:

  1. 5D mode="cubic" is accepted by the ONNX frontend but is not supported by TOPI.

GridSample._impl_v16 translates ONNX mode="cubic" to method="bicubic" and then sends 5D inputs to relax.op.image.grid_sample(..., layout="NCDHW"). However, the TOPI 3D implementation only supports ("bilinear", "nearest"):

assertmethodin ("bilinear", "nearest"), f"{method} is not supported"

So a valid ONNX 5D cubic GridSample model will import successfully but fail later during legalization/compile. Could we either implement 3D cubic, or explicitly reject ndim == 5 and method == "bicubic" in the frontend with a clear NotImplementedError? A regression test for this case would be good too.

  1. While touching InferStructInfoGridSample, there is an existing 4D shape inference mismatch that this PR could fix.

The ONNX frontend permutes the 4D grid from [N, H_out, W_out, 2] to TOPI layout [N, 2, H_out, W_out], but the 4D inference path still reads:

out_tgt_shape.Set(2, grid_shape->values[1]);
out_tgt_shape.Set(3, grid_shape->values[2]);

For a non-square output grid like [N, 2, 3, 5], this infers [N, C, 2, 3] instead of [N, C, 3, 5]. The current 4D test uses [1, 2, 2, 2], so it does not catch this. Since the 5D branch correctly reads the permuted spatial dims from grid_shape->values[2:], I think the 4D branch should do the same (values[2], values[3]) and add a non-square 4D test.

…rence
- onnx frontend: raise NotImplementedError for 5D mode='cubic' (TOPI 3D
grid_sample supports only bilinear/nearest), instead of importing a model
that fails later at legalization
- InferStructInfoGridSample: 4D branch now reads the permuted grid spatial
dims (values[2]/values[3]) to match the frontend's NCHW permutation; fixes
non-square output shape inference
- tests: add 5D cubic rejection test and non-square 4D output shape test
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks for the careful review! Both addressed in 9518915:

  1. The frontend now raises NotImplementedError for 5D mode="cubic" (4D bicubic is still fine via TOPI's 2D path), so an unsupported volumetric-cubic model fails fast at import with a clear message instead of dying later at legalization. Added a regression test.

  2. Fixed the 4D shape-inference mismatch in InferStructInfoGridSample: the 4D branch now reads the permuted spatial dims (values[2]/values[3]) to match the frontend's [N, 2, H_out, W_out] permutation, mirroring the 5D branch. Added a non-square 4D test ([1, 3, 5, 2] -> [1, 3, 3, 5]) that catches the old values[1]/values[2] bug.

I couldn't run pytest locally (no TVM build here), so I'm relying on CI for the compiled checks.

@tlopex

Copy link
Copy Markdown
Member

LGTM! Thanks for the fix!

@tlopex
tlopex merged commit da52d7d into apache:mainJun 18, 2026
6 checks passed
tlopex added a commit to tlopex/tvm that referenced this pull request Jun 18, 2026
The 5D GridSample change (apache#19816) landed with a clang-format violation on
the structured binding for CheckTensorLayout, which fails the repo-wide
pre-commit lint (clang-format v20.1.8). Reformat to satisfy the hook.
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks @tlopex for the quick merge. Supporting 5D volumetric inputs in the ONNX GridSample converter rounds out that frontend.

@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thank you @tlopex. Supporting 5D volumetric inputs in the ONNX GridSample converter closes a real gap in the Relax frontend.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug][Relax][ONNX] GridSample 5D (volumetric) input crashes the frontend

2 participants

@mvanhorn@tlopex
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter - #19816

Merged
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d
Jun 18, 2026
Merged

fix: Support 5D volumetric inputs in ONNX GridSample frontend converter#19816
tlopex merged 3 commits into
apache:mainfrom
mvanhorn:fix/19688-onnx-gridsample-5d

Conversation

@mvanhorn

Copy link
Copy Markdown
Contributor

Summary

The Relax ONNX frontend's GridSample._impl_v16 converter unconditionally permutes the grid from ONNX [N,H,W,2] to TVM [N,2,H,W] and calls image.grid_sample with layout="NCHW". For 5D volumetric inputs ([N,C,D,H,W] with grid [N,D,H,W,3]) this crashes at permute_dims with an InternalError ('PermuteDims expects the number of input axes to equal the ndim of the input tensor.

Changes

In GridSample._impl_v16, read data.struct_info.ndim and dispatch on rank. For ndim==4, keep the existing permute_dims(grid,[0,3,1,2]) + grid_sample(layout="NCHW").

Fixes#19688

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request extends the ONNX frontend's GridSample operator to support 5D inputs (NCDHW layout) in addition to the existing 4D inputs (NCHW layout), and adds corresponding unit tests. The feedback suggests using the existing helper function _get_known_tensor_rank(data) to determine the input's dimensionality more robustly and idiomatically, rather than manually checking attributes on struct_info.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Instead of manually checking hasattr(data.struct_info, "ndim") and falling back to len(data.struct_info.shape), it is more robust and idiomatic to use the existing helper function _get_known_tensor_rank(data). This helper is used throughout the codebase and safely handles various expression types (e.g., relax.Constant, relax.ShapeExpr, relax.PrimValue, and relax.TensorStructInfo) while avoiding potential AttributeError or TypeError if struct_info or shape is not fully defined.

ndim=_get_known_tensor_rank(data)

@gemini-code-assistgemini-code-assistBot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds support for 5D inputs in the ONNX GridSample operator, mapping it to the NCDHW layout and permuting the grid dimensions accordingly, along with corresponding unit tests. Feedback suggests using the helper function _get_known_tensor_rank(data) instead of directly accessing data.struct_info to safely retrieve the input tensor's rank and avoid potential AttributeErrors.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +4997 to +5000
if hasattr(data.struct_info, "ndim"):
ndim = data.struct_info.ndim
else:
ndim = len(data.struct_info.shape)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Directly accessing data.struct_info can lead to an AttributeError if struct_info is None. It is safer and more consistent with the rest of the codebase to use the helper function _get_known_tensor_rank(data) to retrieve the rank of the input tensor.

Suggested change
ifhasattr(data.struct_info, "ndim"):
ndim=data.struct_info.ndim
else:
ndim=len(data.struct_info.shape)
ndim=_get_known_tensor_rank(data)
ifndimisNone:
raiseValueError("GridSample requires a statically known input rank.")

The ONNX frontend dispatches 5D GridSample to the relax grid_sample op with
layout=NCDHW, and TOPI already implements the 3D compute, but
InferStructInfoGridSample hardcoded NCHW so 5D inputs hit a fatal layout
error during StructInfo inference. Branch on the NCDHW layout and derive the
output spatial extents from grid->values[2:], mirroring the existing
Resize3D inference. The 2D NCHW path is unchanged.

@tlopextlopex left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix! @mvanhorn
I found two issues worth addressing before merge:

  1. 5D mode="cubic" is accepted by the ONNX frontend but is not supported by TOPI.

GridSample._impl_v16 translates ONNX mode="cubic" to method="bicubic" and then sends 5D inputs to relax.op.image.grid_sample(..., layout="NCDHW"). However, the TOPI 3D implementation only supports ("bilinear", "nearest"):

assertmethodin ("bilinear", "nearest"), f"{method} is not supported"

So a valid ONNX 5D cubic GridSample model will import successfully but fail later during legalization/compile. Could we either implement 3D cubic, or explicitly reject ndim == 5 and method == "bicubic" in the frontend with a clear NotImplementedError? A regression test for this case would be good too.

  1. While touching InferStructInfoGridSample, there is an existing 4D shape inference mismatch that this PR could fix.

The ONNX frontend permutes the 4D grid from [N, H_out, W_out, 2] to TOPI layout [N, 2, H_out, W_out], but the 4D inference path still reads:

out_tgt_shape.Set(2, grid_shape->values[1]);
out_tgt_shape.Set(3, grid_shape->values[2]);

For a non-square output grid like [N, 2, 3, 5], this infers [N, C, 2, 3] instead of [N, C, 3, 5]. The current 4D test uses [1, 2, 2, 2], so it does not catch this. Since the 5D branch correctly reads the permuted spatial dims from grid_shape->values[2:], I think the 4D branch should do the same (values[2], values[3]) and add a non-square 4D test.

…rence
- onnx frontend: raise NotImplementedError for 5D mode='cubic' (TOPI 3D
grid_sample supports only bilinear/nearest), instead of importing a model
that fails later at legalization
- InferStructInfoGridSample: 4D branch now reads the permuted grid spatial
dims (values[2]/values[3]) to match the frontend's NCHW permutation; fixes
non-square output shape inference
- tests: add 5D cubic rejection test and non-square 4D output shape test
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks for the careful review! Both addressed in 9518915:

  1. The frontend now raises NotImplementedError for 5D mode="cubic" (4D bicubic is still fine via TOPI's 2D path), so an unsupported volumetric-cubic model fails fast at import with a clear message instead of dying later at legalization. Added a regression test.

  2. Fixed the 4D shape-inference mismatch in InferStructInfoGridSample: the 4D branch now reads the permuted spatial dims (values[2]/values[3]) to match the frontend's [N, 2, H_out, W_out] permutation, mirroring the 5D branch. Added a non-square 4D test ([1, 3, 5, 2] -> [1, 3, 3, 5]) that catches the old values[1]/values[2] bug.

I couldn't run pytest locally (no TVM build here), so I'm relying on CI for the compiled checks.

@tlopex

Copy link
Copy Markdown
Member

LGTM! Thanks for the fix!

@tlopex
tlopex merged commit da52d7d into apache:mainJun 18, 2026
6 checks passed
tlopex added a commit to tlopex/tvm that referenced this pull request Jun 18, 2026
The 5D GridSample change (apache#19816) landed with a clang-format violation on
the structured binding for CheckTensorLayout, which fails the repo-wide
pre-commit lint (clang-format v20.1.8). Reformat to satisfy the hook.
@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thanks @tlopex for the quick merge. Supporting 5D volumetric inputs in the ONNX GridSample converter rounds out that frontend.

@mvanhorn

Copy link
Copy Markdown
ContributorAuthor

Thank you @tlopex. Supporting 5D volumetric inputs in the ONNX GridSample converter closes a real gap in the Relax frontend.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug][Relax][ONNX] GridSample 5D (volumetric) input crashes the frontend

2 participants

@mvanhorn@tlopex