Skip to content

[ET-VK][binary] Select binary ops with a specialization constant - #24717

Merged
SS-JIA merged 1 commit into
gh/SS-JIA/689/origfrom
gh/SS-JIA/690/orig
Nov 6, 2026
Merged

SS-JIA merged 1 commit into
gh/SS-JIA/689/origfrom
gh/SS-JIA/690/orig

Conversation

@pytorchbot

Copy link
Copy Markdown
Collaborator

This PR was created by the merge bot to help merge the original PR into the main branch.
ghstack PR number: #24695 by @SS-JIA
^ Please use this as the source of truth for the PR details, comments, and reviews
ghstack PR base: https://github.com/pytorch/executorch/tree/gh/SS-JIA/690/base
ghstack PR head: https://github.com/pytorch/executorch/tree/gh/SS-JIA/690/head
Merge bot PR base: https://github.com/pytorch/executorch/tree/gh/SS-JIA/689/orig
Merge bot PR head: https://github.com/pytorch/executorch/tree/gh/SS-JIA/690/orig
Differential Revision: D130014628
@diff-train-skip-merge

## Ulterior Motive

Preparing ET-VK binary ops for operator fusion, such as folding DSR's
`y + x * scale` residual into the preceding convolution. A fused shader needs a
shared implementation of every binary op it can apply, instead of a separate
shader per op.

## Rationale

**What**: Every binary op of a storage type and dtype now dispatches one shader.
The `op_type` specialization constant selects the op, and `should_broadcast`
selects between broadcast indexing and direct indexing. The op implementations
move to `binary_op.glslh` as `apply_binary_op()`. `q8ta_add` uses the same
header and constant.

**Why**: Fusion shaders can include `binary_op.glslh` to apply any binary op.
Generated binary shaders drop from 80 to 14. Equal-shape inputs skip the
broadcast index math.

## Details

- Shader variants
  - **Before**: one per op, storage and dtype (`binary_add_texture3d_half`,
    `binary_mul_buffer_float`, ...), each with the op expression baked in by
    codegen.
  - **After**: `binary_op_{texture3d,buffer}_{half,float,int32,uint8}` for
    arithmetic, `swiglu` and bitwise ops (bitwise for uint8 only), and
    `binary_cmp_{texture3d,buffer}_{half,float,int32}` for comparisons, which
    write uint8.
- Op selection
  - **Before**: the kernel name (`"binary_" + op + storage + dtype`).
  - **After**: `op_type` (specialization constant 8), from `BinaryOpType` in
    `BinaryOp.h`; values must match `binary_op.glslh`. The driver folds the
    switch at pipeline creation; every op/flag combination checked compiles to
    the same Adreno ISA as the old per-op shader.
- Equal-shape inputs
  - **Before**: texture shaders always converted positions through tensor
    indices; buffer shaders compared input metadata at runtime.
  - **After**: `should_broadcast` (specialization constant 9) is 0 when `out`,
    `in` and `other` share sizes and hashed layout, so all three share texel
    positions or buffer indices. It is fixed when the graph is built, like the
    existing packed-dim broadcast flags.
- q8ta add
  - **Before**: `q8ta_add_buffer`, with `X + Y` baked in by codegen.
  - **After**: `q8ta_binary_buffer`, which calls `apply_binary_op()` with
    `op_type` (specialization constant 7). `add_q8ta_binary_node()` takes a
    `BinaryOpType` instead of an op name; the enum moves to `BinaryOp.h` so
    both files share it.
- Kernel names in profiles: `binary_op_*` / `binary_cmp_*` for every op, and
  `q8ta_binary_buffer` for q8ta add; the op is no longer part of the name.
- Benchmark references, example configs and tests use the new shader names.

A fusion shader declares `op_type`, defines the operand types, and includes the
header:

```glsl
#define IN_T VEC4_T
#define OUT_T VEC4_T
#define ALPHA_T float
#define BINARY_OP_VEC4
#define BINARY_OP_IS_FLOAT
${layout_declare_spec_const(C, "int", "op_type", "0")}
#include "binary_op.glslh"
...
out_texel = apply_binary_op(conv_texel, residual_texel, alpha);
```

Differential Revision: [D130014628](https://our.internmc.facebook.com/intern/diff/D130014628/)


ghstack-source-id: 466197009
Pull-Request: #24695
@pytorchbot
pytorchbot requested a review from SS-JIA as a code owner November 6, 2026 01:22
@pytorch-bot

pytorch-bot Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

🔗 Helpful Links

🧪 See artifacts and rendered test results at hud.pytorch.org/pr/pytorch/executorch/24717

Note: Links to docs will display an error until the docs builds have been completed.

❌ 135 New Failures, 7 Unrelated Failures, 10 Unclassified Failures

As of commit 4b2ce2c with merge base 728e13f (image):

NEW FAILURES - The following jobs have failed:

UNCLASSIFIED FAILURES - DrCI could not classify the following jobs because the workflow did not run on the merge base. The failures may be pre-existing on trunk or introduced by this PR:

FLAKY - The following jobs failed but were likely due to flakiness present on trunk:

This comment was automatically generated by Dr. CI and updates every 15 minutes.

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Nov 6, 2026
@SS-JIA
SS-JIA added this pull request to stack #24719 November 6, 2026 03:05
@SS-JIA
SS-JIA merged commit 6f9d322 into main Nov 6, 2026
88 of 242 checks passed
@SS-JIA
SS-JIA deleted the gh/SS-JIA/690/orig branch November 6, 2026 03:06

This branch had an error being deployed

1 failed deployment
cadence — 4b2ce2cd Deployed Nov 6, 2026 by pytorchbot via vision-build / vision #36988
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants