Files
Romaric Jodin cef3ef6b59 Update '-list' option (#2457)
'-list' option is used to print all sub-tests. But some test do not
support it at all. And all test do not display it the same way, making
it quite complicated for external tools to extract them.

That CL clean the usage so that tests:
- Print the sub-tests list with either '-list' (to prevent breaking
legacy usage) or '--list' (to match other options)
- Do not print anything else when the option is used
2025-08-19 17:48:03 +01:00

257 lines
8.0 KiB
C++

//
// Copyright (c) 2016-2023 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include <stdio.h>
#include <string.h>
#include "procs.h"
#if !defined(_WIN32)
#include <unistd.h>
#endif
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#if defined(_WIN32)
const std::string slash = "\\";
#else
const std::string slash = "/";
#endif
const std::string spvExt = ".spv";
bool gVersionSkip = false;
std::string gAddrWidth = "";
std::string spvBinariesPath = "spirv_bin";
const std::string spvBinariesPathArg = "--spirv-binaries-path";
const std::string spvVersionSkipArg = "--skip-spirv-version-check";
std::vector<unsigned char> readBinary(const char *file_name)
{
std::ifstream file(file_name,
std::ios::in | std::ios::binary | std::ios::ate);
std::vector<char> tmpBuffer(0);
if (file.is_open()) {
size_t size = file.tellg();
tmpBuffer.resize(size);
file.seekg(0, std::ios::beg);
file.read(&tmpBuffer[0], size);
file.close();
} else {
log_error("File %s not found\n", file_name);
}
std::vector<unsigned char> result(tmpBuffer.begin(), tmpBuffer.end());
return result;
}
std::vector<unsigned char> readSPIRV(const char *file_name)
{
std::string full_name_str = spvBinariesPath + slash + file_name + spvExt + gAddrWidth;
return readBinary(full_name_str.c_str());
}
static int offline_get_program_with_il(clProgramWrapper &prog,
const cl_device_id deviceID,
const cl_context context,
const char *prog_name)
{
cl_int err = 0;
std::string outputTypeStr = "binary";
std::string defaultScript = std::string("..") + slash + std::string("spv_to_binary.py");
std::string outputFilename = spvBinariesPath + slash + std::string(prog_name);
std::string sourceFilename = outputFilename + spvExt;
std::string scriptArgs =
sourceFilename + " " +
outputFilename + " " +
gAddrWidth + " " +
outputTypeStr + " " +
"-cl-std=CL2.0";
std::string scriptToRunString = defaultScript + scriptArgs;
// execute script
log_info("Executing command: %s\n", scriptToRunString.c_str());
fflush(stdout);
int returnCode = system(scriptToRunString.c_str());
if (returnCode != 0) {
log_error("Command finished with error: 0x%x\n", returnCode);
return CL_COMPILE_PROGRAM_FAILURE;
}
// read output file
std::vector<unsigned char> buffer_vec = readBinary(outputFilename.c_str());
size_t file_bytes = buffer_vec.size();
if (file_bytes == 0) {
log_error("OfflinerCompiler: Failed to open binary file: %s", outputFilename.c_str());
return -1;
}
const unsigned char *buffer = &buffer_vec[0];
cl_int status = 0;
prog = clCreateProgramWithBinary(context, 1, &deviceID, &file_bytes, &buffer, &status, &err);
SPIRV_CHECK_ERROR((err || status), "Failed to create program with clCreateProgramWithBinary");
return err;
}
int get_program_with_il(clProgramWrapper &prog, const cl_device_id deviceID,
const cl_context context, const char *prog_name,
spec_const spec_const_def)
{
cl_int err = 0;
if (gCompilationMode == kBinary)
{
return offline_get_program_with_il(prog, deviceID, context, prog_name);
}
std::vector<unsigned char> buffer_vec = readSPIRV(prog_name);
int file_bytes = buffer_vec.size();
if (file_bytes == 0)
{
log_error("File %s not found\n", prog_name);
return -1;
}
unsigned char *buffer = &buffer_vec[0];
if (gCoreILProgram)
{
prog = clCreateProgramWithIL(context, buffer, file_bytes, &err);
SPIRV_CHECK_ERROR(
err, "Failed to create program with clCreateProgramWithIL");
if (spec_const_def.spec_value != NULL)
{
err = clSetProgramSpecializationConstant(
prog, spec_const_def.spec_id, spec_const_def.spec_size,
spec_const_def.spec_value);
SPIRV_CHECK_ERROR(
err, "Failed to run clSetProgramSpecializationConstant");
}
}
else
{
cl_platform_id platform;
err = clGetDeviceInfo(deviceID, CL_DEVICE_PLATFORM,
sizeof(cl_platform_id), &platform, NULL);
SPIRV_CHECK_ERROR(err,
"Failed to get platform info with clGetDeviceInfo");
clCreateProgramWithILKHR_fn clCreateProgramWithILKHR = NULL;
clCreateProgramWithILKHR = (clCreateProgramWithILKHR_fn)
clGetExtensionFunctionAddressForPlatform(
platform, "clCreateProgramWithILKHR");
if (clCreateProgramWithILKHR == NULL)
{
log_error(
"ERROR: clGetExtensionFunctionAddressForPlatform failed\n");
return -1;
}
prog = clCreateProgramWithILKHR(context, buffer, file_bytes, &err);
SPIRV_CHECK_ERROR(
err, "Failed to create program with clCreateProgramWithILKHR");
}
err = clBuildProgram(prog, 1, &deviceID, NULL, NULL, NULL);
if (err != CL_SUCCESS)
{
cl_int outputErr = OutputBuildLog(prog, deviceID);
SPIRV_CHECK_ERROR(outputErr, "OutputBuildLog failed");
return err;
}
return err;
}
test_status InitCL(cl_device_id id)
{
test_status spirv_status;
spirv_status = check_spirv_compilation_readiness(id);
if (spirv_status != TEST_PASS)
{
return spirv_status;
}
cl_uint address_bits;
cl_uint err = clGetDeviceInfo(id, CL_DEVICE_ADDRESS_BITS, sizeof(cl_uint),
&address_bits, NULL);
if (err != CL_SUCCESS)
{
log_error("clGetDeviceInfo failed to get address bits!");
return TEST_FAIL;
}
gAddrWidth = address_bits == 32 ? "32" : "64";
return TEST_PASS;
}
void printUsage() {
log_info("Reading SPIR-V files from default '%s' path.\n", spvBinariesPath.c_str());
log_info("In case you want to set other directory use '%s' argument.\n",
spvBinariesPathArg.c_str());
log_info("To skip the SPIR-V version check use the '%s' argument.\n",
spvVersionSkipArg.c_str());
}
int main(int argc, const char *argv[])
{
gReSeed = 1;
bool modifiedSpvBinariesPath = false;
bool listTests = false;
for (int i = 0; i < argc; ++i) {
int argsRemoveNum = 0;
if (argv[i] == spvBinariesPathArg) {
if (i + 1 == argc) {
log_error("Missing value for '%s' argument.\n", spvBinariesPathArg.c_str());
return TEST_FAIL;
} else {
spvBinariesPath = std::string(argv[i + 1]);
argsRemoveNum += 2;
modifiedSpvBinariesPath = true;
}
}
if (argv[i] == spvVersionSkipArg)
{
gVersionSkip = true;
argsRemoveNum++;
}
if (argsRemoveNum > 0) {
for (int j = i; j < (argc - argsRemoveNum); ++j)
argv[j] = argv[j + argsRemoveNum];
argc -= argsRemoveNum;
--i;
}
listTests |= (argv[i] == std::string("--list")
|| argv[i] == std::string("-list"));
}
if (modifiedSpvBinariesPath == false && !listTests)
{
printUsage();
}
return runTestHarnessWithCheck(
argc, argv, test_registry::getInstance().num_tests(),
test_registry::getInstance().definitions(), false, 0, InitCL);
}