Skip to content

Allow arithmetic in lifted differentiable constraints#12029

Merged
saipraveenb25 merged 2 commits into
shader-slang:masterfrom
saipraveenb25:codex/fix-differentiable-generic-arithmetic
Jul 10, 2026
Merged

Allow arithmetic in lifted differentiable constraints#12029
saipraveenb25 merged 2 commits into
shader-slang:masterfrom
saipraveenb25:codex/fix-differentiable-generic-arithmetic

Conversation

@saipraveenb25

@saipraveenb25 saipraveenb25 commented Jul 9, 2026

Copy link
Copy Markdown
Collaborator

Motivation

Consider this example:

interface IModel<TInput, TOutput> {}

struct Sampler<
    int LatentCount,
    int LobeCount,
    int SpecularCount = LobeCount - 1,
    Network : IModel<float[3 + LatentCount], float[3 + 6 * SpecularCount]>> : IFunction
{
    [BackwardDifferentiable]
    float forward(float input) { return input; }
}

A differentiable method is registered by synthesizing generic extensions for its forward- and backward-differentiability conformances. Before this change, the lifted extension for forward could not be applied when an enclosing constraint contained arithmetic such as 3 + LatentCount or 3 + 6 * SpecularCount. As a result, conformance checking reported that the visibly [BackwardDifferentiable] method did not provide the required differentiability.

Proposed solution

Make generic integer-value unification distinguish "known mismatch" from "not decomposed by this helper." Distinct integer constants still fail immediately, and direct generic value parameters still produce ordinary-argument constraints. If both sides are integer values but neither path proves a mismatch or adds a direct binding, unification now returns success without adding a constraint.

This matches how the rest of generic unification is used: it should return false when it has a definite local mismatch, not when it merely lacks an algebraic proof for dependent expressions. A pair such as N + 1 and M + 1 might become equal after surrounding generic arguments are known, while a pair such as N + 1 and N + 2 will be rejected by the later checking/proof path rather than by this inference helper.

This keeps the checked semantic values produced by liftDeclFromGenericContainers as the source of truth. It does not reconstruct arithmetic syntax, add a custom equivalence relation for integer expressions, or weaken final generic-constraint validation.

Change summary

  • Update SemanticsVisitor::TryUnifyVals so non-constant integer values that cannot be decomposed into a direct generic-parameter binding are treated as compatible inference hints instead of immediate failures.
  • Add a Vulkan-capable compute regression covering primal and backward results for addition, subtraction, multiplication, division, remainder, symbolic unary negation, parentheses, multiple model arguments, and a dependent default generic value.

Concepts and vocabulary

  • Lifted extension: the module-scope generic extension synthesized for a differentiable method nested in one or more generic containers.
  • Declared subtype witness: the semantic proof argument associated with a source constraint such as Network : IModel<...>.
  • Inference hint: information collected while matching a generic target; unlike a proof, it may be incomplete until other generic arguments are solved.
  • PolynomialIntVal / BuiltinOperationIntVal: canonical semantic representations used for symbolic integer arithmetic. Addition, subtraction, multiplication, and negation use the former; operations such as division and remainder use the latter.

Process report

SemanticsDeclHeaderVisitor::checkDifferentiableCallableCommon synthesizes differentiability extensions through extendContainerDecl. Because the method is nested in Sampler, liftDeclFromGenericContainers clones the enclosing generic parameters and constraints. The cloned constraint is intentionally expressed using fresh parameters, so the original witness contains arithmetic over LatentCount while the lifted witness contains the same canonical arithmetic over a fresh lifted parameter.

When applyExtensionToType matches the synthesized extension back to the method's function type, TryUnifyTypes reaches tryUnifyGenericAppDeclRef. The generic applications include their declared constraint witnesses. TryUnifyVals compares the witnesses' supertypes to discover ordinary-argument relationships and to reject real shape mismatches.

Without this change, that recursive comparison fails inside the arithmetic IntVal sub-expression. For example, the repro hits TryUnifyVals with the witness supertypes IModel<float[N+1]> and IModel<float[N+1]>, and then with their array-size values N+1 and N+1. The printed expressions are the same, but their N operands come from different generic declarations. Because the values are PolynomialIntVal / BuiltinOperationIntVal rather than direct DeclRefIntVals, getDeclRefIntValIgnoringCasts finds no parameter on either whole expression and ordinary integer unification used to return false. That false bubbled back through the declared-witness comparison, so the valid lifted extension was discarded before the generic solver could substitute inferred arguments and prove the witness.

The input shape is canonical and intentional: lifting must create fresh generic parameters, and PolynomialIntVal / BuiltinOperationIntVal already preserve and substitute the checked arithmetic correctly. Fixing the producer or rebuilding an expression would create a second representation of the same semantic value. A custom arithmetic matcher would duplicate canonicalization and generic solving. The fix therefore keeps the existing direct-parameter inference path, preserves constant mismatch rejection, and treats all remaining integer-value pairs as potentially unifiable.

The regression fails without the TryUnifyVals change and passes with it. Validation performed:

  • Debug slang target built successfully.
  • tests/autodiff/generic-container-arithmetic-constraint passes with -api vk.
  • Focused related checks pass with -api vk: tests/autodiff/callable-constraint-witness-rollback, tests/autodiff/autodiff-generic-where-clause, tests/bugs/polynomial-int-subst, and tests/autodiff/dynamic-dispatch-autodiff-static-generic-uint.
  • tests/language-feature/generics passes with -api vk: 149/149 passed, 86 ignored.
  • Full tests/autodiff Vulkan run: 307/309 passed; the two failures are the existing fwd-diff-forceinline debug-info checks.
  • Repository formatting check and git diff --check pass.

@saipraveenb25 saipraveenb25 added the pr: non-breaking PRs without breaking changes label Jul 9, 2026
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR updates constraint unification so selected integer and declared-subtype witness comparisons no longer fail the matching path. It also adds an autodiff compute test covering generic wrappers with arithmetic-dependent shape constraints.

Changes

Constraint unification behavior change

Layer / File(s) Summary
Deferred proof in TryUnifyVals
source/slang/slang-check-constraint.cpp
Integer parameter unification is attempted in both directions and ignored as a pass/fail gate, and the declared subtype witness sup-type comparison no longer blocks compatibility on TryUnifyTypes failure.

Autodiff generic-container arithmetic constraint test

Layer / File(s) Summary
Test scaffolding and generic wrappers
tests/autodiff/generic-container-arithmetic-constraint.slang
Adds compute/vulkan/cuda test directives, generic model and function interfaces, concrete model structs, and wrapper types with dependent arithmetic constraints and defaults.
Evaluation entry points and compute kernel
tests/autodiff/generic-container-arithmetic-constraint.slang
Adds four [BackwardDifferentiable] helpers plus computeMain, which evaluates them, runs bwd_diff, and writes checked primal and gradient outputs to outputBuffer.

Suggested reviewers: bmillsNV, expipiplus1

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: allowing arithmetic in lifted differentiable constraints.
Description check ✅ Passed The description is directly related to the code and test changes in this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@saipraveenb25
saipraveenb25 marked this pull request as ready for review July 9, 2026 18:24
@saipraveenb25
saipraveenb25 requested a review from a team as a code owner July 9, 2026 18:24
@saipraveenb25
saipraveenb25 requested review from bmillsNV and removed request for a team July 9, 2026 18:24
@jhelferty-nv
jhelferty-nv removed the request for review from bmillsNV July 9, 2026 18:24

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 10245ead-75df-4da4-89e1-dca7a44628b4

📥 Commits

Reviewing files that changed from the base of the PR and between a97110a and a515458.

📒 Files selected for processing (2)
  • source/slang/slang-check-constraint.cpp
  • tests/autodiff/generic-container-arithmetic-constraint.slang

Comment on lines +1 to +3
//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-slang -compute -shaderobj -output-using-type
//TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-vk -compute -shaderobj -output-using-type
//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-cuda -compute -shaderobj -output-using-type

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.

📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

Does Slang autodiff bwd_diff work on the CPU (llvm) and interpreter compute targets?

💡 Result:

Yes, Slang's bwd_diff (backward-mode automatic differentiation) is supported on the CPU compute target [1][2]. Slang's automatic differentiation system is designed to be largely target-independent [1]. Development and regression testing for autodiff features—including backward differentiation through complex constructs like dynamic dispatch and generic interfaces—regularly utilize the CPU target (often explicitly via the -cpu flag) to verify correctness [1][2]. Regarding the "interpreter" compute target, Slang's compute targets generally refer to backends capable of executing Slang code. While Slang provides a CPU target that supports execution via C++ or LLVM [3][4], official documentation and development activity indicate that backward differentiation works in these CPU-based execution environments [1][2]. If you are referring to a specific "interpreter" mode, please note that Slang's autodiff functionality is primarily verified against its supported compute backends (CPU, Vulkan, CUDA, etc.) to ensure derivative propagation is consistent across them [1][2]. Summary of key points: - Functionality: bwd_diff is a standard operator in Slang for reverse-mode autodiff [5][6]. - CPU Support: Full support exists for bwd_diff on the CPU target [1][2]. - Reliability: CPU-based testing is a standard practice in the Slang project for validating autodiff logic because the underlying derivative propagation is independent of the compute backend [1].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file =="
cat -n tests/autodiff/generic-container-arithmetic-constraint.slang

echo
echo "== nearby autodiff tests using CPU/interpreter =="
rg -n "//TEST(:|\().*(-cpu|INTERPRET|COMPARE_COMPUTE)" tests/autodiff -g '*.slang' || true

echo
echo "== nearby generic-container autodiff tests =="
rg -n "generic-container|arithmetic-constraint|autodiff" tests/autodiff -g '*.slang' || true

Repository: shader-slang/slang

Length of output: 50374


Add a -cpu case for this regression.

This front-end constraint-unification bug is target-independent, and the current directives only exercise Slang/Vulkan/CUDA. A -cpu run would cover the same path without depending on GPU execution.

Sources: Coding guidelines, Learnings

github-actions[bot]

This comment was marked as outdated.

@saipraveenb25
saipraveenb25 force-pushed the codex/fix-differentiable-generic-arithmetic branch 2 times, most recently from 78d5b61 to 43c9a07 Compare July 9, 2026 19:59

@coderabbitai coderabbitai Bot 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
source/slang/slang-check-constraint.cpp (1)

3551-3564: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not let declared-witness hint comparison reject the candidate.

This still returns the result of TryUnifyTypes on the two sup types, so a failed arithmetic hint comparison rejects before the normal substituted witness proof runs. Per the PR objective, this path should mine hints only; GenericArgumentSolver::solveWitnessConstraint() should remain the accept/reject boundary.

Suggested fix
-            return TryUnifyTypes(
+            TryUnifyTypes(
                 constraints,
                 unificationOptions,
                 getSup(m_astBuilder, constraintDecl1),
                 getSup(m_astBuilder, constraintDecl2));
+            return true;

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 266736eb-b344-4082-864d-d785b3c8d809

📥 Commits

Reviewing files that changed from the base of the PR and between 78d5b61 and 43c9a07.

📒 Files selected for processing (2)
  • source/slang/slang-check-constraint.cpp
  • tests/autodiff/generic-container-arithmetic-constraint.slang

github-actions[bot]

This comment was marked as outdated.

@saipraveenb25
saipraveenb25 force-pushed the codex/fix-differentiable-generic-arithmetic branch from 43c9a07 to ac959d7 Compare July 9, 2026 20:30
github-actions[bot]

This comment was marked as outdated.

@nv-slang-bot nv-slang-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Verdict: 🟡 Has issues — 2 gaps (non-blocking)

Thanks for this — it's a small, well-motivated fix with an unusually thorough description, and the change sits at a defensible layer (the inference helper, not a syntax reconstruction or a bespoke arithmetic matcher). On the paths the reviewers could trace, the relaxation looks sound because the witness is re-proved authoritatively downstream. The two asks below are what would make the correctness argument locally verifiable rather than "plausible"; neither is a blocker, and both are things only the author can close.

The two high-value asks

1. Prove the deferral's safety net, and reconcile the description with the code. source/slang/slang-check-constraint.cpp:3544

The integer-value branch of TryUnifyVals now returns true unconditionally for any IntVal/IntVal pair that doesn't decompose into a directly bindable generic value parameter. Previously this path returned okay (i.e. false unless a TryUnifyIntParam binding succeeded), so arithmetic pairs like N+1 vs M+1 reported "no unification"; now they report success and record no constraint.

Two things would make this easy for a reviewer to trust:

  • The PR description frames this as a UnificationOptions::deferDependentIntValProof mode "used only while comparing the supertypes of two declared subtype witnesses." That flag isn't in the current diff — the relaxation is unscoped, so it applies to every caller of TryUnifyVals (overload resolution, applyExtensionToType, generic-this-type checks), not just the witness recursion. Either re-introduce the scoping so the return true; is gated to the declared-subtype-witness path (keeping the false rejection elsewhere), or update the description to own the broader scope and say why it's safe for the general case.
  • The new comment states that an unsatisfiable pair like N+1 vs N+2 "will be rejected by the later checking/proof path." That's the load-bearing claim, but every case in the new test is a satisfiable constraint, so nothing exercises the rejection. A negative regression — a lifted constraint whose arithmetic genuinely can't hold (e.g. a model whose array size can't satisfy the constraint, or N+1 vs N+2 for the same N) that still produces a conformance error — would turn "asserted" into "tested." Naming the exact function that performs that later rejection in the comment would also help.

2. Add a -cpu directive so the regression runs GPU-free. tests/autodiff/generic-container-arithmetic-constraint.slang:1

The fix is entirely in front-end generic-constraint solving, which is target-independent — without the fix these shaders fail to compile on every target, so a CPU config exercises the exact regression. But all three directives target GPU configs (-slang -compute, -vk, -cuda) with no -cpu / //TEST:INTERPRET, so the test is effectively skipped in GPU-less CI. 61 existing tests/autodiff/*.slang files already carry a -cpu line. Suggest adding:

//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-cpu -compute -output-using-type -shaderobj

Minor

Comment slightly overstates the earlier guard. source/slang/slang-check-constraint.cpp:3541

Since distinct constants were already rejected above …

The early guard (line 3516) only rejects when both operands are bare ConstantIntVal. A ConstantIntVal paired with a TypeCastIntVal-wrapped constant, or with a single-constant-term PolynomialIntVal, isn't caught above (the branch doesn't resolve()/fold the operands) and reaches this return true;. Tightening the wording to say precisely which pairs are filtered above (both-ConstantIntVal only) would keep the comment accurate. Non-blocking.

The test itself is genuinely good — it covers addition, subtraction, multiplication, division, remainder, unary negation, parentheses, a dependent default, and multiple model arguments, with both primal and backward checks, and the expected values all verify by hand. The only gap is the rejection side.

reviewed at HEAD ac959d7

🤖 Generated by an automated Slang coworker — may be inaccurate. A human maintainer should verify.

@github-actions github-actions Bot 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.

Verdict: 🟡 Has issues — 3 gap(s), 1 question

This PR makes generic integer-value unification in TryUnifyVals return true (compatible inference hint) instead of false for non-constant IntVal pairs that don't decompose into a direct generic-parameter binding, so a lifted [BackwardDifferentiable] extension whose enclosing constraint contains arithmetic (e.g. float[3 + LatentCount]) can be matched back to the method. The change is sound for the two dominant callers (overload inference ignores the result; applyExtensionToType re-checks with equals), but the residual risk sits in a third caller with no post-solve re-validation, and the test suite covers only the positive direction.

Changes Overview

Generic value unification (source/slang/slang-check-constraint.cpp)

  • TryUnifyVals: for two non-constant IntVals, still attempts a direct TryUnifyIntParam binding on each side, but now returns true unconditionally instead of returning whether a binding was made. Distinct-constant rejection (canonical ConstantIntVal pairs) and direct value-parameter binding are preserved.

Regression test (tests/autodiff/generic-container-arithmetic-constraint.slang)

  • New Vulkan/D3D/CUDA compute test covering primal + backward results for +, -, *, /, %, unary negation, parentheses, multiple model arguments, and a dependent arithmetic default in a lifted differentiable constraint.
Findings (4 total)
Severity Location Finding
🔵 Question source/slang/slang-check-constraint.cpp:3544 canSolveGenericThisTypeCompatibility trusts the new true with no post-solve equals re-check, unlike the other two callers; also TryUnifyIntParam results now silently discarded
🟡 Gap source/slang/slang-check-constraint.cpp:3541 "distinct constants already rejected above" only true for canonical ConstantIntVal pairs — cast-wrapped/unfolded constant mismatches now unify as true
🟡 Gap tests/autodiff/generic-container-arithmetic-constraint.slang:78 No negative test that a genuine arithmetic mismatch is still rejected by the later proof path
🟡 Gap tests/autodiff/generic-container-arithmetic-constraint.slang:3 No CPU/interpreter variant — test is skipped entirely in GPU-less CI

reviewed: dc08a39 · diff sha256 b62b992e4341

// inference pass can decide. Since distinct constants were already rejected above, leave
// unresolved non-constant pairs to the later checking/proof path instead of rejecting them
// here.
return true;

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.

🔵 Question: return true is re-validated by two of the three callers — confirm the third is safe

The change turns a definite false (no direct binding made) into unconditional true. Tracing the three consumers of this boolean:

  1. Overload resolution (slang-check-overload.cpp:~2996) — a false was already ignored for non-type-pack args, so the change is inert here. Safe.
  2. applyExtensionToType (slang-check-decl.cpp:~16733) — guarded by a final if (!type->equals(targetType)) return DeclRef<ExtensionDecl>(); (~16789), which catches any wrong solve. Safe — and this is the path the new test exercises.
  3. canSolveGenericThisTypeCompatibility (slang-check-decl.cpp:~18118) — rejects only on TryUnifyTypes==false, then returns true whenever trySolveGenericArguments succeeds, with no post-solve equals re-check.

The residual risk is concentrated in (3): when two this-types differ only in a value-parameter arithmetic term that this routine cannot bind (e.g. float[1+N] vs float[2+N], where neither side decomposes to a DeclRefIntVal), unification now adds no constraint yet returns true. Whether an incompatible derivative this-type is then accepted depends entirely on whether the solver leaves N unconstrained-but-defaulted (accept — wrong) or unsolved (reject — safe).

The binary decision: is the generic solver intended to be the sole proof for the this-type-compatibility path? If yes, please verify canSolveGenericThisTypeCompatibility cannot succeed with a value parameter left at a default when the two arithmetic terms are genuinely unequal. If that guarantee doesn't hold, mirror the post-solve this-type equals/subtype re-check that applyExtensionToType already has at slang-check-decl.cpp:~16789.

Separately on this block: the two TryUnifyIntParam call results are now discarded. TryUnifyIntParam returns false for reasons unrelated to arithmetic — e.g. !isRelevantGeneric(...) (~3744) or a non-value-param DeclRef (~3797). The comment justifies only the "cannot decompose symbolic arithmetic" case; it does not address a decomposable-but-irrelevant parameter, where the old code returned false and the new code returns true. Worth a sentence on why discarding that result is also correct.

// Other non-constant integer values are harder: this routine does not solve arithmetic
// equations or prove symbolic inequality. For example, `N + 1` and `M + 1` may become
// equal after substitution, while `N + 1` and `N + 2` cannot; both are outside what this
// inference pass can decide. Since distinct constants were already rejected above, leave

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.

🟡 Gap: "distinct constants were already rejected above" only holds for canonical ConstantIntVal pairs

The comment's premise is that the earlier guard rejects mismatched constants. But that guard (lines 3516–3522) fires only when both operands are ConstantIntVal:

if (auto fstIntVal = as<ConstantIntVal>(fst))
    if (auto sndIntVal = as<ConstantIntVal>(snd))
        return fstIntVal->getValue() == sndIntVal->getValue();

A constant that arrives wrapped — TypeCastIntVal(int, ConstantIntVal(3)) — is not a ConstantIntVal, so it skips that guard. The existence of getDeclRefIntValIgnoringCasts (which strips TypeCastIntVal) in this very branch shows cast-wrapped values are expected here. After stripping, the base is a ConstantIntVal, not a DeclRefIntVal, so no binding is attempted and control now falls to the unconditional return true. The same applies to an unfolded PolynomialIntVal/BuiltinOperationIntVal whose sub-terms are all constant but which hasn't resolved to ConstantIntVal. So a mismatched pair like int(3) vs int(5) in one of these non-canonical forms now unifies as true, where the old code returned false.

Suggestion: Before return true, resolve/fold both operands and, when both reduce to constants, compare them and reject on mismatch (the existing arePackCountExpectedCountsEqual/coercePackCountExpectedCountToInt machinery around lines 915–947 already compares int values by canonical value). At minimum, narrow the comment to say only canonical ConstantIntVal-vs-ConstantIntVal mismatches are rejected above, so a future reader doesn't over-trust the guard.

Comment thread tests/autodiff/generic-container-arithmetic-constraint.slang
@@ -0,0 +1,140 @@
//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-slang -compute -shaderobj -output-using-type
//TEST(compute, vulkan):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-vk -compute -shaderobj -output-using-type
//TEST(compute):COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-cuda -compute -shaderobj -output-using-type

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.

🟡 Gap: no CPU/interpreter variant — test is skipped entirely in GPU-less CI

The three directives target only D3D (-slang), Vulkan (-vk), and CUDA (-cuda), all of which require a GPU. But the changed code path (TryUnifyVals, front-end generic inference) is entirely target-independent and runs during semantic checking for every target. On GPU-less runners this test is skipped, so the fix gets zero executed coverage there.

Since ~94 existing tests/autodiff/* files already carry a -cpu line, adding a CPU variant is idiomatic and lets GPU-less environments both exercise the inference change and verify the numeric CHECK buffer values at runtime:

//TEST:COMPARE_COMPUTE_EX(filecheck-buffer=CHECK):-cpu -compute -shaderobj -output-using-type

@saipraveenb25
saipraveenb25 enabled auto-merge July 10, 2026 03:20
@saipraveenb25
saipraveenb25 added this pull request to the merge queue Jul 10, 2026
Merged via the queue into shader-slang:master with commit 824e24f Jul 10, 2026
48 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr: non-breaking PRs without breaking changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants