| // |
| // Copyright (c) 2020 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/testHarness.h" |
| #include "harness/deviceInfo.h" |
| |
| static const char* test_kernel = R"CLC( |
| __kernel void test(__global int* dst) { |
| dst[0] = 0; |
| } |
| )CLC"; |
| |
| int test_consistency_svm(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| // clGetDeviceInfo, passing CL_DEVICE_SVM_CAPABILITIES: |
| // May return 0, indicating that device does not support Shared Virtual |
| // Memory. |
| cl_int error; |
| |
| const size_t allocSize = 16; |
| clMemWrapper mem; |
| clProgramWrapper program; |
| clKernelWrapper kernel; |
| |
| cl_device_svm_capabilities svmCaps = 0; |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_SVM_CAPABILITIES, |
| sizeof(svmCaps), &svmCaps, NULL); |
| test_error(error, "Unable to query CL_DEVICE_SVM_CAPABILITIES"); |
| |
| if (svmCaps == 0) |
| { |
| // Test setup: |
| |
| mem = |
| clCreateBuffer(context, CL_MEM_READ_WRITE, allocSize, NULL, &error); |
| test_error(error, "Unable to create test buffer"); |
| |
| error = create_single_kernel_helper(context, &program, &kernel, 1, |
| &test_kernel, "test"); |
| test_error(error, "Unable to create test kernel"); |
| |
| // clGetMemObjectInfo, passing CL_MEM_USES_SVM_POINTER |
| // Returns CL_FALSE if no devices in the context associated with |
| // memobj support Shared Virtual Memory. |
| cl_bool usesSVMPointer; |
| error = |
| clGetMemObjectInfo(mem, CL_MEM_USES_SVM_POINTER, |
| sizeof(usesSVMPointer), &usesSVMPointer, NULL); |
| test_error(error, "Unable to query CL_MEM_USES_SVM_POINTER"); |
| test_assert_error(usesSVMPointer == CL_FALSE, |
| "CL_DEVICE_SVM_CAPABILITIES returned 0 but " |
| "CL_MEM_USES_SVM_POINTER did not return CL_FALSE"); |
| |
| // Check that the SVM APIs can be called. |
| |
| // Returns NULL if no devices in context support Shared Virtual Memory. |
| void* ptr0 = clSVMAlloc(context, CL_MEM_READ_WRITE, allocSize, 0); |
| void* ptr1 = clSVMAlloc(context, CL_MEM_READ_WRITE, allocSize, 0); |
| test_assert_error(ptr0 == NULL && ptr1 == NULL, |
| "CL_DEVICE_SVM_CAPABILITIES returned 0 but " |
| "clSVMAlloc returned a non-NULL value"); |
| |
| // clEnqueueSVMFree, clEnqueueSVMMemcpy, clEnqueueSVMMemFill, |
| // clEnqueueSVMMap, clEnqueueSVMUnmap, clEnqueueSVMMigrateMem Returns |
| // CL_INVALID_OPERATION if the device associated with command_queue does |
| // not support Shared Virtual Memory. |
| |
| // These calls purposefully pass bogus pointers to the functions to |
| // better test that they are a NOP when SVM is not supported. |
| void* bogus0 = (void*)0xDEADBEEF; |
| void* bogus1 = (void*)0xDEADDEAD; |
| cl_uint pattern = 0xAAAAAAAA; |
| error = clEnqueueSVMMemFill(queue, bogus0, &pattern, sizeof(pattern), |
| allocSize, 0, NULL, NULL); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "CL_DEVICE_SVM_CAPABILITIES returned 0 but clEnqueueSVMMemFill did " |
| "not return CL_INVALID_OPERATION"); |
| |
| error = clEnqueueSVMMemcpy(queue, CL_TRUE, bogus1, bogus0, allocSize, 0, |
| NULL, NULL); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "CL_DEVICE_SVM_CAPABILITIES returned 0 but " |
| "clEnqueueSVMMemcpy did not return CL_INVALID_OPERATION"); |
| |
| error = clEnqueueSVMMap(queue, CL_TRUE, CL_MAP_READ, bogus1, allocSize, |
| 0, NULL, NULL); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "CL_DEVICE_SVM_CAPABILITIES returned 0 but " |
| "clEnqueueSVMMap did not return CL_INVALID_OPERATION"); |
| |
| error = clEnqueueSVMUnmap(queue, bogus1, 0, NULL, NULL); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "CL_DEVICE_SVM_CAPABILITIES returned 0 but " |
| "clEnqueueSVMUnmap did not return CL_INVALID_OPERATION"); |
| |
| error = clEnqueueSVMMigrateMem(queue, 1, (const void**)&bogus1, NULL, 0, |
| 0, NULL, NULL); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "CL_DEVICE_SVM_CAPABILITIES returned 0 but " |
| "clEnqueueSVMMigrateMem did not return CL_INVALID_OPERATION"); |
| |
| // If the enqueue calls above did not return errors, a clFinish would be |
| // needed here to ensure the SVM operations are complete before freeing |
| // the SVM pointers. |
| |
| clSVMFree(context, bogus0); |
| error = clEnqueueSVMFree(queue, 1, &bogus0, NULL, NULL, 0, NULL, NULL); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "CL_DEVICE_SVM_CAPABILITIES returned 0 but " |
| "clEnqueueSVMFree did not return CL_INVALID_OPERATION"); |
| |
| // If the enqueue calls above did not return errors, a clFinish should |
| // be included here to ensure the enqueued SVM free is complete. |
| |
| // clSetKernelArgSVMPointer, clSetKernelExecInfo |
| // Returns CL_INVALID_OPERATION if no devices in the context associated |
| // with kernel support Shared Virtual Memory. |
| |
| error = clSetKernelArgSVMPointer(kernel, 0, NULL); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "CL_DEVICE_SVM_CAPABILITIES returned 0 but " |
| "clSetKernelArgSVMPointer did not return CL_INVALID_OPERATION"); |
| |
| error = |
| clSetKernelExecInfo(kernel, CL_KERNEL_EXEC_INFO_SVM_PTRS, 0, NULL); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "CL_DEVICE_SVM_CAPABILITIES returned 0 but " |
| "clSetKernelExecInfo did not return CL_INVALID_OPERATION"); |
| } |
| |
| return TEST_PASS; |
| } |
| |
| static int check_atomic_capabilities(cl_device_atomic_capabilities atomicCaps, |
| cl_device_atomic_capabilities requiredCaps) |
| { |
| if ((atomicCaps & requiredCaps) != requiredCaps) |
| { |
| log_error("Atomic capabilities %llx is missing support for at least " |
| "one required capability %llx!\n", |
| atomicCaps, requiredCaps); |
| return TEST_FAIL; |
| } |
| |
| if ((atomicCaps & CL_DEVICE_ATOMIC_SCOPE_ALL_DEVICES) != 0 |
| && (atomicCaps & CL_DEVICE_ATOMIC_SCOPE_DEVICE) == 0) |
| { |
| log_error("Support for CL_DEVICE_ATOMIC_SCOPE_ALL_DEVICES requires " |
| "support for CL_DEVICE_ATOMIC_SCOPE_DEVICE!\n"); |
| return TEST_FAIL; |
| } |
| |
| if ((atomicCaps & CL_DEVICE_ATOMIC_SCOPE_DEVICE) != 0 |
| && (atomicCaps & CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP) == 0) |
| { |
| log_error("Support for CL_DEVICE_ATOMIC_SCOPE_DEVICE requires " |
| "support for CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP!\n"); |
| return TEST_FAIL; |
| } |
| |
| if ((atomicCaps & CL_DEVICE_ATOMIC_ORDER_SEQ_CST) != 0 |
| && (atomicCaps & CL_DEVICE_ATOMIC_ORDER_ACQ_REL) == 0) |
| { |
| log_error("Support for CL_DEVICE_ATOMIC_ORDER_SEQ_CST requires " |
| "support for CL_DEVICE_ATOMIC_ORDER_ACQ_REL!\n"); |
| return TEST_FAIL; |
| } |
| |
| if ((atomicCaps & CL_DEVICE_ATOMIC_ORDER_ACQ_REL) != 0 |
| && (atomicCaps & CL_DEVICE_ATOMIC_ORDER_RELAXED) == 0) |
| { |
| log_error("Support for CL_DEVICE_ATOMIC_ORDER_ACQ_REL requires " |
| "support for CL_DEVICE_ATOMIC_ORDER_RELAXED!\n"); |
| return TEST_FAIL; |
| } |
| |
| return TEST_PASS; |
| } |
| |
| int test_consistency_memory_model(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| cl_int error; |
| cl_device_atomic_capabilities atomicCaps = 0; |
| |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES, |
| sizeof(atomicCaps), &atomicCaps, NULL); |
| test_error(error, "Unable to query CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES"); |
| |
| error = check_atomic_capabilities(atomicCaps, |
| CL_DEVICE_ATOMIC_ORDER_RELAXED |
| | CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP); |
| if (error == TEST_FAIL) |
| { |
| log_error("Checks failed for CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES\n"); |
| return error; |
| } |
| |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_ATOMIC_FENCE_CAPABILITIES, |
| sizeof(atomicCaps), &atomicCaps, NULL); |
| test_error(error, "Unable to query CL_DEVICE_ATOMIC_FENCE_CAPABILITIES"); |
| |
| error = check_atomic_capabilities(atomicCaps, |
| CL_DEVICE_ATOMIC_ORDER_RELAXED |
| | CL_DEVICE_ATOMIC_ORDER_ACQ_REL |
| | CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP); |
| if (error == TEST_FAIL) |
| { |
| log_error("Checks failed for CL_DEVICE_ATOMIC_FENCE_CAPABILITIES\n"); |
| return error; |
| } |
| |
| return TEST_PASS; |
| } |
| |
| int test_consistency_device_enqueue(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| // clGetDeviceInfo, passing CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES |
| // May return 0, indicating that device does not support Device-Side Enqueue |
| // and On-Device Queues. |
| cl_int error; |
| |
| cl_device_device_enqueue_capabilities dseCaps = 0; |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES, |
| sizeof(dseCaps), &dseCaps, NULL); |
| test_error(error, "Unable to query CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES"); |
| |
| if (dseCaps == 0) |
| { |
| // clGetDeviceInfo, passing CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES |
| // Returns 0 if device does not support Device-Side Enqueue and |
| // On-Device Queues. |
| |
| cl_command_queue_properties devQueueProps = 0; |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES, |
| sizeof(devQueueProps), &devQueueProps, NULL); |
| test_error(error, |
| "Unable to query CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES"); |
| test_assert_error( |
| devQueueProps == 0, |
| "CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES returned 0 but " |
| "CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES returned a non-zero value"); |
| |
| // clGetDeviceInfo, passing |
| // CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE, |
| // CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, |
| // CL_DEVICE_MAX_ON_DEVICE_QUEUES, or |
| // CL_DEVICE_MAX_ON_DEVICE_EVENTS |
| // Returns 0 if device does not support Device-Side Enqueue and |
| // On-Device Queues. |
| |
| cl_uint u = 0; |
| |
| error = |
| clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE, |
| sizeof(u), &u, NULL); |
| test_error(error, |
| "Unable to query CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE"); |
| test_assert_error(u == 0, |
| "CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES returned 0 " |
| "but CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE " |
| "returned a non-zero value"); |
| |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE, |
| sizeof(u), &u, NULL); |
| test_error(error, "Unable to query CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE"); |
| test_assert_error( |
| u == 0, |
| "CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES returned 0 but " |
| "CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE returned a non-zero value"); |
| |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_ON_DEVICE_QUEUES, |
| sizeof(u), &u, NULL); |
| test_error(error, "Unable to query CL_DEVICE_MAX_ON_DEVICE_QUEUES"); |
| test_assert_error( |
| u == 0, |
| "CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES returned 0 but " |
| "CL_DEVICE_MAX_ON_DEVICE_QUEUES returned a non-zero value"); |
| |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_ON_DEVICE_EVENTS, |
| sizeof(u), &u, NULL); |
| test_error(error, "Unable to query CL_DEVICE_MAX_ON_DEVICE_EVENTS"); |
| test_assert_error( |
| u == 0, |
| "CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES returned 0 but " |
| "CL_DEVICE_MAX_ON_DEVICE_EVENTS returned a non-zero value"); |
| |
| // clGetCommandQueueInfo, passing CL_QUEUE_SIZE |
| // Returns CL_INVALID_COMMAND_QUEUE since command_queue cannot be a |
| // valid device command-queue. |
| |
| error = |
| clGetCommandQueueInfo(queue, CL_QUEUE_SIZE, sizeof(u), &u, NULL); |
| test_failure_error( |
| error, CL_INVALID_COMMAND_QUEUE, |
| "CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES returned 0 but " |
| "CL_QUEUE_SIZE did not return CL_INVALID_COMMAND_QUEUE"); |
| |
| cl_command_queue q = NULL; |
| error = clGetCommandQueueInfo(queue, CL_QUEUE_DEVICE_DEFAULT, sizeof(q), |
| &q, NULL); |
| test_error(error, "Unable to query CL_QUEUE_DEVICE_DEFAULT"); |
| test_assert_error( |
| q == NULL, |
| "CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES returned 0 but " |
| "CL_QUEUE_DEVICE_DEFAULT returned a non-NULL value"); |
| |
| // clSetDefaultDeviceCommandQueue |
| // Returns CL_INVALID_OPERATION if device does not support On-Device |
| // Queues. |
| error = clSetDefaultDeviceCommandQueue(context, deviceID, NULL); |
| test_failure_error(error, CL_INVALID_OPERATION, |
| "CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES returned 0 " |
| "but clSetDefaultDeviceCommandQueue did not return " |
| "CL_INVALID_OPERATION"); |
| } |
| else |
| { |
| if ((dseCaps & CL_DEVICE_QUEUE_REPLACEABLE_DEFAULT) == 0) |
| { |
| // clSetDefaultDeviceCommandQueue |
| // Returns CL_INVALID_OPERATION if device does not support a |
| // replaceable default On-Device Queue. |
| error = clSetDefaultDeviceCommandQueue(context, deviceID, NULL); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES did not " |
| "include CL_DEVICE_QUEUE_REPLACEABLE_DEFAULT but " |
| "clSetDefaultDeviceCommandQueue did not return " |
| "CL_INVALID_OPERATION"); |
| } |
| |
| // If CL_DEVICE_QUEUE_REPLACEABLE_DEFAULT is set, |
| // CL_DEVICE_QUEUE_SUPPORTED must also be set. |
| if ((dseCaps & CL_DEVICE_QUEUE_REPLACEABLE_DEFAULT) != 0 |
| && (dseCaps & CL_DEVICE_QUEUE_SUPPORTED) == 0) |
| { |
| log_error("DEVICE_QUEUE_REPLACEABLE_DEFAULT is set but " |
| "DEVICE_QUEUE_SUPPORTED is not set\n"); |
| return TEST_FAIL; |
| } |
| |
| // Devices that set CL_DEVICE_QUEUE_SUPPORTED must also return CL_TRUE |
| // for CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT. |
| if ((dseCaps & CL_DEVICE_QUEUE_SUPPORTED) != 0) |
| { |
| cl_bool b; |
| error = clGetDeviceInfo(deviceID, |
| CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT, |
| sizeof(b), &b, NULL); |
| test_error( |
| error, |
| "Unable to query CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT"); |
| test_assert_error( |
| b == CL_TRUE, |
| "DEVICE_QUEUE_SUPPORTED is set but " |
| "CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT returned CL_FALSE"); |
| } |
| } |
| |
| return TEST_PASS; |
| } |
| |
| int test_consistency_pipes(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| // clGetDeviceInfo, passing CL_DEVICE_PIPE_SUPPORT |
| // May return CL_FALSE, indicating that device does not support Pipes. |
| cl_int error; |
| |
| cl_bool pipeSupport = CL_FALSE; |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_PIPE_SUPPORT, |
| sizeof(pipeSupport), &pipeSupport, NULL); |
| test_error(error, "Unable to query CL_DEVICE_PIPE_SUPPORT"); |
| |
| if (pipeSupport == CL_FALSE) |
| { |
| // clGetDeviceInfo, passing |
| // CL_DEVICE_MAX_PIPE_ARGS, |
| // CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS, or |
| // CL_DEVICE_PIPE_MAX_PACKET_SIZE |
| // Returns 0 if device does not support Pipes. |
| |
| cl_uint u = 0; |
| |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_PIPE_ARGS, sizeof(u), |
| &u, NULL); |
| test_error(error, "Unable to query CL_DEVICE_MAX_PIPE_ARGS"); |
| test_assert_error(u == 0, |
| "CL_DEVICE_PIPE_SUPPORT returned CL_FALSE, but " |
| "CL_DEVICE_MAX_PIPE_ARGS returned a non-zero value"); |
| |
| error = |
| clGetDeviceInfo(deviceID, CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS, |
| sizeof(u), &u, NULL); |
| test_error(error, |
| "Unable to query CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS"); |
| test_assert_error(u == 0, |
| "CL_DEVICE_PIPE_SUPPORT returned CL_FALSE, but " |
| "CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS returned " |
| "a non-zero value"); |
| |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_PIPE_MAX_PACKET_SIZE, |
| sizeof(u), &u, NULL); |
| test_error(error, "Unable to query CL_DEVICE_PIPE_MAX_PACKET_SIZE"); |
| test_assert_error( |
| u == 0, |
| "CL_DEVICE_PIPE_SUPPORT returned CL_FALSE, but " |
| "CL_DEVICE_PIPE_MAX_PACKET_SIZE returned a non-zero value"); |
| |
| // clCreatePipe |
| // Returns CL_INVALID_OPERATION if no devices in context support Pipes. |
| clMemWrapper mem = |
| clCreatePipe(context, CL_MEM_HOST_NO_ACCESS, 4, 4, NULL, &error); |
| test_failure_error(error, CL_INVALID_OPERATION, |
| "CL_DEVICE_PIPE_SUPPORT returned CL_FALSE but " |
| "clCreatePipe did not return CL_INVALID_OPERATION"); |
| |
| // clGetPipeInfo |
| // Returns CL_INVALID_MEM_OBJECT since pipe cannot be a valid pipe |
| // object. |
| clMemWrapper not_a_pipe = |
| clCreateBuffer(context, CL_MEM_READ_WRITE, 4, NULL, &error); |
| test_error(error, "Unable to create non-pipe buffer"); |
| |
| error = |
| clGetPipeInfo(not_a_pipe, CL_PIPE_PACKET_SIZE, sizeof(u), &u, NULL); |
| test_failure_error( |
| error, CL_INVALID_MEM_OBJECT, |
| "CL_DEVICE_PIPE_SUPPORT returned CL_FALSE but clGetPipeInfo did " |
| "not return CL_INVALID_MEM_OBJECT"); |
| } |
| else |
| { |
| // Devices that support pipes must also return CL_TRUE |
| // for CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT. |
| cl_bool b; |
| error = |
| clGetDeviceInfo(deviceID, CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT, |
| sizeof(b), &b, NULL); |
| test_error(error, |
| "Unable to query CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT"); |
| test_assert_error( |
| b == CL_TRUE, |
| "CL_DEVICE_PIPE_SUPPORT returned CL_TRUE but " |
| "CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT returned CL_FALSE"); |
| } |
| |
| return TEST_PASS; |
| } |
| |
| int test_consistency_progvar(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| // clGetDeviceInfo, passing CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE |
| // May return 0, indicating that device does not support Program Scope |
| // Global Variables. |
| cl_int error; |
| |
| clProgramWrapper program; |
| clKernelWrapper kernel; |
| |
| size_t maxGlobalVariableSize = 0; |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE, |
| sizeof(maxGlobalVariableSize), |
| &maxGlobalVariableSize, NULL); |
| test_error(error, "Unable to query CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE"); |
| |
| if (maxGlobalVariableSize == 0) |
| { |
| // Test setup: |
| |
| error = create_single_kernel_helper(context, &program, &kernel, 1, |
| &test_kernel, "test"); |
| test_error(error, "Unable to create test kernel"); |
| |
| size_t sz = SIZE_MAX; |
| |
| // clGetDeviceInfo, passing |
| // CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE |
| // Returns 0 if device does not support Program Scope Global Variables. |
| |
| error = clGetDeviceInfo(deviceID, |
| CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE, |
| sizeof(sz), &sz, NULL); |
| test_error( |
| error, |
| "Unable to query CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE"); |
| test_assert_error( |
| sz == 0, |
| "CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE returned 0 but " |
| "CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE returned a " |
| "non-zero value"); |
| |
| // clGetProgramBuildInfo, passing |
| // CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE |
| // Returns 0 if device does not support Program Scope Global Variables. |
| |
| error = clGetProgramBuildInfo( |
| program, deviceID, CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE, |
| sizeof(sz), &sz, NULL); |
| test_error( |
| error, |
| "Unable to query CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE"); |
| test_assert_error(sz == 0, |
| "CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE returned 0 " |
| "but CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE " |
| "returned a non-zero value"); |
| } |
| |
| return TEST_PASS; |
| } |
| |
| int test_consistency_non_uniform_work_group(cl_device_id deviceID, |
| cl_context context, |
| cl_command_queue queue, |
| int num_elements) |
| { |
| // clGetDeviceInfo, passing CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT: |
| // May return CL_FALSE, indicating that device does not support Non-Uniform |
| // Work Groups. |
| cl_int error; |
| |
| const size_t allocSize = 16; |
| clMemWrapper mem; |
| clProgramWrapper program; |
| clKernelWrapper kernel; |
| |
| cl_bool nonUniformWorkGroupSupport = CL_FALSE; |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT, |
| sizeof(nonUniformWorkGroupSupport), |
| &nonUniformWorkGroupSupport, NULL); |
| test_error(error, |
| "Unable to query CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT"); |
| |
| if (nonUniformWorkGroupSupport == CL_FALSE) |
| { |
| // Test setup: |
| |
| mem = |
| clCreateBuffer(context, CL_MEM_READ_WRITE, allocSize, NULL, &error); |
| test_error(error, "Unable to create test buffer"); |
| |
| error = create_single_kernel_helper(context, &program, &kernel, 1, |
| &test_kernel, "test"); |
| test_error(error, "Unable to create test kernel"); |
| |
| error = clSetKernelArg(kernel, 0, sizeof(mem), &mem); |
| |
| // clEnqueueNDRangeKernel |
| // Behaves as though Non-Uniform Work Groups were not enabled for |
| // kernel, if the device associated with command_queue does not support |
| // Non-Uniform Work Groups. |
| |
| size_t global_work_size[] = { 3, 3, 3 }; |
| size_t local_work_size[] = { 2, 2, 2 }; |
| |
| // First, check that a NULL local work size succeeds. |
| error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global_work_size, |
| NULL, 0, NULL, NULL); |
| test_error(error, |
| "Unable to enqueue kernel with a NULL local work size"); |
| |
| error = clFinish(queue); |
| test_error(error, "Error calling clFinish after NULL local work size"); |
| |
| // 1D non-uniform work group: |
| error = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, global_work_size, |
| local_work_size, 0, NULL, NULL); |
| test_failure_error( |
| error, CL_INVALID_WORK_GROUP_SIZE, |
| "CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT returned CL_FALSE but 1D " |
| "clEnqueueNDRangeKernel did not return CL_INVALID_WORK_GROUP_SIZE"); |
| |
| // 2D non-uniform work group: |
| global_work_size[0] = local_work_size[0]; |
| error = clEnqueueNDRangeKernel(queue, kernel, 2, NULL, global_work_size, |
| local_work_size, 0, NULL, NULL); |
| test_failure_error( |
| error, CL_INVALID_WORK_GROUP_SIZE, |
| "CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT returned CL_FALSE but 2D " |
| "clEnqueueNDRangeKernel did not return CL_INVALID_WORK_GROUP_SIZE"); |
| |
| // 3D non-uniform work group: |
| global_work_size[1] = local_work_size[1]; |
| error = clEnqueueNDRangeKernel(queue, kernel, 3, NULL, global_work_size, |
| local_work_size, 0, NULL, NULL); |
| test_failure_error( |
| error, CL_INVALID_WORK_GROUP_SIZE, |
| "CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT returned CL_FALSE but 3D " |
| "clEnqueueNDRangeKernel did not return CL_INVALID_WORK_GROUP_SIZE"); |
| } |
| |
| return TEST_PASS; |
| } |
| |
| int test_consistency_read_write_images(cl_device_id deviceID, |
| cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| // clGetDeviceInfo, passing |
| // CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS May return 0, |
| // indicating that device does not support Read-Write Images. |
| cl_int error; |
| |
| cl_uint maxReadWriteImageArgs = 0; |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS, |
| sizeof(maxReadWriteImageArgs), |
| &maxReadWriteImageArgs, NULL); |
| test_error(error, |
| "Unable to query " |
| "CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS"); |
| |
| // clGetSupportedImageFormats, passing |
| // CL_MEM_KERNEL_READ_AND_WRITE |
| // Returns an empty set (such as num_image_formats equal to 0), indicating |
| // that no image formats are supported for reading and writing in the same |
| // kernel, if no devices in context support Read-Write Images. |
| |
| cl_uint totalReadWriteImageFormats = 0; |
| |
| const cl_mem_object_type image_types[] = { |
| CL_MEM_OBJECT_IMAGE1D, CL_MEM_OBJECT_IMAGE1D_BUFFER, |
| CL_MEM_OBJECT_IMAGE2D, CL_MEM_OBJECT_IMAGE3D, |
| CL_MEM_OBJECT_IMAGE1D_ARRAY, CL_MEM_OBJECT_IMAGE2D_ARRAY, |
| }; |
| for (int i = 0; i < ARRAY_SIZE(image_types); i++) |
| { |
| cl_uint numImageFormats = 0; |
| error = clGetSupportedImageFormats( |
| context, CL_MEM_KERNEL_READ_AND_WRITE, image_types[i], 0, NULL, |
| &numImageFormats); |
| test_error(error, |
| "Unable to query number of CL_MEM_KERNEL_READ_AND_WRITE " |
| "image formats"); |
| |
| totalReadWriteImageFormats += numImageFormats; |
| } |
| |
| if (maxReadWriteImageArgs == 0) |
| { |
| test_assert_error( |
| totalReadWriteImageFormats == 0, |
| "CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS returned 0 " |
| "but clGetSupportedImageFormats(CL_MEM_KERNEL_READ_AND_WRITE) " |
| "returned a non-empty set"); |
| } |
| else |
| { |
| test_assert_error( |
| totalReadWriteImageFormats != 0, |
| "CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS is non-zero " |
| "but clGetSupportedImageFormats(CL_MEM_KERNEL_READ_AND_WRITE) " |
| "returned an empty set"); |
| } |
| |
| return TEST_PASS; |
| } |
| |
| int test_consistency_2d_image_from_buffer(cl_device_id deviceID, |
| cl_context context, |
| cl_command_queue queue, |
| int num_elements) |
| { |
| // clGetDeviceInfo, passing CL_DEVICE_IMAGE_PITCH_ALIGNMENT or |
| // CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT |
| // May return 0, indicating that device does not support Creating a 2D Image |
| // from a Buffer. |
| cl_int error; |
| |
| const cl_image_format imageFormat = { CL_RGBA, CL_UNORM_INT8 }; |
| const size_t imageDim = 2; |
| const size_t elementSize = 4; |
| const size_t bufferSize = imageDim * imageDim * elementSize; |
| |
| clMemWrapper buffer; |
| clMemWrapper image; |
| |
| cl_uint imagePitchAlignment = 0; |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE_PITCH_ALIGNMENT, |
| sizeof(imagePitchAlignment), &imagePitchAlignment, |
| NULL); |
| test_error(error, |
| "Unable to query " |
| "CL_DEVICE_IMAGE_PITCH_ALIGNMENT"); |
| |
| cl_uint imageBaseAddressAlignment = 0; |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT, |
| sizeof(imageBaseAddressAlignment), |
| &imageBaseAddressAlignment, NULL); |
| test_error(error, |
| "Unable to query " |
| "CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT"); |
| |
| bool supports_cl_khr_image2d_from_buffer = |
| is_extension_available(deviceID, "cl_khr_image2d_from_buffer"); |
| |
| if (imagePitchAlignment == 0 || imageBaseAddressAlignment == 0) |
| { |
| // This probably means that Creating a 2D Image from a Buffer is not |
| // supported. |
| |
| // Test setup: |
| buffer = |
| clCreateBuffer(context, CL_MEM_READ_ONLY, bufferSize, NULL, &error); |
| test_error(error, "Unable to create test buffer"); |
| |
| // Check that both queries return zero: |
| test_assert_error( |
| imagePitchAlignment == 0, |
| "CL_DEVICE_IMAGE_PITCH_ALIGNMENT returned a non-zero value but " |
| "CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT returned 0"); |
| test_assert_error( |
| imageBaseAddressAlignment == 0, |
| "CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT returned a non-zero value " |
| "but CL_DEVICE_IMAGE_PITCH_ALIGNMENT returned 0"); |
| |
| // clGetDeviceInfo, passing CL_DEVICE_EXTENSIONS |
| // Will not describe support for the cl_khr_image2d_from_buffer |
| // extension if device does not support Creating a 2D Image from a |
| // Buffer. |
| test_assert_error(supports_cl_khr_image2d_from_buffer == false, |
| "Device does not support Creating a 2D Image from a " |
| "Buffer but does support cl_khr_image2d_from_buffer"); |
| |
| // clCreateImage or clCreateImageWithProperties, passing image_type |
| // equal to CL_MEM_OBJECT_IMAGE2D and mem_object not equal to |
| // NULL |
| // Returns CL_INVALID_OPERATION if no devices in context support |
| // Creating a 2D Image from a Buffer. |
| |
| cl_image_desc imageDesc = { 0 }; |
| imageDesc.image_type = CL_MEM_OBJECT_IMAGE2D; |
| imageDesc.image_width = imageDim; |
| imageDesc.image_height = imageDim; |
| imageDesc.mem_object = buffer; |
| |
| image = clCreateImage(context, CL_MEM_READ_ONLY, &imageFormat, |
| &imageDesc, NULL, &error); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "Device does not support Creating a 2D Image from a " |
| "Buffer but clCreateImage did not return CL_INVALID_OPERATION"); |
| |
| image = |
| clCreateImageWithProperties(context, NULL, CL_MEM_READ_ONLY, |
| &imageFormat, &imageDesc, NULL, &error); |
| test_failure_error(error, CL_INVALID_OPERATION, |
| "Device does not support Creating a 2D Image from a " |
| "Buffer but clCreateImageWithProperties did not " |
| "return CL_INVALID_OPERATION"); |
| } |
| else |
| { |
| test_assert_error(supports_cl_khr_image2d_from_buffer, |
| "Device supports Creating a 2D Image from a Buffer " |
| "but does not support cl_khr_image2d_from_buffer"); |
| } |
| |
| return TEST_PASS; |
| } |
| |
| // Nothing needed for sRGB Images: |
| // All of the sRGB Image Channel Orders (such as CL_​sRGBA) are optional for |
| // devices supporting OpenCL 3.0. |
| |
| int test_consistency_depth_images(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| // The CL_DEPTH Image Channel Order is optional for devices supporting |
| // OpenCL 3.0. |
| cl_int error; |
| |
| cl_uint totalDepthImageFormats = 0; |
| |
| const cl_mem_flags mem_flags[] = { |
| CL_MEM_WRITE_ONLY, |
| CL_MEM_READ_WRITE, |
| CL_MEM_KERNEL_READ_AND_WRITE, |
| }; |
| for (int i = 0; i < ARRAY_SIZE(mem_flags); i++) |
| { |
| cl_uint numImageFormats = 0; |
| error = clGetSupportedImageFormats(context, mem_flags[i], |
| CL_MEM_OBJECT_IMAGE2D, 0, NULL, |
| &numImageFormats); |
| test_error( |
| error, |
| "Unable to query number of CL_MEM_OBJECT_IMAGE2D image formats"); |
| |
| std::vector<cl_image_format> imageFormats(numImageFormats); |
| error = clGetSupportedImageFormats( |
| context, mem_flags[i], CL_MEM_OBJECT_IMAGE2D, imageFormats.size(), |
| imageFormats.data(), NULL); |
| test_error(error, |
| "Unable to query CL_MEM_OBJECT_IMAGE2D image formats"); |
| for (auto& imageFormat : imageFormats) |
| { |
| if (imageFormat.image_channel_order == CL_DEPTH) |
| { |
| totalDepthImageFormats++; |
| } |
| } |
| } |
| |
| bool supports_cl_khr_depth_images = |
| is_extension_available(deviceID, "cl_khr_depth_images"); |
| |
| if (totalDepthImageFormats == 0) |
| { |
| test_assert_error(supports_cl_khr_depth_images == false, |
| "Device does not support Depth Images but does " |
| "support cl_khr_depth_images"); |
| } |
| else |
| { |
| test_assert_error(supports_cl_khr_depth_images, |
| "Device supports Depth Images but does not support " |
| "cl_khr_depth_images"); |
| } |
| |
| return TEST_PASS; |
| } |
| |
| int test_consistency_device_and_host_timer(cl_device_id deviceID, |
| cl_context context, |
| cl_command_queue queue, |
| int num_elements) |
| { |
| // clGetPlatformInfo, passing CL_PLATFORM_HOST_TIMER_RESOLUTION |
| // May return 0, indicating that platform does not support Device and Host |
| // Timer Synchronization. |
| cl_int error; |
| |
| cl_platform_id platform = NULL; |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_PLATFORM, sizeof(platform), |
| &platform, NULL); |
| test_error(error, "Unable to query CL_DEVICE_PLATFORM"); |
| |
| cl_ulong hostTimerResolution = 0; |
| error = clGetPlatformInfo(platform, CL_PLATFORM_HOST_TIMER_RESOLUTION, |
| sizeof(hostTimerResolution), &hostTimerResolution, |
| NULL); |
| test_error(error, "Unable to query CL_PLATFORM_HOST_TIMER_RESOLUTION"); |
| |
| if (hostTimerResolution == 0) |
| { |
| // clGetDeviceAndHostTimer, clGetHostTimer |
| // Returns CL_INVALID_OPERATION if the platform associated with device |
| // does not support Device and Host Timer Synchronization. |
| |
| cl_ulong dt = 0; |
| cl_ulong ht = 0; |
| |
| error = clGetDeviceAndHostTimer(deviceID, &dt, &ht); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "CL_PLATFORM_HOST_TIMER_RESOLUTION returned 0 but " |
| "clGetDeviceAndHostTimer did not return CL_INVALID_OPERATION"); |
| |
| error = clGetHostTimer(deviceID, &ht); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "CL_PLATFORM_HOST_TIMER_RESOLUTION returned 0 but " |
| "clGetHostTimer did not return CL_INVALID_OPERATION"); |
| } |
| |
| return TEST_PASS; |
| } |
| |
| int test_consistency_il_programs(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| // clGetDeviceInfo, passing CL_DEVICE_IL_VERSION or |
| // CL_DEVICE_ILS_WITH_VERSION |
| // May return an empty string and empty array, indicating that device does |
| // not support Intermediate Language Programs. |
| cl_int error; |
| |
| clProgramWrapper program; |
| clKernelWrapper kernel; |
| |
| // Even if the device does not support Intermediate Language Programs the |
| // size of the string query should not be zero. |
| size_t sz = SIZE_MAX; |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_IL_VERSION, 0, NULL, &sz); |
| test_error(error, "Unable to query CL_DEVICE_IL_VERSION"); |
| test_assert_error(sz != 0, |
| "CL_DEVICE_IL_VERSION should return a non-zero size"); |
| |
| std::string ilVersion = get_device_il_version_string(deviceID); |
| |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_ILS_WITH_VERSION, 0, NULL, &sz); |
| test_error(error, "Unable to query CL_DEVICE_ILS_WITH_VERSION"); |
| |
| if (ilVersion == "" || sz == 0) |
| { |
| // This probably means that Intermediate Language Programs are not |
| // supported. |
| |
| // Check that both queries are consistent: |
| test_assert_error( |
| ilVersion == "", |
| "CL_DEVICE_IL_VERSION returned a non-empty string but " |
| "CL_DEVICE_ILS_WITH_VERSION returned no supported ILs"); |
| |
| test_assert_error(sz == 0, |
| "CL_DEVICE_ILS_WITH_VERSION returned supported ILs " |
| "but CL_DEVICE_IL_VERSION returned an empty string"); |
| |
| bool supports_cl_khr_il_program = |
| is_extension_available(deviceID, "cl_khr_il_program"); |
| test_assert_error(supports_cl_khr_il_program == false, |
| "Device does not support IL Programs but does " |
| "support cl_khr_il_program"); |
| |
| // Test setup: |
| |
| error = create_single_kernel_helper(context, &program, &kernel, 1, |
| &test_kernel, "test"); |
| test_error(error, "Unable to create test kernel"); |
| |
| // clGetProgramInfo, passing CL_PROGRAM_IL |
| // Returns an empty buffer (such as param_value_size_ret equal to 0) if |
| // no devices in the context associated with program support |
| // Intermediate Language Programs. |
| |
| error = clGetProgramInfo(program, CL_PROGRAM_IL, 0, NULL, &sz); |
| test_error(error, "Unable to query CL_PROGRAM_IL"); |
| test_assert_error(sz == 0, |
| "Device does not support IL Programs but " |
| "CL_PROGRAM_IL returned a non-zero size"); |
| |
| // clCreateProgramWithIL |
| // Returns CL_INVALID_OPERATION if no devices in context support |
| // Intermediate Language Programs. |
| |
| cl_uint bogus = 0xDEADBEEF; |
| clProgramWrapper ilProgram = |
| clCreateProgramWithIL(context, &bogus, sizeof(bogus), &error); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "Device does not support IL Programs but clCreateProgramWithIL did " |
| "not return CL_INVALID_OPERATION"); |
| |
| // clSetProgramSpecializationConstant |
| // Returns CL_INVALID_OPERATION if no devices associated with program |
| // support Intermediate Language Programs. |
| |
| cl_uint specConst = 42; |
| error = clSetProgramSpecializationConstant( |
| program, 0, sizeof(specConst), &specConst); |
| test_failure_error(error, CL_INVALID_OPERATION, |
| "Device does not support IL Programs but " |
| "clSetProgramSpecializationConstant did not return " |
| "CL_INVALID_OPERATION"); |
| } |
| |
| return TEST_PASS; |
| } |
| |
| int test_consistency_subgroups(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| // clGetDeviceInfo, passing CL_DEVICE_MAX_NUM_SUB_GROUPS |
| // May return 0, indicating that device does not support Subgroups. |
| cl_int error; |
| |
| clProgramWrapper program; |
| clKernelWrapper kernel; |
| |
| cl_uint maxNumSubGroups = 0; |
| error = clGetDeviceInfo(deviceID, CL_DEVICE_MAX_NUM_SUB_GROUPS, |
| sizeof(maxNumSubGroups), &maxNumSubGroups, NULL); |
| test_error(error, "Unable to query CL_DEVICE_MAX_NUM_SUB_GROUPS"); |
| |
| if (maxNumSubGroups == 0) |
| { |
| // Test setup: |
| |
| error = create_single_kernel_helper(context, &program, &kernel, 1, |
| &test_kernel, "test"); |
| test_error(error, "Unable to create test kernel"); |
| |
| // clGetDeviceInfo, passing |
| // CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS |
| // Returns CL_FALSE if device does not support Subgroups. |
| |
| cl_bool ifp = CL_FALSE; |
| error = clGetDeviceInfo( |
| deviceID, CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS, |
| sizeof(ifp), &ifp, NULL); |
| test_error( |
| error, |
| "Unable to query CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS"); |
| test_assert_error(ifp == CL_FALSE, |
| "Device does not support Subgroups but " |
| "CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS " |
| "did not return CL_FALSE"); |
| |
| // clGetDeviceInfo, passing CL_DEVICE_EXTENSIONS |
| // Will not describe support for the cl_khr_subgroups extension if |
| // device does not support Subgroups. |
| |
| bool supports_cl_khr_subgroups = |
| is_extension_available(deviceID, "cl_khr_subgroups"); |
| test_assert_error(supports_cl_khr_subgroups == false, |
| "Device does not support Subgroups but does " |
| "support cl_khr_subgroups"); |
| |
| // clGetKernelSubGroupInfo |
| // Returns CL_INVALID_OPERATION if device does not support Subgroups. |
| |
| size_t sz = SIZE_MAX; |
| error = clGetKernelSubGroupInfo(kernel, deviceID, |
| CL_KERNEL_MAX_NUM_SUB_GROUPS, 0, NULL, |
| sizeof(sz), &sz, NULL); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "Device does not support Subgroups but clGetKernelSubGroupInfo did " |
| "not return CL_INVALID_OPERATION"); |
| } |
| |
| return TEST_PASS; |
| } |
| |
| static void CL_CALLBACK program_callback(cl_program, void*) {} |
| |
| int test_consistency_prog_ctor_dtor(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| cl_int error; |
| |
| clProgramWrapper program; |
| clKernelWrapper kernel; |
| |
| // Test setup: |
| |
| error = create_single_kernel_helper(context, &program, &kernel, 1, |
| &test_kernel, "test"); |
| test_error(error, "Unable to create test kernel"); |
| |
| // clGetProgramInfo, passing CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT or |
| // CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT |
| // Returns CL_FALSE if no devices in the context associated with program |
| // support Program Initialization and Clean-Up Kernels. |
| |
| cl_bool b = CL_FALSE; |
| |
| error = clGetProgramInfo(program, CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT, |
| sizeof(b), &b, NULL); |
| test_error(error, "Unable to query CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT"); |
| test_assert_error( |
| b == CL_FALSE, |
| "CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT did not return CL_FALSE"); |
| |
| error = clGetProgramInfo(program, CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT, |
| sizeof(b), &b, NULL); |
| test_error(error, "Unable to query CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT"); |
| test_assert_error( |
| b == CL_FALSE, |
| "CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT did not return CL_FALSE"); |
| |
| // clSetProgramReleaseCallback |
| // Returns CL_INVALID_OPERATION if no devices in the context associated with |
| // program support Program Initialization and Clean-Up Kernels. |
| |
| error = clSetProgramReleaseCallback(program, program_callback, NULL); |
| test_failure_error( |
| error, CL_INVALID_OPERATION, |
| "clSetProgramReleaseCallback did not return CL_INVALID_OPERATION"); |
| |
| return TEST_PASS; |
| } |
| |
| int test_consistency_3d_image_writes(cl_device_id deviceID, cl_context context, |
| cl_command_queue queue, int num_elements) |
| { |
| // clGetSupportedImageFormats, passing CL_MEM_OBJECT_IMAGE3D and one of |
| // CL_MEM_WRITE_ONLY, CL_MEM_READ_WRITE, or CL_MEM_KERNEL_READ_AND_WRITE |
| // Returns an empty set (such as num_image_formats equal to 0), |
| // indicating that no image formats are supported for writing to 3D |
| // image objects, if no devices in context support Writing to 3D Image |
| // Objects. |
| cl_int error; |
| |
| cl_uint total3DImageWriteFormats = 0; |
| |
| const cl_mem_flags mem_flags[] = { |
| CL_MEM_WRITE_ONLY, |
| CL_MEM_READ_WRITE, |
| CL_MEM_KERNEL_READ_AND_WRITE, |
| }; |
| for (int i = 0; i < ARRAY_SIZE(mem_flags); i++) |
| { |
| cl_uint numImageFormats = 0; |
| error = clGetSupportedImageFormats(context, mem_flags[i], |
| CL_MEM_OBJECT_IMAGE3D, 0, NULL, |
| &numImageFormats); |
| test_error( |
| error, |
| "Unable to query number of CL_MEM_OBJECT_IMAGE3D image formats"); |
| |
| total3DImageWriteFormats += numImageFormats; |
| } |
| |
| bool supports_cl_khr_3d_image_writes = |
| is_extension_available(deviceID, "cl_khr_3d_image_writes"); |
| |
| if (total3DImageWriteFormats == 0) |
| { |
| // clGetDeviceInfo, passing CL_DEVICE_EXTENSIONS |
| // Will not describe support for the cl_khr_3d_image_writes extension if |
| // device does not support Writing to 3D Image Objects. |
| test_assert_error(supports_cl_khr_3d_image_writes == false, |
| "Device does not support Writing to 3D Image Objects " |
| "but does support cl_khr_3d_image_writes"); |
| } |
| else |
| { |
| test_assert_error(supports_cl_khr_3d_image_writes, |
| "Device supports Writing to 3D Image Objects but " |
| "does not support cl_khr_3d_image_writes"); |
| } |
| |
| return TEST_PASS; |
| } |