Skip to content

[HLSL] Add LinAlg FP8 input-vector and bias role coverage - #8869

Merged
Jack Elliott (JoeCitizen) merged 1 commit into
microsoft:mainfrom
JoeCitizen:linalg-hlk-fp8-roles
Sep 2, 2026
Merged

[HLSL] Add LinAlg FP8 input-vector and bias role coverage#8869
Jack Elliott (JoeCitizen) merged 1 commit into
microsoft:mainfrom
JoeCitizen:linalg-hlk-fp8-roles

Conversation

@JoeCitizen

@JoeCitizen Jack Elliott (JoeCitizen) commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

The existing FP8 MatVec coverage only exercises FP8 as the matrix component type, but proposal 0035 requires every implementation to support both FP8 formats for matrices, bias and input vectors. This adds the two remaining roles, which are not the same kind of thing: the input-vector cells go through the existing private builtin because the interpretation is an immarg on the DXIL op and VectorInputType is its own capability field, while the bias cells need the public dx::linalg header because the private builtin shares one component type between bias and result.

Assisted-by: GitHub Copilot

The existing FP8 MatVec coverage only exercises FP8 as the *matrix*
component type. Proposal 0035 requires all three roles:

  "The DirectX API specification requires that all implementations
   support both FP8 formats for matrices, bias, and input vectors"
  (proposals/0035-linalg-matrix.md:2049-2053)

This adds the two remaining roles. They are not the same kind of thing,
and the difference is why they are implemented differently.

Input vector: a real driver capability.
The interpretation is an immarg on the DXIL MatVec op and
VectorInputType is its own field in the D3D12 capability query, so this
is expressible through the existing private-builtin shader. A D3D12
probe confirms WARP answers supported=1 for both FP8 formats as the
vector type with an F16 matrix.

Bias: not a distinct MatVec capability.
Verified from two independent directions before writing any test. The
lowered DXIL shows the bias arriving at the builtin as *native F16*
after a separate dx.op.linAlgConvert, so by the time MatVecMulAdd sees
it there is no FP8 left to support. The API agrees: querying an FP8
bias type returns supported=0, while an F32 bias control also returns
0, so the field discriminates rather than being ignored. The value is
therefore in exercising the header's VectorRef load -> Convert ->
truncate chain end to end, not in a new capability.

The private builtin shares one component type between bias and result,
so an interpreted bias is only expressible through the public
dx::linalg header. Hence the new MatVecMulAddMemoryBiasShader and the
BiasFromMemory flag. It reuses the existing bindings and root
signature, so only the bias path differs from the register-bias cases.
querySupport asks the driver about ResultType rather than
BiasInputType for these cases, because that is what the lowered DXIL
actually carries.

Both roles are classified Mandatory. FP8 is required functionally even
where it is not native: "the driver is required to emulate them. This
emulation is required" (D3D12LinearAlgebraRuntimeFeatureSupport.md:427).

Closing a harness gap first.
encodeByte handled only I8/U8 and returned nullopt for FP8, so packing
an FP8 input vector failed outright, while encodeComponents carried a
separate duplicate FP8 codec. The codec now lives in encodeByte and
encodeComponents delegates, which both fixes the gap and removes the
duplication. The round-trip check is load-bearing: the oracle is an
exact integer dot product and cannot absorb a rounded input, so a value
that is not exactly representable now reports loudly instead of
silently producing a wrong expectation. All chosen values stay within
the set that is exact in E5M2, which has only two mantissa bits.

No convert capability gate is applied. There is no convert entry in
D3D12_LINEAR_ALGEBRA_OPERATION_TYPE to gate on, and FP8 conversion
support is mandatory regardless.

Validation on WARP: 82/80/0/2, against a 78/76/0/2 baseline on
upstream/main. Compared per test rather than by totals: four tests
added, zero outcome changes among the pre-existing 78. The two
non-passing are the pre-existing I32 contention skips.

Assisted-by: GitHub Copilot
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 83725f5d-8e98-4c1d-91ee-ad47629e007b

Copilot AI 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.

Pull request overview

Adds runtime coverage for FP8 input-vector and memory-bias roles in linear algebra matrix-vector operations.

Changes:

  • Extends byte encoding to FP8 components.
  • Adds public-header shader coverage for FP8 memory bias.
  • Adds mandatory tests for both FP8 formats.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

1, 0, -1, 2, -2, 3, -3, 1, 0, 1, 2, -1, 3, -2, 1, -3,
-1, 2, 0, 1, -2, 1, 3, -1, 2, -1, 1, 0, 1, -3, -2, 3,
};
// Only 0 through 8 are exactly representable in both FP8 formats.

@alsepkow Alex Sepkowski (alsepkow) 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.

LGTUS: Joshua Batista (@bob80905)
One minor nit.

const std::optional<BYTE> Encoded = encodeHalfToFP8(Half, Type);
// The oracle is an exact integer dot product, so reject rounded inputs.
const std::optional<float> RoundTrip =
Encoded ? decodeFP8ToFloat(*Encoded, Type) : std::optional<float>();

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.

nit:

Suggested change
Encoded ? decodeFP8ToFloat(*Encoded, Type) : std::optional<float>();
Encoded ? decodeFP8ToFloat(*Encoded, Type) : std::nullopt;

@JoeCitizen
Jack Elliott (JoeCitizen) merged commit 55ea110 into microsoft:main Sep 2, 2026
15 checks passed
@github-project-automation github-project-automation Bot moved this from New to Done in HLSL Roadmap Sep 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants