| // |
| // 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 "testBase.h" |
| |
| |
| #include "harness/conversions.h" |
| #include "harness/typeWrappers.h" |
| #include "harness/testHarness.h" |
| |
| #include "structs.h" |
| |
| #include "defines.h" |
| |
| #include "type_replacer.h" |
| |
| |
| /* |
| test_step_type, |
| test_step_var, |
| test_step_typedef_type, |
| test_step_typedef_var, |
| */ |
| |
| |
| int test_step_internal(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, const char* pattern, |
| const char* testName) |
| { |
| int err; |
| int typeIdx, vecSizeIdx; |
| |
| char tempBuffer[2048]; |
| |
| clState* pClState = newClState(deviceID, context, queue); |
| bufferStruct* pBuffers = |
| newBufferStruct(BUFFER_SIZE, BUFFER_SIZE, pClState); |
| |
| if (pBuffers == NULL) |
| { |
| destroyClState(pClState); |
| vlog_error("%s : Could not create buffer\n", testName); |
| return -1; |
| } |
| |
| // detect whether profile of the device is embedded |
| char profile[1024] = ""; |
| err = clGetDeviceInfo(deviceID, CL_DEVICE_PROFILE, sizeof(profile), profile, |
| NULL); |
| if (err) |
| { |
| print_error(err, "clGetDeviceInfo for CL_DEVICE_PROFILE failed\n"); |
| return -1; |
| } |
| gIsEmbedded = NULL != strstr(profile, "EMBEDDED_PROFILE"); |
| |
| for (typeIdx = 0; types[typeIdx] != kNumExplicitTypes; ++typeIdx) |
| { |
| if (types[typeIdx] == kDouble) |
| { |
| // If we're testing doubles, we need to check for support first |
| if (!is_extension_available(deviceID, "cl_khr_fp64")) |
| { |
| log_info("Not testing doubles (unsupported on this device)\n"); |
| continue; |
| } |
| } |
| |
| if (types[typeIdx] == kLong || types[typeIdx] == kULong) |
| { |
| // If we're testing long/ulong, we need to check for embedded |
| // support |
| if (gIsEmbedded |
| && !is_extension_available(deviceID, "cles_khr_int64")) |
| { |
| log_info("Not testing longs (unsupported on this embedded " |
| "device)\n"); |
| continue; |
| } |
| } |
| |
| char srcBuffer[2048]; |
| |
| doSingleReplace(tempBuffer, 2048, pattern, ".EXTENSIONS.", |
| types[typeIdx] == kDouble |
| ? "#pragma OPENCL EXTENSION cl_khr_fp64 : enable" |
| : ""); |
| |
| for (vecSizeIdx = 0; vecSizeIdx < NUM_VECTOR_SIZES; ++vecSizeIdx) |
| { |
| doReplace(srcBuffer, 2048, tempBuffer, ".TYPE.", |
| g_arrTypeNames[typeIdx], ".NUM.", |
| g_arrVecSizeNames[vecSizeIdx]); |
| |
| if (srcBuffer[0] == '\0') |
| { |
| vlog_error("%s: failed to fill source buf for type %s%s\n", |
| testName, g_arrTypeNames[typeIdx], |
| g_arrVecSizeNames[vecSizeIdx]); |
| destroyBufferStruct(pBuffers, pClState); |
| destroyClState(pClState); |
| return -1; |
| } |
| |
| err = clStateMakeProgram(pClState, srcBuffer, testName); |
| if (err) |
| { |
| vlog_error("%s: Error compiling \"\n%s\n\"", testName, |
| srcBuffer); |
| destroyBufferStruct(pBuffers, pClState); |
| destroyClState(pClState); |
| return -1; |
| } |
| |
| err = pushArgs(pBuffers, pClState); |
| if (err != 0) |
| { |
| vlog_error("%s: failed to push args %s%s\n", testName, |
| g_arrTypeNames[typeIdx], |
| g_arrVecSizeNames[vecSizeIdx]); |
| destroyBufferStruct(pBuffers, pClState); |
| destroyClState(pClState); |
| return -1; |
| } |
| |
| // now we run the kernel |
| err = runKernel(pClState, 1024); |
| if (err != 0) |
| { |
| vlog_error("%s: runKernel fail (%ld threads) %s%s\n", testName, |
| pClState->m_numThreads, g_arrTypeNames[typeIdx], |
| g_arrVecSizeNames[vecSizeIdx]); |
| destroyBufferStruct(pBuffers, pClState); |
| destroyClState(pClState); |
| return -1; |
| } |
| |
| err = retrieveResults(pBuffers, pClState); |
| if (err != 0) |
| { |
| vlog_error("%s: failed to retrieve results %s%s\n", testName, |
| g_arrTypeNames[typeIdx], |
| g_arrVecSizeNames[vecSizeIdx]); |
| destroyBufferStruct(pBuffers, pClState); |
| destroyClState(pClState); |
| return -1; |
| } |
| |
| err = checkCorrectnessStep(pBuffers, pClState, |
| g_arrTypeSizes[typeIdx], |
| g_arrVecSizes[vecSizeIdx]); |
| |
| if (err != 0) |
| { |
| vlog_error("%s: incorrect results %s%s\n", testName, |
| g_arrTypeNames[typeIdx], |
| g_arrVecSizeNames[vecSizeIdx]); |
| vlog_error("%s: Source was \"\n%s\n\"", testName, srcBuffer); |
| destroyBufferStruct(pBuffers, pClState); |
| destroyClState(pClState); |
| return -1; |
| } |
| } |
| } |
| |
| destroyBufferStruct(pBuffers, pClState); |
| |
| destroyClState(pClState); |
| |
| |
| // vlog_error("%s : implementation incomplete : FAIL\n", testName); |
| return 0; // -1; // fails on account of not being written. |
| } |
| |
| static const char* patterns[] = { |
| ".EXTENSIONS.\n" |
| "__kernel void test_step_type(__global .TYPE..NUM. *source, __global int " |
| "*dest)\n" |
| "{\n" |
| " int tid = get_global_id(0);\n" |
| " dest[tid] = vec_step(.TYPE..NUM.);\n" |
| "\n" |
| "}\n", |
| |
| ".EXTENSIONS.\n" |
| "__kernel void test_step_var(__global .TYPE..NUM. *source, __global int " |
| "*dest)\n" |
| "{\n" |
| " int tid = get_global_id(0);\n" |
| " dest[tid] = vec_step(source[tid]);\n" |
| "\n" |
| "}\n", |
| |
| ".EXTENSIONS.\n" |
| " typedef .TYPE..NUM. TypeToTest;\n" |
| "__kernel void test_step_typedef_type(__global TypeToTest *source, " |
| "__global int *dest)\n" |
| "{\n" |
| " int tid = get_global_id(0);\n" |
| " dest[tid] = vec_step(TypeToTest);\n" |
| "\n" |
| "}\n", |
| |
| ".EXTENSIONS.\n" |
| " typedef .TYPE..NUM. TypeToTest;\n" |
| "__kernel void test_step_typedef_var(__global TypeToTest *source, __global " |
| "int *dest)\n" |
| "{\n" |
| " int tid = get_global_id(0);\n" |
| " dest[tid] = vec_step(source[tid]);\n" |
| "\n" |
| "}\n", |
| }; |
| |
| /* |
| test_step_type, |
| test_step_var, |
| test_step_typedef_type, |
| test_step_typedef_var, |
| */ |
| |
| int test_step_type(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| return test_step_internal(deviceID, context, queue, patterns[0], |
| "test_step_type"); |
| } |
| |
| int test_step_var(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| return test_step_internal(deviceID, context, queue, patterns[1], |
| "test_step_var"); |
| } |
| |
| int test_step_typedef_type(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| return test_step_internal(deviceID, context, queue, patterns[2], |
| "test_step_typedef_type"); |
| } |
| |
| int test_step_typedef_var(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| return test_step_internal(deviceID, context, queue, patterns[3], |
| "test_step_typedef_var"); |
| } |