mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-23 07:39:01 +00:00
Initial open source release of OpenCL 2.2 CTS.
This commit is contained in:
12
test_conformance/clcpp/spec_constants/CMakeLists.txt
Normal file
12
test_conformance/clcpp/spec_constants/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
set(MODULE_NAME CPP_SPEC_CONSTANTS)
|
||||
|
||||
set(${MODULE_NAME}_SOURCES
|
||||
main.cpp
|
||||
../../../test_common/harness/errorHelpers.c
|
||||
../../../test_common/harness/testHarness.c
|
||||
../../../test_common/harness/kernelHelpers.c
|
||||
../../../test_common/harness/msvc9.c
|
||||
../../../test_common/harness/parseParameters.cpp
|
||||
)
|
||||
|
||||
include(../../CMakeCommon.txt)
|
||||
257
test_conformance/clcpp/spec_constants/common.hpp
Normal file
257
test_conformance/clcpp/spec_constants/common.hpp
Normal file
@@ -0,0 +1,257 @@
|
||||
//
|
||||
// Copyright (c) 2017 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.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_COMMON_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_COMMON_HPP
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "../common.hpp"
|
||||
#include "../funcs_test_utils.hpp"
|
||||
|
||||
#define RUN_SPEC_CONSTANTS_TEST_MACRO(TEST_CLASS) \
|
||||
last_error = run_spec_constants_test( \
|
||||
device, context, queue, n_elems, TEST_CLASS \
|
||||
); \
|
||||
CHECK_ERROR(last_error) \
|
||||
error |= last_error;
|
||||
|
||||
// Base class for all tests of cl::spec_contatnt
|
||||
template <class T>
|
||||
struct spec_constants_test : public detail::base_func_type<T>
|
||||
{
|
||||
// Output buffer type
|
||||
typedef T type;
|
||||
|
||||
virtual ~spec_constants_test() {};
|
||||
// Returns test name
|
||||
virtual std::string str() = 0;
|
||||
// Returns OpenCL program source
|
||||
virtual std::string generate_program() = 0;
|
||||
|
||||
// Return names of test's kernels, in order.
|
||||
// Typical case: one kernel.
|
||||
virtual std::vector<std::string> get_kernel_names()
|
||||
{
|
||||
// Typical case, that is, only one kernel
|
||||
return { this->get_kernel_name() };
|
||||
}
|
||||
|
||||
// If local size has to be set in clEnqueueNDRangeKernel()
|
||||
// this should return true; otherwise - false;
|
||||
virtual bool set_local_size()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Calculates maximal work-group size (one dim)
|
||||
virtual size_t get_max_local_size(const std::vector<cl_kernel>& kernels,
|
||||
cl_device_id device,
|
||||
size_t work_group_size, // default work-group size
|
||||
cl_int& error)
|
||||
{
|
||||
size_t wg_size = work_group_size;
|
||||
for(auto& k : kernels)
|
||||
{
|
||||
size_t max_wg_size;
|
||||
error = clGetKernelWorkGroupInfo(
|
||||
k, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &max_wg_size, NULL
|
||||
);
|
||||
RETURN_ON_CL_ERROR(error, "clGetKernelWorkGroupInfo")
|
||||
wg_size = (std::min)(wg_size, max_wg_size);
|
||||
}
|
||||
return wg_size;
|
||||
}
|
||||
|
||||
// Sets spec constants
|
||||
// Typical case: no spec constants to set
|
||||
virtual cl_int set_spec_constants(const cl_program& program)
|
||||
{
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
// This covers typical case:
|
||||
// 1. each kernel is executed once,
|
||||
// 2. the only argument in every kernel is output_buffer
|
||||
virtual cl_int execute(const std::vector<cl_kernel>& kernels,
|
||||
cl_mem& output_buffer,
|
||||
cl_command_queue& queue,
|
||||
size_t work_size,
|
||||
size_t work_group_size)
|
||||
{
|
||||
cl_int err;
|
||||
for(auto& k : kernels)
|
||||
{
|
||||
err = clSetKernelArg(k, 0, sizeof(output_buffer), &output_buffer);
|
||||
RETURN_ON_CL_ERROR(err, "clSetKernelArg");
|
||||
|
||||
err = clEnqueueNDRangeKernel(
|
||||
queue, k, 1,
|
||||
NULL, &work_size, this->set_local_size() ? &work_group_size : NULL,
|
||||
0, NULL, NULL
|
||||
);
|
||||
RETURN_ON_CL_ERROR(err, "clEnqueueNDRangeKernel");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
// This is a function which performs additional queries and checks
|
||||
// if the results are correct. This method is run after checking that
|
||||
// test results (output values) are correct.
|
||||
virtual cl_int check_queries(const std::vector<cl_kernel>& kernels,
|
||||
cl_device_id device,
|
||||
cl_context context,
|
||||
cl_command_queue queue)
|
||||
{
|
||||
(void) kernels;
|
||||
(void) device;
|
||||
(void) context;
|
||||
(void) queue;
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
};
|
||||
|
||||
template <class spec_constants_test>
|
||||
int run_spec_constants_test(cl_device_id device, cl_context context, cl_command_queue queue, size_t count, spec_constants_test op)
|
||||
{
|
||||
cl_mem buffers[1];
|
||||
cl_program program;
|
||||
std::vector<cl_kernel> kernels;
|
||||
size_t wg_size;
|
||||
size_t work_size[1];
|
||||
cl_int err;
|
||||
|
||||
typedef typename spec_constants_test::type TYPE;
|
||||
|
||||
// Don't run test for unsupported types
|
||||
if(!(type_supported<TYPE>(device)))
|
||||
{
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
std::string code_str = op.generate_program();
|
||||
std::vector<std::string> kernel_names = op.get_kernel_names();
|
||||
if(kernel_names.empty())
|
||||
{
|
||||
RETURN_ON_ERROR_MSG(-1, "No kernel to run");
|
||||
}
|
||||
kernels.resize(kernel_names.size());
|
||||
|
||||
std::string options = "";
|
||||
if(is_extension_available(device, "cl_khr_fp16"))
|
||||
{
|
||||
options += " -cl-fp16-enable";
|
||||
}
|
||||
if(is_extension_available(device, "cl_khr_fp64"))
|
||||
{
|
||||
options += " -cl-fp64-enable";
|
||||
}
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Only OpenCL C++ to SPIR-V compilation
|
||||
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
|
||||
err = create_opencl_kernel(context, &program, &(kernels[0]), code_str, kernel_names[0], options);
|
||||
return err;
|
||||
// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code)
|
||||
#elif defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
|
||||
err = create_opencl_kernel(context, &program, &(kernels[0]), code_str, kernel_names[0], "-cl-std=CL2.0", false);
|
||||
RETURN_ON_ERROR(err)
|
||||
for(size_t i = 1; i < kernels.size(); i++)
|
||||
{
|
||||
kernels[i] = clCreateKernel(program, kernel_names[i].c_str(), &err);
|
||||
RETURN_ON_CL_ERROR(err, "clCreateKernel");
|
||||
}
|
||||
#else
|
||||
const char * code_c_str = code_str.c_str();
|
||||
err = create_openclcpp_program(context, &program, 1, &(code_c_str), options.c_str());
|
||||
RETURN_ON_ERROR_MSG(err, "Creating OpenCL C++ program failed")
|
||||
|
||||
// Set spec constants
|
||||
err = op.set_spec_constants(program);
|
||||
RETURN_ON_ERROR_MSG(err, "Setting Spec Constants failed")
|
||||
|
||||
// Build program and create 1st kernel
|
||||
err = build_program_create_kernel_helper(
|
||||
context, &program, &(kernels[0]), 1, &(code_c_str), kernel_names[0].c_str()
|
||||
);
|
||||
RETURN_ON_ERROR_MSG(err, "Unable to build program or to create kernel")
|
||||
// Create other kernels
|
||||
for(size_t i = 1; i < kernels.size(); i++)
|
||||
{
|
||||
kernels[i] = clCreateKernel(program, kernel_names[i].c_str(), &err);
|
||||
RETURN_ON_CL_ERROR(err, "clCreateKernel");
|
||||
}
|
||||
#endif
|
||||
|
||||
// Find the max possible wg size for among all the kernels
|
||||
wg_size = op.get_max_local_size(kernels, device, 1024, err);
|
||||
RETURN_ON_ERROR(err);
|
||||
|
||||
work_size[0] = count;
|
||||
if(op.set_local_size())
|
||||
{
|
||||
size_t wg_number = static_cast<size_t>(
|
||||
std::ceil(static_cast<double>(count) / wg_size)
|
||||
);
|
||||
work_size[0] = wg_number * wg_size;
|
||||
}
|
||||
|
||||
// host output vector
|
||||
std::vector<TYPE> output = generate_output<TYPE>(work_size[0], 9999);
|
||||
|
||||
// device output buffer
|
||||
buffers[0] = clCreateBuffer(
|
||||
context, (cl_mem_flags)(CL_MEM_READ_WRITE), sizeof(TYPE) * output.size(), NULL, &err
|
||||
);
|
||||
RETURN_ON_CL_ERROR(err, "clCreateBuffer");
|
||||
|
||||
// Execute test
|
||||
err = op.execute(kernels, buffers[0], queue, work_size[0], wg_size);
|
||||
RETURN_ON_ERROR(err)
|
||||
|
||||
err = clEnqueueReadBuffer(
|
||||
queue, buffers[0], CL_TRUE, 0, sizeof(TYPE) * output.size(),
|
||||
static_cast<void *>(output.data()), 0, NULL, NULL
|
||||
);
|
||||
RETURN_ON_CL_ERROR(err, "clEnqueueReadBuffer");
|
||||
|
||||
// Check output values
|
||||
for(size_t i = 0; i < output.size(); i++)
|
||||
{
|
||||
TYPE v = op(i, wg_size);
|
||||
if(!(are_equal(v, output[i], detail::make_value<TYPE>(0), op)))
|
||||
{
|
||||
RETURN_ON_ERROR_MSG(-1,
|
||||
"test_%s(%s) failed. Expected: %s, got: %s", op.str().c_str(), type_name<cl_uint>().c_str(),
|
||||
format_value(v).c_str(), format_value(output[i]).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if queries returns correct values
|
||||
err = op.check_queries(kernels, device, context, queue);
|
||||
RETURN_ON_ERROR(err);
|
||||
|
||||
log_info("test_%s(%s) passed\n", op.str().c_str(), type_name<TYPE>().c_str());
|
||||
|
||||
clReleaseMemObject(buffers[0]);
|
||||
for(auto& k : kernels)
|
||||
clReleaseKernel(k);
|
||||
clReleaseProgram(program);
|
||||
return err;
|
||||
}
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_COMMON_HPP
|
||||
31
test_conformance/clcpp/spec_constants/main.cpp
Normal file
31
test_conformance/clcpp/spec_constants/main.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// Copyright (c) 2017 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 "../common.hpp"
|
||||
|
||||
#include "test_spec_consts_attributes.hpp"
|
||||
#include "test_spec_consts_if.hpp"
|
||||
#include "test_spec_consts_init_vars.hpp"
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
// Get list to all test functions
|
||||
std::vector<basefn> testfn_list = autotest::test_suite::get_test_functions();
|
||||
// Get names of all test functions
|
||||
std::vector<std::string> testfn_names = autotest::test_suite::get_test_names();
|
||||
// Create a vector of pointers to the names test functions
|
||||
std::vector<const char *> testfn_names_c_str = autotest::get_strings_ptrs(testfn_names);
|
||||
return runTestHarness(argc, argv, testfn_list.size(), testfn_list.data(), testfn_names_c_str.data(), false, false, 0);
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
//
|
||||
// Copyright (c) 2017 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.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_ATTRIBUTES_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_ATTRIBUTES_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
// In this test we check if specialization constant can be successfully used
|
||||
// in kernel attribute cl::required_work_group_size(X, Y, Z).
|
||||
struct spec_const_required_work_group_size_test : public spec_constants_test<cl_uint>
|
||||
{
|
||||
// See generate_program() to know what set_spec_constant is for.
|
||||
spec_const_required_work_group_size_test(const bool set_spec_constant,
|
||||
const cl_uint work_group_size_0)
|
||||
: m_set_spec_constant(set_spec_constant),
|
||||
m_work_group_size_0(work_group_size_0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
std::string str()
|
||||
{
|
||||
if(m_set_spec_constant)
|
||||
return "spec_const_in_required_work_group_size_" + std::to_string(m_work_group_size_0);
|
||||
else
|
||||
return "spec_const_in_required_work_group_size_not_set";
|
||||
}
|
||||
|
||||
bool set_local_size()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t get_max_local_size(const std::vector<cl_kernel>& kernels,
|
||||
cl_device_id device,
|
||||
size_t work_group_size, // default work-group size
|
||||
cl_int& error)
|
||||
{
|
||||
if(m_set_spec_constant)
|
||||
{
|
||||
return m_work_group_size_0;
|
||||
}
|
||||
return size_t(1);
|
||||
}
|
||||
|
||||
cl_uint operator()(size_t i, size_t work_group_size)
|
||||
{
|
||||
(void) work_group_size;
|
||||
if(m_set_spec_constant)
|
||||
{
|
||||
return m_work_group_size_0;
|
||||
}
|
||||
return cl_uint(1);
|
||||
}
|
||||
|
||||
// Check if query for CL_KERNEL_COMPILE_WORK_GROUP_SIZE using clGetKernelWorkGroupInfo
|
||||
// return correct values. It should return the work-group size specified by the
|
||||
// cl::required_work_group_size(X, Y, Z) qualifier.
|
||||
cl_int check_queries(const std::vector<cl_kernel>& kernels,
|
||||
cl_device_id device,
|
||||
cl_context context,
|
||||
cl_command_queue queue)
|
||||
{
|
||||
(void) device;
|
||||
(void) context;
|
||||
size_t compile_wg_size[] = { 1, 1, 1 };
|
||||
cl_int error = clGetKernelWorkGroupInfo(
|
||||
kernels[0], device, CL_KERNEL_COMPILE_WORK_GROUP_SIZE,
|
||||
sizeof(compile_wg_size), compile_wg_size, NULL
|
||||
);
|
||||
RETURN_ON_CL_ERROR(error, "clGetKernelWorkGroupInfo")
|
||||
if(m_set_spec_constant)
|
||||
{
|
||||
if(compile_wg_size[0] != m_work_group_size_0
|
||||
|| compile_wg_size[1] != 1
|
||||
|| compile_wg_size[2] != 1)
|
||||
{
|
||||
error = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(compile_wg_size[0] != 1
|
||||
|| compile_wg_size[1] != 1
|
||||
|| compile_wg_size[2] != 1)
|
||||
{
|
||||
error = -1;
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// Sets spec constant
|
||||
cl_int set_spec_constants(const cl_program& program)
|
||||
{
|
||||
cl_int error = CL_SUCCESS;
|
||||
if(m_set_spec_constant)
|
||||
{
|
||||
error = clSetProgramSpecializationConstant(
|
||||
program, cl_uint(1), sizeof(cl_uint), static_cast<void*>(&m_work_group_size_0)
|
||||
);
|
||||
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// Each work-item writes get_local_size(0) to output[work-item-global-id]
|
||||
std::string generate_program(bool with_attribute)
|
||||
{
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
|
||||
std::string att = " ";
|
||||
if(with_attribute)
|
||||
{
|
||||
std::string work_group_size_0 = "1";
|
||||
if(m_set_spec_constant)
|
||||
{
|
||||
work_group_size_0 = std::to_string(m_work_group_size_0);
|
||||
}
|
||||
att = "\n__attribute__((reqd_work_group_size(" + work_group_size_0 + ",1,1)))\n";
|
||||
}
|
||||
return
|
||||
"__kernel" + att + "void " + this->get_kernel_name() + "(global uint *output)\n"
|
||||
"{\n"
|
||||
" uint gid = get_global_id(0);\n"
|
||||
" output[gid] = get_local_size(0);\n"
|
||||
"}\n";
|
||||
|
||||
#else
|
||||
std::string att = "";
|
||||
if(with_attribute)
|
||||
{
|
||||
att = "[[cl::required_work_group_size(spec1, 1, 1)]]\n";
|
||||
}
|
||||
return
|
||||
"#include <opencl_memory>\n"
|
||||
"#include <opencl_work_item>\n"
|
||||
"#include <opencl_spec_constant>\n"
|
||||
"using namespace cl;\n"
|
||||
"spec_constant<uint, 1> spec1{1};\n"
|
||||
+ att +
|
||||
"__kernel void " + this->get_kernel_name() + "(global_ptr<uint[]> output)\n"
|
||||
"{\n"
|
||||
" uint gid = get_global_id(0);\n"
|
||||
" output[gid] = get_local_size(0);\n"
|
||||
"}\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
// Each work-item writes get_local_size(0) to output[work-item-global-id]
|
||||
std::string generate_program()
|
||||
{
|
||||
return generate_program(true);
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_set_spec_constant;
|
||||
cl_uint m_work_group_size_0;
|
||||
};
|
||||
|
||||
// This function return max work-group size that can be used
|
||||
// for kernels defined in source
|
||||
size_t get_max_wg_size(const std::string& source,
|
||||
const std::vector<std::string>& kernel_names,
|
||||
size_t work_group_size, // max wg size we want to have
|
||||
cl_device_id device,
|
||||
cl_context context,
|
||||
cl_command_queue queue,
|
||||
cl_int& err)
|
||||
{
|
||||
cl_program program;
|
||||
std::vector<cl_kernel> kernels;
|
||||
if(kernel_names.empty())
|
||||
{
|
||||
RETURN_ON_ERROR_MSG(-1, "No kernel to run");
|
||||
}
|
||||
kernels.resize(kernel_names.size());
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
// Use OpenCL C kernels instead of OpenCL C++ kernels (test C++ host code)
|
||||
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
|
||||
err = create_opencl_kernel(context, &program, &(kernels[0]), source, kernel_names[0], "-cl-std=CL2.0", false);
|
||||
RETURN_ON_ERROR(err)
|
||||
for(size_t i = 1; i < kernels.size(); i++)
|
||||
{
|
||||
kernels[i] = clCreateKernel(program, kernel_names[i].c_str(), &err);
|
||||
RETURN_ON_CL_ERROR(err, "clCreateKernel");
|
||||
}
|
||||
#else
|
||||
err = create_opencl_kernel(context, &program, &(kernels[0]), source, kernel_names[0]);
|
||||
RETURN_ON_ERROR(err)
|
||||
for(size_t i = 1; i < kernels.size(); i++)
|
||||
{
|
||||
kernels[i] = clCreateKernel(program, kernel_names[i].c_str(), &err);
|
||||
RETURN_ON_CL_ERROR(err, "clCreateKernel");
|
||||
}
|
||||
#endif
|
||||
size_t wg_size = work_group_size;
|
||||
for(auto& k : kernels)
|
||||
{
|
||||
size_t max_wg_size;
|
||||
err = clGetKernelWorkGroupInfo(
|
||||
k, device, CL_KERNEL_WORK_GROUP_SIZE, sizeof(size_t), &max_wg_size, NULL
|
||||
);
|
||||
RETURN_ON_CL_ERROR(err, "clGetKernelWorkGroupInfo")
|
||||
wg_size = (std::min)(wg_size, max_wg_size);
|
||||
}
|
||||
return wg_size;
|
||||
}
|
||||
|
||||
AUTO_TEST_CASE(test_spec_constants_in_kernel_attributes)
|
||||
(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems)
|
||||
{
|
||||
int error = CL_SUCCESS;
|
||||
int last_error = CL_SUCCESS;
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
// If ONLY_SPIRV_COMPILATION is defined we can't check the max work-group size for the
|
||||
// kernel because OpenCL kernel object is never created in that mode.
|
||||
#if defined(DEVELOPMENT) && defined(ONLY_SPIRV_COMPILATION)
|
||||
const size_t max_wg_size = 16;
|
||||
#else
|
||||
// Get max work-group size that can be used in [[cl::required_work_group_size(X, 1, 1)]]
|
||||
// We do this by building kernel without this attribute and checking what is the max
|
||||
// work-group size we can use with it.
|
||||
auto test = spec_const_required_work_group_size_test(true, 1);
|
||||
const size_t max_wg_size = get_max_wg_size(
|
||||
test.generate_program(false), test.get_kernel_names(),
|
||||
1024, // max wg size we want to test
|
||||
device, context, queue,
|
||||
error
|
||||
);
|
||||
RETURN_ON_ERROR_MSG(error, "Can't get max work-group size");
|
||||
#endif
|
||||
|
||||
// Run tests when specialization constant spec1 is set (kernel
|
||||
// attribute is [[cl::required_work_group_size(spec1, 1, 1)]]).
|
||||
for(size_t i = 1; i <= max_wg_size; i *=2)
|
||||
{
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(
|
||||
spec_const_required_work_group_size_test(
|
||||
true, i
|
||||
)
|
||||
);
|
||||
}
|
||||
// This test does not set spec constant
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(
|
||||
spec_const_required_work_group_size_test(
|
||||
false, 9999999 // This value is incorrect, but won't be set and kernel
|
||||
// attribute should be [[cl::required_work_group_size(1, 1, 1)]]
|
||||
)
|
||||
);
|
||||
|
||||
if(error != CL_SUCCESS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_ATTRIBUTES_HPP
|
||||
161
test_conformance/clcpp/spec_constants/test_spec_consts_if.hpp
Normal file
161
test_conformance/clcpp/spec_constants/test_spec_consts_if.hpp
Normal file
@@ -0,0 +1,161 @@
|
||||
//
|
||||
// Copyright (c) 2017 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.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_IF_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_IF_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
// This class tests using specialization constant in if statement
|
||||
template <class T /* spec constant type*/>
|
||||
struct spec_const_in_if_test : public spec_constants_test<cl_uint>
|
||||
{
|
||||
// See generate_program() to know what set_spec_constant is for.
|
||||
spec_const_in_if_test(const bool set_spec_constant)
|
||||
: m_set_spec_constant(set_spec_constant)
|
||||
{
|
||||
static_assert(
|
||||
is_vector_type<T>::value == false,
|
||||
"Specialization constant can be only scalar int or float type"
|
||||
);
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case 1:
|
||||
m_test_value = T(127);
|
||||
break;
|
||||
case 2:
|
||||
m_test_value = T(0xdeadU);
|
||||
break;
|
||||
// 4 and 8
|
||||
default:
|
||||
m_test_value = T(0xdeaddeadU);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string str()
|
||||
{
|
||||
return "spec_const_in_if_" + type_name<T>();
|
||||
}
|
||||
|
||||
cl_uint operator()(size_t i, size_t work_group_size)
|
||||
{
|
||||
(void) work_group_size;
|
||||
if(m_set_spec_constant)
|
||||
{
|
||||
return m_test_value;
|
||||
}
|
||||
return static_cast<cl_uint>(i);
|
||||
}
|
||||
|
||||
// Sets spec constant
|
||||
cl_int set_spec_constants(const cl_program& program)
|
||||
{
|
||||
cl_int error = CL_SUCCESS;
|
||||
if(m_set_spec_constant)
|
||||
{
|
||||
T spec1 = static_cast<T>(m_test_value);
|
||||
error = clSetProgramSpecializationConstant(
|
||||
program, cl_uint(1), sizeof(T), static_cast<void*>(&spec1)
|
||||
);
|
||||
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// IF set_spec_constant == true:
|
||||
// each work-item writes T(m_test_value) to output[work-item-global-id]
|
||||
// Otherwise:
|
||||
// each work-item writes T(get_global_id(0)) to output[work-item-global-id]
|
||||
std::string generate_program()
|
||||
{
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
|
||||
std::string result = "gid";
|
||||
if(m_set_spec_constant)
|
||||
result = std::to_string(m_test_value);
|
||||
return
|
||||
"__kernel void " + this->get_kernel_name() + "(global uint *output)\n"
|
||||
"{\n"
|
||||
" uint gid = get_global_id(0);\n"
|
||||
" output[gid] = " + result + ";\n"
|
||||
"}\n";
|
||||
|
||||
#else
|
||||
return
|
||||
"#include <opencl_memory>\n"
|
||||
"#include <opencl_work_item>\n"
|
||||
"#include <opencl_spec_constant>\n"
|
||||
"using namespace cl;\n"
|
||||
"typedef " + type_name<T>() + " TYPE;\n"
|
||||
"spec_constant<TYPE, 1> spec1{TYPE(0)};\n"
|
||||
"__kernel void " + this->get_kernel_name() + "(global_ptr<uint[]> output)\n"
|
||||
"{\n"
|
||||
" uint gid = get_global_id(0);\n"
|
||||
" if(get(spec1) == TYPE(" + std::to_string(m_test_value) +"))\n"
|
||||
" {\n"
|
||||
" output[gid] = " + std::to_string(m_test_value) +";\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" output[gid] = gid;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_set_spec_constant;
|
||||
cl_uint m_test_value;
|
||||
};
|
||||
|
||||
AUTO_TEST_CASE(test_spec_constants_in_if_statement)
|
||||
(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems)
|
||||
{
|
||||
int error = CL_SUCCESS;
|
||||
int last_error = CL_SUCCESS;
|
||||
|
||||
const std::vector<bool> set_spec_const_options { true, false };
|
||||
for(auto option : set_spec_const_options)
|
||||
{
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test<cl_char>(option));
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test<cl_uchar>(option));
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test<cl_int>(option));
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test<cl_uint>(option));
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test<cl_long>(option));
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test<cl_ulong>(option));
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test<cl_float>(option));
|
||||
if(is_extension_available(device, "cl_khr_fp16"))
|
||||
{
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test<cl_half>(option));
|
||||
}
|
||||
if(is_extension_available(device, "cl_khr_fp64"))
|
||||
{
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_in_if_test<cl_double>(option));
|
||||
}
|
||||
}
|
||||
|
||||
if(error != CL_SUCCESS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_IF_HPP
|
||||
@@ -0,0 +1,174 @@
|
||||
//
|
||||
// Copyright (c) 2017 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.
|
||||
//
|
||||
#ifndef TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_INIT_VARS_HPP
|
||||
#define TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_INIT_VARS_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "common.hpp"
|
||||
|
||||
// This class tests initializing variables with a specialization constant value.
|
||||
template <class T /* spec constant type*/>
|
||||
struct spec_const_init_var : public spec_constants_test<cl_uint>
|
||||
{
|
||||
// See generate_program() to know what set_spec_constant is for.
|
||||
spec_const_init_var(const bool set_spec_constant)
|
||||
: m_set_spec_constant(set_spec_constant)
|
||||
{
|
||||
static_assert(
|
||||
is_vector_type<T>::value == false,
|
||||
"Specialization constant can be only scalar int or float type"
|
||||
);
|
||||
switch (sizeof(T))
|
||||
{
|
||||
case 1:
|
||||
m_test_value = T(127);
|
||||
break;
|
||||
case 2:
|
||||
m_test_value = T(0xdeadU);
|
||||
break;
|
||||
// 4 and 8
|
||||
default:
|
||||
m_test_value = T(0xdeaddeadU);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string str()
|
||||
{
|
||||
return "spec_const_init_var_" + type_name<T>();
|
||||
}
|
||||
|
||||
cl_uint operator()(size_t i, size_t work_group_size)
|
||||
{
|
||||
(void) work_group_size;
|
||||
if(m_set_spec_constant)
|
||||
{
|
||||
return m_test_value;
|
||||
}
|
||||
return static_cast<cl_uint>(i);
|
||||
}
|
||||
|
||||
// Sets spec constant
|
||||
cl_int set_spec_constants(const cl_program& program)
|
||||
{
|
||||
cl_int error = CL_SUCCESS;
|
||||
if(m_set_spec_constant)
|
||||
{
|
||||
T spec = static_cast<T>(m_test_value);
|
||||
// spec1
|
||||
error = clSetProgramSpecializationConstant(
|
||||
program, cl_uint(1), sizeof(T), static_cast<void*>(&spec)
|
||||
);
|
||||
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
|
||||
|
||||
// spec2
|
||||
error = clSetProgramSpecializationConstant(
|
||||
program, cl_uint(2), sizeof(T), static_cast<void*>(&spec)
|
||||
);
|
||||
RETURN_ON_CL_ERROR(error, "clSetProgramSpecializationConstant")
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
// IF set_spec_constant == true:
|
||||
// each work-item writes T(m_test_value) to output[work-item-global-id]
|
||||
// Otherwise:
|
||||
// each work-item writes T(get_global_id(0)) to output[work-item-global-id]
|
||||
std::string generate_program()
|
||||
{
|
||||
// -----------------------------------------------------------------------------------
|
||||
// ------------- ONLY FOR OPENCL 22 CONFORMANCE TEST 22 DEVELOPMENT ------------------
|
||||
// -----------------------------------------------------------------------------------
|
||||
#if defined(DEVELOPMENT) && defined(USE_OPENCLC_KERNELS)
|
||||
std::string result = "gid";
|
||||
if(m_set_spec_constant)
|
||||
result = std::to_string(m_test_value);
|
||||
return
|
||||
"__kernel void " + this->get_kernel_name() + "(global uint *output)\n"
|
||||
"{\n"
|
||||
" uint gid = get_global_id(0);\n"
|
||||
" output[gid] = " + result + ";\n"
|
||||
"}\n";
|
||||
|
||||
#else
|
||||
return
|
||||
"#include <opencl_memory>\n"
|
||||
"#include <opencl_work_item>\n"
|
||||
"#include <opencl_spec_constant>\n"
|
||||
"using namespace cl;\n"
|
||||
"typedef " + type_name<T>() + " TYPE;\n"
|
||||
"spec_constant<TYPE, 1> spec1{TYPE(0)};\n"
|
||||
"spec_constant<TYPE, 2> spec2{TYPE(0)};\n"
|
||||
"__kernel void " + this->get_kernel_name() + "(global_ptr<uint[]> output)\n"
|
||||
"{\n"
|
||||
" uint gid = get_global_id(0);\n"
|
||||
" TYPE var1(spec1.get());\n"
|
||||
" TYPE var2(spec2);\n"
|
||||
" TYPE var3; var3 = spec2;\n"
|
||||
" if((var1 == TYPE(" + std::to_string(m_test_value) +")) "
|
||||
"&& (var2 == TYPE(" + std::to_string(m_test_value) +"))\n"
|
||||
"&& (var3 == TYPE(" + std::to_string(m_test_value) +")))\n"
|
||||
" {\n"
|
||||
" output[gid] = " + std::to_string(m_test_value) +";\n"
|
||||
" }\n"
|
||||
" else\n"
|
||||
" {\n"
|
||||
" output[gid] = gid;\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_set_spec_constant;
|
||||
cl_uint m_test_value;
|
||||
};
|
||||
|
||||
AUTO_TEST_CASE(test_spec_constants_initializing_variables)
|
||||
(cl_device_id device, cl_context context, cl_command_queue queue, int n_elems)
|
||||
{
|
||||
int error = CL_SUCCESS;
|
||||
int last_error = CL_SUCCESS;
|
||||
|
||||
const std::vector<bool> set_spec_const_options { true, false };
|
||||
for(auto option : set_spec_const_options)
|
||||
{
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var<cl_char>(option));
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var<cl_uchar>(option));
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var<cl_int>(option));
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var<cl_uint>(option));
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var<cl_long>(option));
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var<cl_ulong>(option));
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var<cl_float>(option));
|
||||
if(is_extension_available(device, "cl_khr_fp16"))
|
||||
{
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var<cl_half>(option));
|
||||
}
|
||||
if(is_extension_available(device, "cl_khr_fp64"))
|
||||
{
|
||||
RUN_SPEC_CONSTANTS_TEST_MACRO(spec_const_init_var<cl_double>(option));
|
||||
}
|
||||
}
|
||||
|
||||
if(error != CL_SUCCESS)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
#endif // TEST_CONFORMANCE_CLCPP_SPEC_CONSTANTS_TEST_SPEC_CONSTS_INIT_VARS_HPP
|
||||
Reference in New Issue
Block a user