Remove spir half vloada_half tests as this builtin does not exist in OpenCL (#2552)

The test was using vloada_half which does not exist for scalars.

Also removed the files test.vloada_half_*.* from half.zip.

For test.vloada_half3_global, changed the OpenCL kernel to use
vload_half instead of vloada_half.

Build failures will return a proper failure now, before, the test was
passing in this case.

More Info: https://github.com/KhronosGroup/OpenCL-Docs/issues/648
This commit is contained in:
Ahmed
2025-10-21 17:59:13 +01:00
committed by GitHub
parent 940c8bb973
commit a1d8c3e419
3 changed files with 803 additions and 762 deletions

BIN
test_conformance/spir/half.zip Normal file → Executable file

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -43,35 +43,37 @@
// //
// Task // Task
// //
Task::Task(cl_device_id device, const char* options): Task::Task(cl_device_id device, const char* options): m_devid(device)
m_devid(device) { {
if (options) if (options) m_options = options;
m_options = options;
} }
Task::~Task() {} Task::~Task() {}
const char* Task::getErrorLog() const { const char* Task::getErrorLog() const { return m_log.c_str(); }
return m_log.c_str();
}
void Task::setErrorLog(cl_program prog) { void Task::setErrorLog(cl_program prog)
{
size_t len = 0; size_t len = 0;
std::vector<char> log; std::vector<char> log;
cl_int err_code = clGetProgramBuildInfo(prog, m_devid, CL_PROGRAM_BUILD_LOG, 0, NULL, &len); cl_int err_code = clGetProgramBuildInfo(prog, m_devid, CL_PROGRAM_BUILD_LOG,
0, NULL, &len);
if (err_code != CL_SUCCESS) if (err_code != CL_SUCCESS)
{ {
m_log = "Error: clGetProgramBuildInfo(CL_PROGRAM_BUILD_LOG, &len) failed.\n"; m_log = "Error: clGetProgramBuildInfo(CL_PROGRAM_BUILD_LOG, &len) "
"failed.\n";
return; return;
} }
log.resize(len, 0); log.resize(len, 0);
err_code = clGetProgramBuildInfo(prog, m_devid, CL_PROGRAM_BUILD_LOG, len, &log[0], NULL); err_code = clGetProgramBuildInfo(prog, m_devid, CL_PROGRAM_BUILD_LOG, len,
&log[0], NULL);
if (err_code != CL_SUCCESS) if (err_code != CL_SUCCESS)
{ {
m_log = "Error: clGetProgramBuildInfo(CL_PROGRAM_BUILD_LOG, &log) failed.\n"; m_log = "Error: clGetProgramBuildInfo(CL_PROGRAM_BUILD_LOG, &log) "
"failed.\n";
return; return;
} }
m_log.append(&log[0]); m_log.append(&log[0]);
@@ -84,10 +86,11 @@ BuildTask::BuildTask(cl_program prog, cl_device_id dev, const char* options)
: Task(dev, options), m_program(prog) : Task(dev, options), m_program(prog)
{} {}
bool BuildTask::execute() { bool BuildTask::execute()
cl_int err_code = clBuildProgram(m_program, 0, NULL, m_options.c_str(), NULL, NULL); {
if(CL_SUCCESS == err_code) cl_int err_code =
return true; clBuildProgram(m_program, 0, NULL, m_options.c_str(), NULL, NULL);
if (CL_SUCCESS == err_code) return true;
setErrorLog(m_program); setErrorLog(m_program);
return false; return false;
@@ -96,8 +99,10 @@ bool BuildTask::execute() {
// //
// SpirBuildTask // SpirBuildTask
// //
SpirBuildTask::SpirBuildTask(cl_program prog, cl_device_id dev, const char* options) : SpirBuildTask::SpirBuildTask(cl_program prog, cl_device_id dev,
BuildTask(prog, dev, options) {} const char* options)
: BuildTask(prog, dev, options)
{}
// //
// CompileTask // CompileTask
@@ -107,26 +112,28 @@ CompileTask::CompileTask(cl_program prog, cl_device_id dev, const char* options)
: Task(dev, options), m_program(prog) : Task(dev, options), m_program(prog)
{} {}
void CompileTask::addHeader(const char* hname, cl_program hprog) { void CompileTask::addHeader(const char* hname, cl_program hprog)
{
m_headers.push_back(std::make_pair(hname, hprog)); m_headers.push_back(std::make_pair(hname, hprog));
} }
const char* first(std::pair<const char*,cl_program>& p) { const char* first(std::pair<const char*, cl_program>& p) { return p.first; }
return p.first;
}
cl_program second(const std::pair<const char*, cl_program>& p) { cl_program second(const std::pair<const char*, cl_program>& p)
{
return p.second; return p.second;
} }
bool CompileTask::execute() { bool CompileTask::execute()
{
// Generating the header names vector. // Generating the header names vector.
std::vector<const char*> names; std::vector<const char*> names;
std::transform(m_headers.begin(), m_headers.end(), names.begin(), first); std::transform(m_headers.begin(), m_headers.end(), names.begin(), first);
// Generating the header programs vector. // Generating the header programs vector.
std::vector<cl_program> programs; std::vector<cl_program> programs;
std::transform(m_headers.begin(), m_headers.end(), programs.begin(), second); std::transform(m_headers.begin(), m_headers.end(), programs.begin(),
second);
const char** h_names = NULL; const char** h_names = NULL;
const cl_program* h_programs = NULL; const cl_program* h_programs = NULL;
@@ -137,17 +144,11 @@ bool CompileTask::execute() {
} }
// Compiling with the headers. // Compiling with the headers.
cl_int err_code = clCompileProgram( cl_int err_code =
m_program, clCompileProgram(m_program, 1U, &m_devid, m_options.c_str(),
1U,
&m_devid,
m_options.c_str(),
m_headers.size(), // # of headers m_headers.size(), // # of headers
h_programs, h_programs, h_names, NULL, NULL);
h_names, if (CL_SUCCESS == err_code) return true;
NULL, NULL);
if (CL_SUCCESS == err_code)
return true;
setErrorLog(m_program); setErrorLog(m_program);
return false; return false;
@@ -156,8 +157,10 @@ bool CompileTask::execute() {
// //
// SpirCompileTask // SpirCompileTask
// //
SpirCompileTask::SpirCompileTask(cl_program prog, cl_device_id dev, const char* options) : SpirCompileTask::SpirCompileTask(cl_program prog, cl_device_id dev,
CompileTask(prog, dev, options) {} const char* options)
: CompileTask(prog, dev, options)
{}
// //
@@ -169,13 +172,16 @@ LinkTask::LinkTask(cl_program* programs, int num_programs, cl_context ctxt,
m_numPrograms(num_programs), m_context(ctxt) m_numPrograms(num_programs), m_context(ctxt)
{} {}
bool LinkTask::execute() { bool LinkTask::execute()
{
cl_int err_code; cl_int err_code;
int i; int i;
for (i = 0; i < m_numPrograms; ++i) for (i = 0; i < m_numPrograms; ++i)
{ {
err_code = clCompileProgram(m_programs[i], 1, &m_devid, "-x spir -spir-std=1.2 -cl-kernel-arg-info", 0, NULL, NULL, NULL, NULL); err_code = clCompileProgram(m_programs[i], 1, &m_devid,
"-x spir -spir-std=1.2 -cl-kernel-arg-info",
0, NULL, NULL, NULL, NULL);
if (CL_SUCCESS != err_code) if (CL_SUCCESS != err_code)
{ {
setErrorLog(m_programs[i]); setErrorLog(m_programs[i]);
@@ -183,61 +189,52 @@ bool LinkTask::execute() {
} }
} }
m_executable = clLinkProgram(m_context, 1, &m_devid, m_options.c_str(), m_numPrograms, m_programs, NULL, NULL, &err_code); m_executable =
if (CL_SUCCESS == err_code) clLinkProgram(m_context, 1, &m_devid, m_options.c_str(), m_numPrograms,
return true; m_programs, NULL, NULL, &err_code);
if (CL_SUCCESS == err_code) return true;
if (m_executable) setErrorLog(m_executable); if (m_executable) setErrorLog(m_executable);
return false; return false;
} }
cl_program LinkTask::getExecutable() const { cl_program LinkTask::getExecutable() const { return m_executable; }
return m_executable;
}
LinkTask::~LinkTask() { LinkTask::~LinkTask()
{
if (m_executable) clReleaseProgram(m_executable); if (m_executable) clReleaseProgram(m_executable);
} }
// //
// KernelEnumerator // KernelEnumerator
// //
void KernelEnumerator::process(cl_program prog) { void KernelEnumerator::process(cl_program prog)
{
const size_t MAX_KERNEL_NAME = 64; const size_t MAX_KERNEL_NAME = 64;
size_t num_kernels; size_t num_kernels;
cl_int err_code = clGetProgramInfo( cl_int err_code = clGetProgramInfo(prog, CL_PROGRAM_NUM_KERNELS,
prog, sizeof(size_t), &num_kernels, NULL);
CL_PROGRAM_NUM_KERNELS, if (CL_SUCCESS != err_code) return;
sizeof(size_t),
&num_kernels,
NULL
);
if (CL_SUCCESS != err_code)
return;
// Querying for the number of kernels. // Querying for the number of kernels.
size_t buffer_len = sizeof(char) * num_kernels * MAX_KERNEL_NAME; size_t buffer_len = sizeof(char) * num_kernels * MAX_KERNEL_NAME;
char* kernel_names = new char[buffer_len]; char* kernel_names = new char[buffer_len];
memset(kernel_names, '\0', buffer_len); memset(kernel_names, '\0', buffer_len);
size_t str_len = 0; size_t str_len = 0;
err_code = clGetProgramInfo( err_code = clGetProgramInfo(prog, CL_PROGRAM_KERNEL_NAMES, buffer_len,
prog, (void*)kernel_names, &str_len);
CL_PROGRAM_KERNEL_NAMES, if (CL_SUCCESS != err_code) return;
buffer_len,
(void *)kernel_names,
&str_len
);
if (CL_SUCCESS != err_code)
return;
// parsing the names and inserting them to the list // parsing the names and inserting them to the list
std::string names(kernel_names); std::string names(kernel_names);
assert(str_len == 1 + names.size() && "incompatible string lengths"); assert(str_len == 1 + names.size() && "incompatible string lengths");
size_t offset = 0; size_t offset = 0;
for(size_t i=0 ; i<names.size() ; ++i){ for (size_t i = 0; i < names.size(); ++i)
{
// kernel names are separated by semi colons // kernel names are separated by semi colons
if (names[i] == ';'){ if (names[i] == ';')
{
m_kernels.push_back(names.substr(offset, i - offset)); m_kernels.push_back(names.substr(offset, i - offset));
offset = i + 1; offset = i + 1;
} }
@@ -246,28 +243,24 @@ void KernelEnumerator::process(cl_program prog) {
delete[] kernel_names; delete[] kernel_names;
} }
KernelEnumerator::KernelEnumerator(cl_program prog) { KernelEnumerator::KernelEnumerator(cl_program prog) { process(prog); }
process(prog);
}
KernelEnumerator::iterator KernelEnumerator::begin(){ KernelEnumerator::iterator KernelEnumerator::begin()
{
return m_kernels.begin(); return m_kernels.begin();
} }
KernelEnumerator::iterator KernelEnumerator::end(){ KernelEnumerator::iterator KernelEnumerator::end() { return m_kernels.end(); }
return m_kernels.end();
}
size_t KernelEnumerator::size() const { size_t KernelEnumerator::size() const { return m_kernels.size(); }
return m_kernels.size();
}
/** /**
Run the single test - run the test for both CL and SPIR versions of the kernel Run the single test - run the test for both CL and SPIR versions of the kernel
*/ */
static bool run_test(cl_context context, cl_command_queue queue, cl_program clprog, static bool run_test(cl_context context, cl_command_queue queue,
cl_program bcprog, const std::string& kernel_name, std::string& err, const cl_device_id device, cl_program clprog, cl_program bcprog,
float ulps) const std::string& kernel_name, std::string& err,
const cl_device_id device, float ulps)
{ {
WorkSizeInfo ws; WorkSizeInfo ws;
TestResult cl_result; TestResult cl_result;
@@ -276,7 +269,8 @@ static bool run_test(cl_context context, cl_command_queue queue, cl_program clpr
{ {
// make sure that the kernel will be released before the program // make sure that the kernel will be released before the program
clKernelWrapper kernel = create_kernel_helper(clprog, kernel_name); clKernelWrapper kernel = create_kernel_helper(clprog, kernel_name);
// based on the kernel characteristics, we are generating and initializing the arguments for both phases (cl and bc executions) // based on the kernel characteristics, we are generating and
// initializing the arguments for both phases (cl and bc executions)
generate_kernel_data(context, kernel, ws, cl_result); generate_kernel_data(context, kernel, ws, cl_result);
bc_result.reset(cl_result.clone(context, ws, kernel, device)); bc_result.reset(cl_result.clone(context, ws, kernel, device));
assert(compare_results(cl_result, *bc_result, ulps) && "not equal?"); assert(compare_results(cl_result, *bc_result, ulps) && "not equal?");
@@ -337,8 +331,9 @@ static float get_max_ulps(const char *test_name)
} }
TestRunner::TestRunner(EventHandler* success, EventHandler* failure, TestRunner::TestRunner(EventHandler* success, EventHandler* failure,
const OclExtensions& devExt): const OclExtensions& devExt)
m_successHandler(success), m_failureHandler(failure), m_devExt(&devExt) {} : m_successHandler(success), m_failureHandler(failure), m_devExt(&devExt)
{}
/** /**
Based on the test name build the cl file name, the bc file name and execute Based on the test name build the cl file name, the bc file name and execute
@@ -365,20 +360,25 @@ bool TestRunner::runBuildTest(cl_device_id device, const char *folder,
cl_bool images3D = khrDb.isImages3DRequired(folder, test_name); cl_bool images3D = khrDb.isImages3DRequired(folder, test_name);
char deviceProfile[64]; char deviceProfile[64];
clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(deviceProfile), &deviceProfile, NULL); clGetDeviceInfo(device, CL_DEVICE_PROFILE, sizeof(deviceProfile),
&deviceProfile, NULL);
std::string device_profile(deviceProfile, 64); std::string device_profile(deviceProfile, 64);
if (images == CL_TRUE && checkForImageSupport(device) != 0) if (images == CL_TRUE && checkForImageSupport(device) != 0)
{ {
(*m_successHandler)(test_name, ""); (*m_successHandler)(test_name, "");
std::cout << "Skipped. (Cannot run on device due to Images is not supported)." << std::endl; std::cout
<< "Skipped. (Cannot run on device due to Images is not supported)."
<< std::endl;
return true; return true;
} }
if (images3D == CL_TRUE && checkFor3DImageSupport(device) != 0) if (images3D == CL_TRUE && checkFor3DImageSupport(device) != 0)
{ {
(*m_successHandler)(test_name, ""); (*m_successHandler)(test_name, "");
std::cout << "Skipped. (Cannot run on device as 3D images are not supported)." << std::endl; std::cout
<< "Skipped. (Cannot run on device as 3D images are not supported)."
<< std::endl;
return true; return true;
} }
@@ -386,7 +386,9 @@ bool TestRunner::runBuildTest(cl_device_id device, const char *folder,
if (!m_devExt->supports(requiredExt)) if (!m_devExt->supports(requiredExt))
{ {
(*m_successHandler)(test_name, ""); (*m_successHandler)(test_name, "");
std::cout << "Skipped. (Cannot run on device due to missing extensions: " << m_devExt->get_missing(requiredExt) << " )." << std::endl; std::cout
<< "Skipped. (Cannot run on device due to missing extensions: "
<< m_devExt->get_missing(requiredExt) << " )." << std::endl;
return true; return true;
} }
@@ -409,17 +411,26 @@ bool TestRunner::runBuildTest(cl_device_id device, const char *folder,
cl_device_fp_config gFloatCapabilities = 0; cl_device_fp_config gFloatCapabilities = 0;
cl_int err; cl_int err;
if ((err = clGetDeviceInfo(device, CL_DEVICE_SINGLE_FP_CONFIG, sizeof(gFloatCapabilities), &gFloatCapabilities, NULL))) if ((err = clGetDeviceInfo(device, CL_DEVICE_SINGLE_FP_CONFIG,
sizeof(gFloatCapabilities), &gFloatCapabilities,
NULL)))
{ {
log_info("Unable to get device CL_DEVICE_SINGLE_FP_CONFIG. (%d)\n", err); log_info("Unable to get device CL_DEVICE_SINGLE_FP_CONFIG. (%d)\n",
err);
} }
if (strstr(test_name, "div_cr") || strstr(test_name, "sqrt_cr")) { if (strstr(test_name, "div_cr") || strstr(test_name, "sqrt_cr"))
if ((gFloatCapabilities & CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT) == 0) { {
if ((gFloatCapabilities & CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT) == 0)
{
(*m_successHandler)(test_name, ""); (*m_successHandler)(test_name, "");
std::cout << "Skipped. (Cannot run on device due to missing CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT property.)" << std::endl; std::cout << "Skipped. (Cannot run on device due to missing "
"CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT property.)"
<< std::endl;
return true; return true;
} else { }
else
{
bcoptions += " -cl-fp32-correctly-rounded-divide-sqrt"; bcoptions += " -cl-fp32-correctly-rounded-divide-sqrt";
cloptions += " -cl-fp32-correctly-rounded-divide-sqrt"; cloptions += " -cl-fp32-correctly-rounded-divide-sqrt";
} }
@@ -427,22 +438,27 @@ bool TestRunner::runBuildTest(cl_device_id device, const char *folder,
// Building the programs. // Building the programs.
BuildTask clBuild(clprog, device, cloptions.c_str()); BuildTask clBuild(clprog, device, cloptions.c_str());
if (!clBuild.execute()) { if (!clBuild.execute())
{
std::cerr << clBuild.getErrorLog() << std::endl; std::cerr << clBuild.getErrorLog() << std::endl;
(*m_failureHandler)(test_name, "");
return false; return false;
} }
SpirBuildTask bcBuild(bcprog, device, bcoptions.c_str()); SpirBuildTask bcBuild(bcprog, device, bcoptions.c_str());
if (!bcBuild.execute()) { if (!bcBuild.execute())
{
std::cerr << bcBuild.getErrorLog() << std::endl; std::cerr << bcBuild.getErrorLog() << std::endl;
(*m_failureHandler)(test_name, "");
return false; return false;
} }
KernelEnumerator clkernel_enumerator(clprog), KernelEnumerator clkernel_enumerator(clprog), bckernel_enumerator(bcprog);
bckernel_enumerator(bcprog); if (clkernel_enumerator.size() != bckernel_enumerator.size())
if (clkernel_enumerator.size() != bckernel_enumerator.size()) { {
std::cerr << "number of kernels in test" << test_name std::cerr << "number of kernels in test" << test_name
<< " doesn't match in bc and cl files" << std::endl; << " doesn't match in bc and cl files" << std::endl;
(*m_failureHandler)(test_name, "");
return false; return false;
} }
KernelEnumerator::iterator it = clkernel_enumerator.begin(), KernelEnumerator::iterator it = clkernel_enumerator.begin(),
@@ -453,7 +469,8 @@ bool TestRunner::runBuildTest(cl_device_id device, const char *folder,
std::string err; std::string err;
try try
{ {
bool success = run_test(context, queue, clprog, bcprog, kernel_name, err, device, ulps); bool success = run_test(context, queue, clprog, bcprog, kernel_name,
err, device, ulps);
if (success) if (success)
{ {
log_info("kernel '%s' passed.\n", kernel_name.c_str()); log_info("kernel '%s' passed.\n", kernel_name.c_str());
@@ -468,7 +485,8 @@ bool TestRunner::runBuildTest(cl_device_id device, const char *folder,
} catch (const std::runtime_error& err) } catch (const std::runtime_error& err)
{ {
++failures; ++failures;
log_info("kernel '%s' failed: %s\n", kernel_name.c_str(), err.what()); log_info("kernel '%s' failed: %s\n", kernel_name.c_str(),
err.what());
(*m_failureHandler)(test_name, kernel_name); (*m_failureHandler)(test_name, kernel_name);
} }
} }
@@ -476,4 +494,3 @@ bool TestRunner::runBuildTest(cl_device_id device, const char *folder,
log_info("%s %s\n", test_name, failures ? "FAILED" : "passed."); log_info("%s %s\n", test_name, failures ? "FAILED" : "passed.");
return failures == 0; return failures == 0;
} }