diff --git a/test_conformance/api/testBase.h b/test_conformance/api/testBase.h index 02f76e94..beb3c924 100644 --- a/test_conformance/api/testBase.h +++ b/test_conformance/api/testBase.h @@ -27,4 +27,24 @@ #include #include +// scope guard helper to ensure proper releasing of sub devices +struct SubDevicesScopeGuarded +{ + SubDevicesScopeGuarded(const cl_int dev_count) + { + sub_devices.resize(dev_count); + } + ~SubDevicesScopeGuarded() + { + for (auto &device : sub_devices) + { + cl_int err = clReleaseDevice(device); + if (err != CL_SUCCESS) + log_error("\n Releasing sub-device failed \n"); + } + } + + std::vector sub_devices; +}; + #endif // _testBase_h diff --git a/test_conformance/api/test_queries.cpp b/test_conformance/api/test_queries.cpp index 92eff9c1..81b99495 100644 --- a/test_conformance/api/test_queries.cpp +++ b/test_conformance/api/test_queries.cpp @@ -18,8 +18,10 @@ #include "harness/propertyHelpers.h" #include #include +#include #include #include +#include #include REGISTER_TEST(get_platform_info) @@ -476,18 +478,41 @@ REGISTER_TEST(get_command_queue_info_compatibility) REGISTER_TEST(get_context_info) { int error; + + // query single device context and perform object comparability test + cl_uint num_devices = 0; + error = clGetContextInfo(context, CL_CONTEXT_NUM_DEVICES, sizeof(cl_uint), + &num_devices, nullptr); + test_error(error, "clGetContextInfo CL_CONTEXT_NUM_DEVICES failed\n"); + + test_assert_error(num_devices == 1, + "Context must contain exactly one device\n"); + + cl_device_id comp_device = nullptr; + error = clGetContextInfo(context, CL_CONTEXT_DEVICES, sizeof(cl_device_id), + &comp_device, nullptr); + test_error(error, "clGetContextInfo CL_CONTEXT_DEVICES failed\n"); + + test_assert_error(device == comp_device, + "Unexpected result returned by CL_CONTEXT_DEVICES query"); + + // query context properties against valid size size_t size; cl_context_properties props; + error = clGetContextInfo(context, CL_CONTEXT_PROPERTIES, sizeof(props), + &props, &size); + test_error(error, "Unable to get context props"); - error = clGetContextInfo( context, CL_CONTEXT_PROPERTIES, sizeof( props ), &props, &size ); - test_error( error, "Unable to get context props" ); - - if (size == 0) { + if (size == 0) + { // Valid size return 0; - } else if (size == sizeof(cl_context_properties)) { + } + else if (size == sizeof(cl_context_properties)) + { // Data must be NULL - if (props != 0) { + if (props != 0) + { log_error("ERROR: Returned properties is no NULL.\n"); return -1; } @@ -495,11 +520,126 @@ REGISTER_TEST(get_context_info) return 0; } // Size was not 0 or 1 - log_error( "ERROR: Returned size of context props is not valid! (expected 0 or %d, got %d)\n", - (int)sizeof(cl_context_properties), (int)size ); + log_error("ERROR: Returned size of context props is not valid! (expected 0 " + "or %d, got %d)\n", + (int)sizeof(cl_context_properties), (int)size); return -1; } +REGISTER_TEST(get_context_info_mult_devices) +{ + cl_int err = CL_SUCCESS; + size_t size = 0; + + // query multi-device context and perform objects comparability test + err = clGetDeviceInfo(device, CL_DEVICE_PARTITION_PROPERTIES, 0, nullptr, + &size); + test_error_fail(err, "clGetDeviceInfo failed"); + + if (size == 0) + { + log_info("Can't partition device, test not supported\n"); + return TEST_SKIPPED_ITSELF; + } + + std::vector supported_props( + size / sizeof(cl_device_partition_property), 0); + err = clGetDeviceInfo(device, CL_DEVICE_PARTITION_PROPERTIES, + supported_props.size() + * sizeof(cl_device_partition_property), + supported_props.data(), &size); + test_error_fail(err, "clGetDeviceInfo failed"); + + if (supported_props.empty() || supported_props.front() == 0) + { + log_info("Can't partition device, test not supported\n"); + return TEST_SKIPPED_ITSELF; + } + + cl_uint maxComputeUnits = 0; + err = clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, + sizeof(maxComputeUnits), &maxComputeUnits, NULL); + test_error_fail(err, "Unable to get maximal number of compute units"); + + std::vector> partition_props = { + { CL_DEVICE_PARTITION_EQUALLY, (cl_int)maxComputeUnits / 2, 0, 0, 0 }, + { CL_DEVICE_PARTITION_BY_COUNTS, 1, (cl_int)maxComputeUnits - 1, + CL_DEVICE_PARTITION_BY_COUNTS_LIST_END, 0 }, + { CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN, + CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE, 0, 0, 0 } + }; + + std::unique_ptr scope_guard; + cl_uint num_devices = 0; + for (auto &sup_prop : supported_props) + { + for (auto &prop : partition_props) + { + if (sup_prop == prop[0]) + { + // how many sub-devices can we create? + err = clCreateSubDevices(device, prop.data(), 0, nullptr, + &num_devices); + test_error_fail(err, "clCreateSubDevices failed"); + if (num_devices < 2) continue; + + // get the list of subDevices + scope_guard.reset(new SubDevicesScopeGuarded(num_devices)); + err = clCreateSubDevices(device, prop.data(), num_devices, + scope_guard->sub_devices.data(), + &num_devices); + test_error_fail(err, "clCreateSubDevices failed"); + break; + } + } + if (scope_guard.get() != nullptr) break; + } + + if (scope_guard.get() == nullptr) + { + log_info("Can't partition device, test not supported\n"); + return TEST_SKIPPED_ITSELF; + } + + /* Create a multi device context */ + clContextWrapper multi_device_context = clCreateContext( + NULL, (cl_uint)num_devices, scope_guard->sub_devices.data(), nullptr, + nullptr, &err); + test_error_fail(err, "Unable to create testing context"); + + err = clGetContextInfo(multi_device_context, CL_CONTEXT_NUM_DEVICES, + sizeof(cl_uint), &num_devices, nullptr); + test_error_fail(err, "clGetContextInfo CL_CONTEXT_NUM_DEVICES failed\n"); + + test_assert_error(num_devices == scope_guard->sub_devices.size(), + "Context must contain exact number of devices\n"); + + std::vector devices(num_devices); + err = clGetContextInfo(multi_device_context, CL_CONTEXT_DEVICES, + num_devices * sizeof(cl_device_id), devices.data(), + nullptr); + test_error_fail(err, "clGetContextInfo CL_CONTEXT_DEVICES failed\n"); + + test_assert_error(devices.size() == scope_guard->sub_devices.size(), + "Size of devices arrays must be in sync\n"); + + for (cl_uint i = 0; i < devices.size(); i++) + { + bool found = false; + for (auto &it : scope_guard->sub_devices) + { + if (it == devices[i]) + { + found = true; + break; + } + } + test_error_fail( + !found, "Unexpected result returned by CL_CONTEXT_DEVICES query"); + } + return TEST_PASS; +} + void CL_CALLBACK mem_obj_destructor_callback( cl_mem, void *data ) { free( data );