dawn/node: Allow picking of the adapter by name

Add the "--adapter" flag to run-cts as a helper for setting this.

Make "--verbose" print the picked adapter.

Rename "dawn-backend" flag to just "backend" - this is already specific to the "gpu provider" (dawn).

Change-Id: Idc8d0eb3ccf5fa23325c06f0f9520aa9b528d9dd
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/116295
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Auto-Submit: Ben Clayton <bclayton@google.com>
Kokoro: Ben Clayton <bclayton@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton 2023-01-10 19:15:42 +00:00 committed by Dawn LUCI CQ
parent c6236de7c2
commit c9c937cc3e
3 changed files with 117 additions and 51 deletions

View File

@ -69,7 +69,8 @@ VK_ICD_FILENAMES=<swiftshader-cmake-build>/Linux/vk_swiftshader_icd.json ./src/t
``` ```
The `--flag` parameter must be passed in multiple times, once for each flag begin set. Here are some common arguments: The `--flag` parameter must be passed in multiple times, once for each flag begin set. Here are some common arguments:
* `dawn-backend=<null|webgpu|d3d11|d3d12|metal|vulkan|opengl|opengles>` * `backend=<null|webgpu|d3d11|d3d12|metal|vulkan|opengl|opengles>`
* `adapter=<name-of-adapter>` - specifies the adapter to use. May be a substring of the full adapter name. Pass an invalid adapter name and `--verbose` to see all possible adapters.
* `dlldir=<path>` - used to add an extra DLL search path on Windows, primarily to load the right d3dcompiler_47.dll * `dlldir=<path>` - used to add an extra DLL search path on Windows, primarily to load the right d3dcompiler_47.dll
* `enable-dawn-features=<features>` - enable [Dawn toggles](https://dawn.googlesource.com/dawn/+/refs/heads/main/src/dawn/native/Toggles.cpp), e.g. `dump_shaders` * `enable-dawn-features=<features>` - enable [Dawn toggles](https://dawn.googlesource.com/dawn/+/refs/heads/main/src/dawn/native/Toggles.cpp), e.g. `dump_shaders`
* `disable-dawn-features=<features>` - disable [Dawn toggles](https://dawn.googlesource.com/dawn/+/refs/heads/main/src/dawn/native/Toggles.cpp) * `disable-dawn-features=<features>` - disable [Dawn toggles](https://dawn.googlesource.com/dawn/+/refs/heads/main/src/dawn/native/Toggles.cpp)

View File

@ -52,6 +52,41 @@ void SetDllDir(const char* dir) {
#endif #endif
} }
struct BackendInfo {
const char* const name;
const char* const alias; // may be nullptr
wgpu::BackendType const backend;
};
constexpr BackendInfo kBackends[] = {
{"null", nullptr, wgpu::BackendType::Null}, //
{"webgpu", nullptr, wgpu::BackendType::WebGPU}, //
{"d3d11", nullptr, wgpu::BackendType::D3D11}, //
{"d3d12", "d3d", wgpu::BackendType::D3D12}, //
{"metal", nullptr, wgpu::BackendType::Metal}, //
{"vulkan", "vk", wgpu::BackendType::Vulkan}, //
{"opengl", "gl", wgpu::BackendType::OpenGL}, //
{"opengles", "gles", wgpu::BackendType::OpenGLES}, //
};
std::optional<wgpu::BackendType> ParseBackend(std::string_view name) {
for (auto& info : kBackends) {
if (info.name == name || (info.alias && info.alias == name)) {
return info.backend;
}
}
return std::nullopt;
}
const char* BackendName(wgpu::BackendType backend) {
for (auto& info : kBackends) {
if (info.backend == backend) {
return info.name;
}
}
return "<unknown>";
}
} // namespace } // namespace
namespace wgpu::binding { namespace wgpu::binding {
@ -99,69 +134,93 @@ interop::Promise<std::optional<interop::Interface<interop::GPUAdapter>>> GPU::re
#error "Unsupported platform" #error "Unsupported platform"
#endif #endif
auto targetBackendType = defaultBackendType; // Check for backend override from env var / flag
std::string forceBackend; std::string forceBackend;
if (auto f = flags_.Get("backend")) {
// Check for override from env var forceBackend = *f;
if (std::string envVar = GetEnvVar("DAWNNODE_BACKEND"); !envVar.empty()) { } else if (std::string envVar = GetEnvVar("DAWNNODE_BACKEND"); !envVar.empty()) {
forceBackend = envVar; forceBackend = envVar;
} }
// Check for override from flag // Check for specific adapter name
if (auto f = flags_.Get("dawn-backend")) { std::string adapterName;
forceBackend = *f; if (auto f = flags_.Get("adapter")) {
adapterName = *f;
} }
std::transform(forceBackend.begin(), forceBackend.end(), forceBackend.begin(), std::transform(forceBackend.begin(), forceBackend.end(), forceBackend.begin(),
[](char c) { return std::tolower(c); }); [](char c) { return std::tolower(c); });
// Default to first adapter if a backend is not specified auto targetBackendType = defaultBackendType;
size_t adapterIndex = 0;
if (!forceBackend.empty()) { if (!forceBackend.empty()) {
if (forceBackend == "null") { if (auto parsed = ParseBackend(forceBackend)) {
targetBackendType = wgpu::BackendType::Null; targetBackendType = parsed.value();
} else if (forceBackend == "webgpu") {
targetBackendType = wgpu::BackendType::WebGPU;
} else if (forceBackend == "d3d11") {
targetBackendType = wgpu::BackendType::D3D11;
} else if (forceBackend == "d3d12" || forceBackend == "d3d") {
targetBackendType = wgpu::BackendType::D3D12;
} else if (forceBackend == "metal") {
targetBackendType = wgpu::BackendType::Metal;
} else if (forceBackend == "vulkan" || forceBackend == "vk") {
targetBackendType = wgpu::BackendType::Vulkan;
} else if (forceBackend == "opengl" || forceBackend == "gl") {
targetBackendType = wgpu::BackendType::OpenGL;
} else if (forceBackend == "opengles" || forceBackend == "gles") {
targetBackendType = wgpu::BackendType::OpenGLES;
} else { } else {
promise.Reject("unknown backend '" + forceBackend + "'"); std::stringstream msg;
msg << "unrecognised backend '" + forceBackend + "'" << std::endl
<< "Possible backends: ";
for (auto& info : kBackends) {
if (&info != &kBackends[0]) {
msg << ", ";
}
msg << "'" << info.name << "'";
}
promise.Reject(msg.str());
return promise; return promise;
} }
} }
bool found = false; dawn::native::Adapter* adapter = nullptr;
for (size_t i = 0; i < adapters.size(); ++i) { for (auto& a : adapters) {
wgpu::AdapterProperties props; wgpu::AdapterProperties props;
adapters[i].GetProperties(&props); a.GetProperties(&props);
if (props.backendType == targetBackendType) { if (props.backendType != targetBackendType) {
adapterIndex = i; continue;
found = true; }
if (!adapterName.empty() && props.name &&
std::string(props.name).find(adapterName) == std::string::npos) {
continue;
}
adapter = &a;
break; break;
} }
}
if (!found) { if (!adapter) {
std::stringstream msg;
if (!forceBackend.empty() || adapterName.empty()) {
msg << "no adapter ";
if (!forceBackend.empty()) { if (!forceBackend.empty()) {
promise.Reject("backend '" + forceBackend + "' not found"); msg << "with backend '" << forceBackend << "'";
} else { if (!adapterName.empty()) {
promise.Reject("no suitable backends found"); msg << " and name '" << adapterName << "'";
} }
} else {
msg << " with name '" << adapterName << "'";
}
msg << " found";
} else {
msg << "no suitable backends found";
}
msg << std::endl << "Available adapters:";
for (auto& a : adapters) {
wgpu::AdapterProperties props;
a.GetProperties(&props);
msg << std::endl
<< " * backend: '" << BackendName(props.backendType) << "', name: '" << props.name
<< "'";
}
promise.Reject(msg.str());
return promise; return promise;
} }
auto adapter = GPUAdapter::Create<GPUAdapter>(env, adapters[adapterIndex], flags_); if (flags_.Get("verbose")) {
promise.Resolve(std::optional<interop::Interface<interop::GPUAdapter>>(adapter)); wgpu::AdapterProperties props;
adapter->GetProperties(&props);
printf("using GPU adapter: %s\n", props.name);
}
auto gpuAdapter = GPUAdapter::Create<GPUAdapter>(env, *adapter, flags_);
promise.Resolve(std::optional<interop::Interface<interop::GPUAdapter>>(gpuAdapter));
return promise; return promise;
} }

View File

@ -131,8 +131,8 @@ func run() error {
unrollConstEvalLoopsDefault := runtime.GOOS != "windows" unrollConstEvalLoopsDefault := runtime.GOOS != "windows"
var dawnNode, cts, node, npx, resultsPath, expectationsPath, logFilename, backend, coverageFile string var dawnNode, cts, node, npx, resultsPath, expectationsPath, logFilename, backend, adapterName, coverageFile string
var printStdout, verbose, isolated, build, dumpShaders, unrollConstEvalLoops, genCoverage bool var verbose, isolated, build, dumpShaders, unrollConstEvalLoops, genCoverage bool
var numRunners int var numRunners int
var flags dawnNodeFlags var flags dawnNodeFlags
flag.StringVar(&dawnNode, "dawn-node", "", "path to dawn.node module") flag.StringVar(&dawnNode, "dawn-node", "", "path to dawn.node module")
@ -141,7 +141,6 @@ func run() error {
flag.StringVar(&npx, "npx", "", "path to npx executable") flag.StringVar(&npx, "npx", "", "path to npx executable")
flag.StringVar(&resultsPath, "output", "", "path to write test results file") flag.StringVar(&resultsPath, "output", "", "path to write test results file")
flag.StringVar(&expectationsPath, "expect", "", "path to expectations file") flag.StringVar(&expectationsPath, "expect", "", "path to expectations file")
flag.BoolVar(&printStdout, "print-stdout", false, "print the stdout and stderr from each test runner server")
flag.BoolVar(&verbose, "verbose", false, "print extra information while testing") flag.BoolVar(&verbose, "verbose", false, "print extra information while testing")
flag.BoolVar(&build, "build", true, "attempt to build the CTS before running") flag.BoolVar(&build, "build", true, "attempt to build the CTS before running")
flag.BoolVar(&isolated, "isolate", false, "run each test in an isolated process") flag.BoolVar(&isolated, "isolate", false, "run each test in an isolated process")
@ -151,6 +150,7 @@ func run() error {
flag.Var(&flags, "flag", "flag to pass to dawn-node as flag=value. multiple flags must be passed in individually") flag.Var(&flags, "flag", "flag to pass to dawn-node as flag=value. multiple flags must be passed in individually")
flag.StringVar(&backend, "backend", backendDefault, "backend to use: default|null|webgpu|d3d11|d3d12|metal|vulkan|opengl|opengles."+ flag.StringVar(&backend, "backend", backendDefault, "backend to use: default|null|webgpu|d3d11|d3d12|metal|vulkan|opengl|opengles."+
" set to 'vulkan' if VK_ICD_FILENAMES environment variable is set, 'default' otherwise") " set to 'vulkan' if VK_ICD_FILENAMES environment variable is set, 'default' otherwise")
flag.StringVar(&adapterName, "adapter", "", "name (or substring) of the GPU adapter to use")
flag.BoolVar(&dumpShaders, "dump-shaders", false, "dump WGSL shaders. Enables --verbose") flag.BoolVar(&dumpShaders, "dump-shaders", false, "dump WGSL shaders. Enables --verbose")
flag.BoolVar(&unrollConstEvalLoops, "unroll-const-eval-loops", unrollConstEvalLoopsDefault, "unroll loops in const-eval tests") flag.BoolVar(&unrollConstEvalLoops, "unroll-const-eval-loops", unrollConstEvalLoopsDefault, "unroll loops in const-eval tests")
flag.BoolVar(&genCoverage, "coverage", false, "displays coverage data. Enables --isolated") flag.BoolVar(&genCoverage, "coverage", false, "displays coverage data. Enables --isolated")
@ -209,10 +209,13 @@ func run() error {
} }
} }
// Forward the backend to use, if specified. // Forward the backend and adapter to use, if specified.
if backend != "default" { if backend != "default" {
fmt.Fprintln(stdout, "Forcing backend to", backend) fmt.Fprintln(stdout, "Forcing backend to", backend)
flags = append(flags, fmt.Sprint("dawn-backend=", backend)) flags.Set("backend=" + backend)
}
if adapterName != "" {
flags.Set("adapter=" + adapterName)
} }
// While running the CTS, always allow unsafe APIs so they can be tested. // While running the CTS, always allow unsafe APIs so they can be tested.
@ -233,7 +236,6 @@ func run() error {
r := runner{ r := runner{
numRunners: numRunners, numRunners: numRunners,
printStdout: printStdout,
verbose: verbose, verbose: verbose,
node: node, node: node,
npx: npx, npx: npx,
@ -416,7 +418,6 @@ func (c *cache) save(path string) error {
type runner struct { type runner struct {
numRunners int numRunners int
printStdout bool
verbose bool verbose bool
node string node string
npx string npx string
@ -657,7 +658,9 @@ func (r *runner) runServer(ctx context.Context, id int, caseIndices <-chan int,
args = append(args, "--colors") args = append(args, "--colors")
} }
if r.verbose { if r.verbose {
args = append(args, "--verbose") args = append(args,
"--verbose",
"--gpu-provider-flag", "verbose=1")
} }
if r.unrollConstEvalLoops { if r.unrollConstEvalLoops {
args = append(args, "--unroll-const-eval-loops") args = append(args, "--unroll-const-eval-loops")
@ -669,7 +672,7 @@ func (r *runner) runServer(ctx context.Context, id int, caseIndices <-chan int,
cmd := exec.CommandContext(ctx, r.node, args...) cmd := exec.CommandContext(ctx, r.node, args...)
writer := io.Writer(testCaseLog) writer := io.Writer(testCaseLog)
if r.printStdout { if r.verbose {
pw := &prefixWriter{ pw := &prefixWriter{
prefix: fmt.Sprintf("[%d] ", id), prefix: fmt.Sprintf("[%d] ", id),
writer: r.stdout, writer: r.stdout,
@ -1065,9 +1068,12 @@ func (r *runner) runTestcase(ctx context.Context, query string, profraw string)
"placeholder-arg", "placeholder-arg",
// Actual arguments begin here // Actual arguments begin here
"--gpu-provider", r.dawnNode, "--gpu-provider", r.dawnNode,
"--verbose", "--verbose", // always required to emit test pass results
"--quiet", "--quiet",
} }
if r.verbose {
args = append(args, "--gpu-provider-flag", "verbose=1")
}
if r.colors { if r.colors {
args = append(args, "--colors") args = append(args, "--colors")
} }