HLSL Specifications

INF-0007 - DXC Vulkan SDK Release Strategy

StatusUnder Consideration
Authors
Sponsors
  • Impacted Projects: DXC

Introduction

DXC is included in the Vulkan SDK. Before each SDK release, the DXC submodule references (SPIRV-Headers, SPIRV-Tools) need to be updated and the product needs to be tested. This process has previously been mostly performed manually. This document details the requirements for ensuring DXC is ready for inclusion in the Vulkan SDK and proposes the changes required in order to satisfy them.

Motivation

SPIRV-Headers and SPIRV-Tools need to be kept up to date so that the most recent SPIRV features are available in DXC. We need to verify that DXC is generating valid SPIRV code and that there are no regressions. The process needs to be documented and automated enough so that it does not rely on individuals with special knowledge. Additionally, we want to align the version included in the Vulkan SDK with a formal DXC release so that it matches up with GitHub and NuGet releases and can be ingested into Godbolt.

Proposed solution

The SPIRV-Headers and SPIRV-Tools submodules are the single source of truth for the SPIRV revisions a candidate is built against. Once a week a workflow bumps them to the latest upstream commit and opens a pull request to merge that update into main. The pull request runs the release-candidate pipeline, building DXC against the updated submodules and running the SPIRV tests.

For an SDK release, the pipeline also publishes the candidate as an artifact and runs the LLVM offload-test-suite against it, using lavapipe as the SPIRV driver and WARP as the DXIL driver. DXC from the Vulkan SDK is also used to compile shader targeting DirectX, so its DXIL output is worth testing too. Each validated candidate handed to LunarG is tagged as a release candidate (its results recorded in the manifest); the latest is promoted to a release once the Vulkan SDK ships.

The automation is split into three workflows, each shown below starting from its triggers:

1. Weekly submodule update — keeps the SPIRV dependencies updated.

flowchart TD
    cron(["Trigger: weekly schedule"]) --> bump
    md1(["Trigger: manual dispatch"]) --> bump
    bump["Bump SPIRV-Headers / SPIRV-Tools<br/>submodules to latest upstream"] --> changed{"Anything changed?"}
    changed -->|no| stop(["Done — already current"])
    changed -->|yes| pr["Open a vk-update PR"]
    pr -. "branch push starts" .-> rc(["Release-candidate pipeline"])

2. Release-candidate pipeline — builds and tests DXC; for a release candidate it also publishes the artifact and runs the offload tests.

flowchart TD
    push(["Trigger: push to a<br/>vk-update or release/vulkan branch"]) --> build
    md2(["Trigger: manual dispatch"]) --> build
    build["Build DXC against the<br/>submodule pointers, plus spirv-val"] --> test
    test["Run every SPIRV test:<br/>googletest, lit, TAEF, spirv-val"] --> gate{"Release candidate?<br/>release/vulkan branch<br/>or manual opt-in"}
    gate -->|no| prchecks(["Validation only — checks surface<br/>on the vk-update PR, merge when green"])
    gate -->|yes| publish["Publish dxc_rc artifact + manifest"]
    publish -. "consumed by" .-> offload(["Offload tests"])

3. Offload tests — runs the offload-test-suite against the published candidate on software renderers, split by API.

flowchart TD
    called(["Trigger: called by the pipeline"]) --> get
    md3(["Trigger: manual dispatch —<br/>run_id + artifact name"]) --> get
    get["Download the dxc_rc artifact"] --> conf["Build offload-test-suite against<br/>the candidate's DXC — DXC only"]
    conf --> vk["Vulkan: check-hlsl-vk on lavapipe<br/>runs the candidate's SPIRV"]
    conf --> d3d["Direct3D 12: check-hlsl-warp-d3d12 on WARP<br/>runs the candidate's DXIL"]

Dependency update

A scheduled job runs once a week (and can be triggered on demand). Such advances the SPIRV-Headers and SPIRV-Tools submodules to their latest upstream commit and, if anything changed, commits the new pointers onto a fresh vk-update/<date> branch and opens a pull request against the default branch. Pushing that branch starts the release-candidate pipeline, whose checks attach to the commit and show on the pull request, so the bump is reviewed and merged only once the candidate is green.

Release Pipeline

The release pipeline runs on every push to a vk-update/<date> branch (the weekly job creates these) or a release/vulkan/<version> branch (cut by hand for a release; see [Release Steps](#Release Steps)), and can be started manually from the GitHub UI. The build and test stages run on every push; the publish and offload stages run only for a release candidate — a release/vulkan/<version> branch, or a manual run that opts in.

  1. Build. DXC is checked out with its submodules, so it builds against exactly the SPIRV the pointers name, configured with SPIRV code generation and the SPIRV tests enabled. The build also produces the tools the tests need, including spirv-val.

  2. Test. Googletest unit tests, the lit CodeGenSPIRV tests, and the TAEF tests are all run in this stage; the binary’s output is then checked with spirv-val. Each result is recorded in the manifest, including failed tests. The logs also contain further information where each file is located and what was exected. This stage is non-blocking — a release candidate is published even if some tests fail.

  3. Publish. The DXC binaries (dxc, dxv, and dxcompiler.dll), the manifest, and the test reports are uploaded as a single artifact named dxc_rc_<version>.

  4. Offload tests. A separate job runs the LLVM offload-test-suite against the published artifact, with DXC as the only compiler (the in-tree clang compiler is disabled). The Vulkan tests (check-hlsl-vk) on lavapipe and the Direct3D 12 tests (check-hlsl-warp-d3d12) on WARP (developers still use the dxc which ships in the Vulkan SDK to compile dx shaders). Because it consumes the published artifact rather than the build tree, this job can also be run on its own against any earlier candidate.

Release manifest

The manifest records the DXC commit, the SPIRV-Headers and SPIRV-Tools commits the candidate was built against and the tests results:

{
  "dxc_commit": "<sha>",
  "lavapipe_version": "<version>",
  "warp_version": "<version>",
  "spirv_dependencies": {
    "SPIRV-Headers": "<sha>",
    "SPIRV-Tools": "<sha>"
  },
  "test_suites": [
    { "name": "spirv-unit", "passed": 105, "failed": 0 },
    { "name": "spirv-codegen", "passed": 1564, "failed": 0 },
    { "name": "spirv-taef", "passed": 1, "failed": 0 },
    { "name": "spirv-val", "passed": 6, "failed": 0 }
  ]
}

Release tagging

A release is prepared on a branch and shipped to LunarG as a series of release candidate tags. The branch carries the Vulkan SDK’s major and minor version; each tag records the full Vulkan SDK version and a release-candidate number, and is prefixed vulkan-sdk- so it reads as a Vulkan SDK version rather than being confused with DXC’s own release tags (v<major>.<minor>.YYMM.<patch>). This matches the vulkan-sdk- tags SPIRV-Tools already uses for the SDK. For SDK version 1.4.360, for example, the release branch is release/vulkan/1.4.360, the candidates sent to LunarG are tagged vulkan-sdk-1.4.360.0rc1, vulkan-sdk-1.4.360.0rc2, and so on, and once the Vulkan SDK is published the latest candidate is promoted to a release tag with no rc suffix: vulkan-sdk-1.4.360.0.

Release Steps

These steps are performed by whoever is currently responsible for monitoring the llvm-build, and may be repeated as needed:

  1. File an issue in DXC repository using the vk_release_checklist.md issue template, assign this to yourself. This should be handed off at the end of rotation.
  2. Update the SPIRV-Headers and SPIRV-Tools submodules to the commits specified by LunarG.
  3. Create the release/vulkan/<version> branch — named for the SDK major and minor version, e.g. release/vulkan/1.4.360 — which triggers the pipeline.
  4. Check whether the resulting candidate is validated (see Release Candidate readiness).
  5. Tag the validated commit with the next release-candidate tag (e.g. vulkan-sdk-1.4.360.0rc1) and report that tag to LunarG — by email, or by updating the Khronos GitLab release issue with the validated commit.
  6. If LunarG reports a problem, fix it on the release branch and re-validate, then cut the next release-candidate tag (...rc2, and so on) and report it.
  7. Once the Vulkan SDK is published, promote the latest release-candidate tag to a release tag with no rc suffix, e.g. vulkan-sdk-1.4.360.0.

Release Candidate readiness

The following must be true and validated for a release candidate to be considered ready for the Vulkan SDK.

  • It builds against the SPIRV-Headers and SPIRV-Tools commits the submodules are pinned to.
  • Every SPIRV test harness passes — the googletest, lit, and TAEF tests — and the SPIRV the binary emits validates under spirv-val.
  • The shaders the candidate compiles execute on the offload-test-suite under both software renderers: the SPIRV on lavapipe (Vulkan) and the DXIL on WARP (Direct3D 12).