blob: 1c7cec2abb35898686ec896b44589fd6a829e609 [file] [log] [blame]
//
// 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