Skip to content

Commit 4b7f8f1

Browse files
authored
[WebGPU EP] Add environment variable to dump shader code to a file, move shader key validation to nightly build (#28674)
### Description <!-- Describe your changes. --> Allow shader code to be dumped to the file specified in the `ORT_WEBGPU_EP_SHADER_DUMP_FILE` environment variable. Previously, shader code was only dumped by verbose logging. Create new nightly CI pipeline to run shader key validation test. That test is removed from the CI pipeline in #28642. ### Motivation and Context <!-- - Why is this change required? What problem does it solve? - If it fixes an open issue, please link to the issue here. --> More shader dump output options. Moving shader key validation test.
1 parent efbffdd commit 4b7f8f1

4 files changed

Lines changed: 114 additions & 18 deletions

File tree

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
name: Nightly ONNX Runtime WebGPU Builds
2+
3+
on:
4+
schedule:
5+
- cron: '0 9 * * *' # Daily at 09:00 UTC
6+
workflow_dispatch:
7+
8+
concurrency:
9+
group: ${{ github.workflow }}-${{ github.ref }}
10+
cancel-in-progress: true
11+
12+
jobs:
13+
webgpu_shader_key_validation:
14+
runs-on: [
15+
"self-hosted",
16+
"1ES.Pool=onnxruntime-github-Win2022-GPU-A10",
17+
"JobId=webgpu_shader_validation-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}"
18+
]
19+
timeout-minutes: 90
20+
env:
21+
ALLOW_RELEASED_ONNX_OPSET_ONLY: "0"
22+
ONNXRUNTIME_TEST_GPU_DEVICE_ID: "0"
23+
steps:
24+
- name: Checkout
25+
uses: actions/checkout@v6
26+
with:
27+
fetch-depth: 0
28+
submodules: none
29+
30+
- name: Setup Python
31+
uses: actions/setup-python@v6
32+
with:
33+
python-version: "3.12"
34+
architecture: x64
35+
36+
- name: Locate vcvarsall and Setup Env
37+
uses: ./.github/actions/locate-vcvarsall-and-setup-env
38+
with:
39+
architecture: x64
40+
41+
- name: Install python modules
42+
run: python -m pip install -r tools\ci_build\github\windows\python\requirements.txt
43+
shell: cmd
44+
working-directory: ${{ github.workspace }}
45+
46+
- name: Setup Node.js
47+
uses: actions/setup-node@v6
48+
with:
49+
node-version: "24"
50+
51+
- name: Build and Test
52+
shell: pwsh
53+
run: |
54+
$env:ORT_WEBGPU_EP_SHADER_DUMP_FILE = "${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo\shader_dump.log"
55+
56+
python.exe ${{ github.workspace }}\tools\ci_build\build.py `
57+
--config RelWithDebInfo `
58+
--build_dir ${{ github.workspace }} `
59+
--use_binskim_compliant_compile_flags `
60+
--cmake_generator "Visual Studio 17 2022" `
61+
--build_shared_lib `
62+
--use_webgpu `
63+
--wgsl_template static `
64+
--cmake_extra_defines onnxruntime_BUILD_DAWN_SHARED_LIBRARY=ON `
65+
--update `
66+
--build --parallel `
67+
--test
68+
69+
- name: Check log file
70+
shell: cmd
71+
run: |
72+
dir ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo\shader_dump.log
73+
74+
- name: Validate shader keys
75+
uses: ./.github/actions/webgpu-validate-shader-key
76+
with:
77+
log_file_path: ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo\shader_dump.log

onnxruntime/core/providers/webgpu/program_manager.cc

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
// Licensed under the MIT License.
33

44
#include <algorithm>
5+
#include <fstream>
6+
#include <memory>
57

68
#include "core/common/common.h"
79
#include "core/common/logging/logging.h"
10+
#include "core/platform/env_var.h"
811

912
#include "core/providers/webgpu/program_manager.h"
1013
#include "core/providers/webgpu/shader_helper.h"
@@ -18,6 +21,17 @@ ProgramArtifact::ProgramArtifact(const ProgramBase& program, wgpu::ComputePipeli
1821
compute_pipeline{compute_pipeline},
1922
shape_uniform_ranks{shape_uniform_ranks} {}
2023

24+
ProgramManager::ProgramManager(WebGpuContext& webgpu_context)
25+
: webgpu_context_{webgpu_context} {
26+
if (std::string dump_file_path = onnxruntime::detail::GetEnvironmentVar("ORT_WEBGPU_EP_SHADER_DUMP_FILE");
27+
!dump_file_path.empty()) {
28+
auto dump_file = std::make_shared<std::ofstream>(dump_file_path.c_str(), std::ios::app);
29+
shader_dump_fn_ = [dump_file = std::move(dump_file)](std::string_view shader_content) {
30+
*dump_file << shader_content << "\n";
31+
};
32+
}
33+
}
34+
2135
Status ProgramManager::NormalizeDispatchGroupSize(uint32_t& x, uint32_t& y, uint32_t& z) const {
2236
ORT_RETURN_IF(x == 0 || y == 0 || z == 0, "Invalid dispatch group size (", x, ", ", y, ", ", z, ")");
2337

@@ -66,9 +80,7 @@ Status ProgramManager::Build(const ProgramBase& program,
6680
const ProgramMetadata& program_metadata,
6781
const std::span<uint32_t> inputs_segments,
6882
const std::span<uint32_t> outputs_segments,
69-
#ifndef NDEBUG // if debug build
7083
const std::string& program_key,
71-
#endif
7284
uint32_t normalized_dispatch_x,
7385
uint32_t normalized_dispatch_y,
7486
uint32_t normalized_dispatch_z,
@@ -100,17 +112,24 @@ Status ProgramManager::Build(const ProgramBase& program,
100112
std::string code;
101113
ORT_RETURN_IF_ERROR(shader_helper.GenerateSourceCode(code, shape_uniform_ranks));
102114

103-
LOGS_DEFAULT(VERBOSE) << "\n=== WebGPU Shader code [" << program.Name()
104-
#ifndef NDEBUG // if debug build
105-
<< ", Key=\"" << program_key << "\""
106-
#endif
107-
<< "] Start ===\n\n"
108-
<< code
109-
<< "\n=== WebGPU Shader code [" << program.Name()
110-
#ifndef NDEBUG // if debug build
111-
<< ", Key=\"" << program_key << "\""
112-
#endif
113-
<< "] End ===\n";
115+
// Dump shader code, if requested. It is dumped to `shader_dump_fn_` if set or VERBOSE logging otherwise.
116+
{
117+
const auto shader_content = [&program, &program_key, &code]() {
118+
return MakeString("\n=== WebGPU Shader code [", program.Name(),
119+
", Key=\"", program_key, "\"",
120+
"] Start ===\n\n",
121+
code,
122+
"\n=== WebGPU Shader code [", program.Name(),
123+
", Key=\"", program_key, "\"",
124+
"] End ===\n");
125+
};
126+
127+
if (shader_dump_fn_) {
128+
shader_dump_fn_(shader_content());
129+
} else {
130+
LOGS_DEFAULT(VERBOSE) << shader_content();
131+
}
132+
}
114133

115134
wgpu::ShaderSourceWGSL wgsl_source{};
116135
wgsl_source.code = code.c_str();

onnxruntime/core/providers/webgpu/program_manager.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33

44
#pragma once
55

6+
#include <functional>
67
#include <span>
78
#include <string>
9+
#include <string_view>
810
#include <unordered_map>
911

1012
#include "core/providers/webgpu/webgpu_external_header.h"
@@ -36,7 +38,7 @@ class ProgramArtifact {
3638

3739
class ProgramManager {
3840
public:
39-
ProgramManager(WebGpuContext& webgpu_context) : webgpu_context_(webgpu_context) {}
41+
ProgramManager(WebGpuContext& webgpu_context);
4042

4143
Status NormalizeDispatchGroupSize(uint32_t& x, uint32_t& y, uint32_t& z) const;
4244
Status CalculateSegmentsForInputsAndOutputs(const ProgramBase& program, std::vector<uint32_t>& inputs_segments, std::vector<uint32_t>& outputs_segments) const;
@@ -45,9 +47,7 @@ class ProgramManager {
4547
const ProgramMetadata& metadata,
4648
const std::span<uint32_t> inputs_segments,
4749
const std::span<uint32_t> outputs_segments,
48-
#ifndef NDEBUG // if debug build
4950
const std::string& program_key,
50-
#endif
5151
uint32_t normalized_dispatch_x,
5252
uint32_t normalized_dispatch_y,
5353
uint32_t normalized_dispatch_z,
@@ -59,6 +59,8 @@ class ProgramManager {
5959
private:
6060
std::unordered_map<std::string, ProgramArtifact> programs_;
6161
WebGpuContext& webgpu_context_;
62+
63+
std::function<void(std::string_view)> shader_dump_fn_;
6264
};
6365

6466
} // namespace webgpu

onnxruntime/core/providers/webgpu/webgpu_context.cc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,9 +303,7 @@ Status WebGpuContext::Run(ComputeContextBase& context, const ProgramBase& progra
303303
metadata,
304304
inputs_segments,
305305
outputs_segments,
306-
#ifndef NDEBUG // if debug build
307306
key,
308-
#endif
309307
x,
310308
y,
311309
z,

0 commit comments

Comments
 (0)