Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 35 additions & 8 deletions test_common/harness/deviceInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ std::string get_device_info_string(cl_device_id device,
}

/* Determines if an extension is supported by a device. */
int is_extension_available(cl_device_id device, const char *extensionName)
bool is_extension_available(cl_device_id device, const char *extensionName)
{
std::string extString = get_device_extensions_string(device);
std::istringstream ss(extString);
Expand All @@ -63,7 +63,32 @@ int is_extension_available(cl_device_id device, const char *extensionName)
return false;
}

cl_version get_extension_version(cl_device_id device, const char *extensionName)
bool is_extension_available(cl_device_id device, const char *extensionName,
cl_version extensionVersion)
{
const auto version = get_extension_version(device, extensionName);
if (!version)
{
return false;
}

const bool available = *version == extensionVersion;
if (!available)
{
log_info("Extension: %s supported with version: %u.%u.%u. Required "
"version: %u.%u.%u\n",
extensionName, CL_VERSION_MAJOR(*version),
CL_VERSION_MINOR(*version), CL_VERSION_PATCH(*version),
CL_VERSION_MAJOR(extensionVersion),
CL_VERSION_MINOR(extensionVersion),
CL_VERSION_PATCH(extensionVersion));
}

return available;
}

std::optional<cl_version> get_extension_version(cl_device_id device,
const char *extensionName)
{
cl_int err;
size_t size;
Expand All @@ -72,17 +97,19 @@ cl_version get_extension_version(cl_device_id device, const char *extensionName)
&size);
if (err != CL_SUCCESS)
{
throw std::runtime_error("clGetDeviceInfo(CL_DEVICE_EXTENSIONS_WITH_"
"VERSION) failed to return size\n");
log_error("clGetDeviceInfo(CL_DEVICE_EXTENSIONS_WITH_"
"VERSION) failed to return size\n");
return std::nullopt;
}

std::vector<cl_name_version> extensions(size / sizeof(cl_name_version));
err = clGetDeviceInfo(device, CL_DEVICE_EXTENSIONS_WITH_VERSION, size,
extensions.data(), &size);
if (err != CL_SUCCESS)
{
throw std::runtime_error("clGetDeviceInfo(CL_DEVICE_EXTENSIONS_WITH_"
"VERSION) failed to return value\n");
log_error("clGetDeviceInfo(CL_DEVICE_EXTENSIONS_WITH_"
"VERSION) failed to return value\n");
return std::nullopt;
}

for (auto &ext : extensions)
Expand All @@ -93,8 +120,8 @@ cl_version get_extension_version(cl_device_id device, const char *extensionName)
}
}

throw std::runtime_error("Extension " + std::string(extensionName)
+ " not supported by device!");
log_error("Extension %s not supported by device!\n", extensionName);
return std::nullopt;
}

/* Returns a string containing the supported extensions list for a device. */
Expand Down
27 changes: 22 additions & 5 deletions test_common/harness/deviceInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#define _deviceInfo_h

#include <string>
#include <optional>

#include <CL/opencl.h>

Expand All @@ -26,12 +27,28 @@ std::string get_device_info_string(cl_device_id device,
cl_device_info param_name);

/* Determines if an extension is supported by a device. */
int is_extension_available(cl_device_id device, const char *extensionName);
bool is_extension_available(cl_device_id device, const char *extensionName);

/* Returns the version of the extension the device supports or throws an
* exception if the extension is not supported by the device. */
cl_version get_extension_version(cl_device_id device,
const char *extensionName);
/**
* @brief Check if an extension is supported by an OpenCL device.
*
* In addition to checking that the extension is in the list of extensions
* supported by the device, the function will check the extension version.
* To guarantee compatibility with any breaking changes, the function
* succeeds only on an exact version match.
Comment on lines +35 to +38
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I understand the rationale for checking for an exact version match, but I also think this is likely to cause confusion and problems in the future. Couple of options to consider:

  • Do nothing. 😄
  • Rename the function so it's more obvious that it is checking for the exact version, and leave the door open for additional overloads in the future - is_exact_extension_version_available?
  • Add more version checking smarts, maybe something like checking for an exact version for major versions less than 1, or a matching major version and a minor version equal to or greater?

Note, we may want to ignore mismatching "patch" versions regardless.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have anything to add, but this thread made me think of this CTS Issue we still have #2152 open about how the versions of provisional extensions is tested. It would be nice if we could resolve that issue as part of this PR.

*
* @param device The OpenCL device to query.
* @param extensionName The name of the extension to check for.
* @param extensionVersion The required extension version to be supported.
*
* @return True if the extension is supported by the device, and the supported
* extension version matches the requested version, false otherwise.
*/
bool is_extension_available(cl_device_id device, const char *extensionName,
cl_version extensionVersion);

std::optional<cl_version> get_extension_version(cl_device_id device,
const char *extensionName);

/* Returns a string containing the supported extensions list for a device. */
std::string get_device_extensions_string(cl_device_id device);
Expand Down
11 changes: 8 additions & 3 deletions test_common/harness/testHarness.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,17 +150,22 @@ template <typename T> T *register_test(const char *name, Version version)

#define REGISTER_TEST(name) REGISTER_TEST_VERSION(name, Version(1, 2))

#define REQUIRE_EXTENSION(name) \
#define REQUIRE_EXTENSION(ext) \
do \
{ \
if (!is_extension_available(device, name)) \
if (!is_extension_available(device, ext##_EXTENSION_NAME, \
ext##_EXTENSION_VERSION)) \
Comment on lines +156 to +157
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may be OK, but so we go in with eyes open - I think this means that the tests (that use this macro at least) will only run for implementations that support the extension version in the headers, and only that version.

Do we want to have the ability to test other extension versions also? For example, I could envision tests for an extension that have one codepath for version 1.X and another codepath for version 2.X, kind of like the tests for integer dot product, but perhaps with a breaking change between 1.x and 2.X. For usages like this one I don't think we'd be able to use this REQUIRE_EXTENSION macro the way it is currently defined.

{ \
log_info(name \
log_info(ext##_EXTENSION_NAME \
" is not supported on this device. Skipping test.\n"); \
return TEST_SKIPPED_ITSELF; \
} \
} while (0)

#define HAS_EXTENSION(ext) \
is_extension_available(device, ext##_EXTENSION_NAME, \
ext##_EXTENSION_VERSION)

extern int gFailCount;
extern int gTestCount;
extern cl_uint gReSeed;
Expand Down
2 changes: 1 addition & 1 deletion test_conformance/api/negative_enqueue_map_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ REGISTER_TEST(negative_enqueue_map_image)
{
constexpr size_t image_dim = 32;

REQUIRE_EXTENSION("cl_ext_immutable_memory_objects");
REQUIRE_EXTENSION(CL_EXT_IMMUTABLE_MEMORY_OBJECTS);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is clever, but I wonder if it's a bit too clever, since things like intellisense linking and even grep'ing for these symbols won't work. Should we just type out the extension name and extension version instead?

REQUIRE_EXTENSION(
    CL_EXT_IMMUTABLE_MEMORY_OBJECTS_EXTENSION_NAME,
    CL_EXT_IMMUTABLE_MEMORY_OBJECTS_VERSION);


static constexpr cl_mem_flags mem_flags[]{
CL_MEM_IMMUTABLE_EXT | CL_MEM_USE_HOST_PTR,
Expand Down
4 changes: 2 additions & 2 deletions test_conformance/api/test_kernels.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// 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
Expand Down Expand Up @@ -667,7 +667,7 @@ REGISTER_TEST(kernel_global_constant)

REGISTER_TEST(negative_set_immutable_memory_to_writeable_kernel_arg)
{
REQUIRE_EXTENSION("cl_ext_immutable_memory_objects");
REQUIRE_EXTENSION(CL_EXT_IMMUTABLE_MEMORY_OBJECTS);

cl_int error = CL_SUCCESS;
clProgramWrapper program;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,15 @@ test_status InitCL(cl_device_id device)
return TEST_SKIPPED_ITSELF;
}

cl_version ext_version =
auto ext_version =
get_extension_version(device, "cl_ext_buffer_device_address");

if (ext_version != CL_MAKE_VERSION(1, 0, 2))
{
log_info("The test is written against cl_ext_buffer_device_address "
"extension version 1.0.2, device supports version: %u.%u.%u\n",
CL_VERSION_MAJOR(ext_version), CL_VERSION_MINOR(ext_version),
CL_VERSION_PATCH(ext_version));
CL_VERSION_MAJOR(*ext_version), CL_VERSION_MINOR(*ext_version),
CL_VERSION_PATCH(*ext_version));
return TEST_SKIPPED_ITSELF;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ int MakeAndRunTest(cl_device_id device, cl_context context,
|| is_extension_available(device, "cl_khr_extended_versioning"))
{

cl_version extension_version =
auto extension_version =
get_extension_version(device, "cl_khr_command_buffer");

if (extension_version != CL_MAKE_VERSION(0, 9, 7))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ struct BasicMutableCommandBufferTest : BasicCommandBufferTest
|| is_extension_available(device, "cl_khr_extended_versioning"))
{

cl_version extension_version = get_extension_version(
auto extension_version = get_extension_version(
device, "cl_khr_command_buffer_mutable_dispatch");

if (extension_version != CL_MAKE_VERSION(0, 9, 3))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ struct PropertiesArray : public InfoMutableCommandBufferTest
|| is_extension_available(device, "cl_khr_extended_versioning"))
{

cl_version extension_version = get_extension_version(
auto extension_version = get_extension_version(
device, "cl_khr_command_buffer_mutable_dispatch");

if (extension_version != CL_MAKE_VERSION(0, 9, 3))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ static cl_int get_device_semaphore_handle_types(
// Confirm the semaphores can be successfully queried
REGISTER_TEST_VERSION(external_semaphores_queries, Version(1, 2))
{
REQUIRE_EXTENSION("cl_khr_semaphore");
REQUIRE_EXTENSION("cl_khr_external_semaphore");
REQUIRE_EXTENSION(CL_KHR_SEMAPHORE);
REQUIRE_EXTENSION(CL_KHR_EXTERNAL_SEMAPHORE);

if (init_vulkan_device(1, &device))
{
Expand Down Expand Up @@ -199,7 +199,7 @@ REGISTER_TEST_VERSION(external_semaphores_queries, Version(1, 2))

REGISTER_TEST_VERSION(external_semaphores_cross_context, Version(1, 2))
{
REQUIRE_EXTENSION("cl_khr_external_semaphore");
REQUIRE_EXTENSION(CL_KHR_EXTERNAL_SEMAPHORE);

GET_PFN(device, clEnqueueSignalSemaphoresKHR);
GET_PFN(device, clEnqueueWaitSemaphoresKHR);
Expand Down Expand Up @@ -322,7 +322,7 @@ REGISTER_TEST_VERSION(external_semaphores_cross_context, Version(1, 2))
// Confirm that a signal followed by a wait will complete successfully
REGISTER_TEST_VERSION(external_semaphores_simple_1, Version(1, 2))
{
REQUIRE_EXTENSION("cl_khr_external_semaphore");
REQUIRE_EXTENSION(CL_KHR_EXTERNAL_SEMAPHORE);

if (init_vulkan_device(1, &device))
{
Expand Down Expand Up @@ -391,7 +391,7 @@ REGISTER_TEST_VERSION(external_semaphores_simple_1, Version(1, 2))
// Confirm that a semaphore can be reused multiple times
REGISTER_TEST_VERSION(external_semaphores_reuse, Version(1, 2))
{
REQUIRE_EXTENSION("cl_khr_external_semaphore");
REQUIRE_EXTENSION(CL_KHR_EXTERNAL_SEMAPHORE);

if (init_vulkan_device(1, &device))
{
Expand Down Expand Up @@ -509,7 +509,7 @@ static int external_semaphore_cross_queue_helper(cl_device_id device,
cl_command_queue queue_1,
cl_command_queue queue_2)
{
REQUIRE_EXTENSION("cl_khr_external_semaphore");
REQUIRE_EXTENSION(CL_KHR_EXTERNAL_SEMAPHORE);

if (init_vulkan_device(1, &device))
{
Expand Down Expand Up @@ -612,7 +612,7 @@ REGISTER_TEST_VERSION(external_semaphores_cross_queues_io, Version(1, 2))

REGISTER_TEST_VERSION(external_semaphores_cross_queues_io2, Version(1, 2))
{
REQUIRE_EXTENSION("cl_khr_external_semaphore");
REQUIRE_EXTENSION(CL_KHR_EXTERNAL_SEMAPHORE);

if (init_vulkan_device(1, &device))
{
Expand Down Expand Up @@ -714,7 +714,7 @@ REGISTER_TEST_VERSION(external_semaphores_cross_queues_io2, Version(1, 2))
// Confirm that we can signal multiple semaphores with one command
REGISTER_TEST_VERSION(external_semaphores_multi_signal, Version(1, 2))
{
REQUIRE_EXTENSION("cl_khr_external_semaphore");
REQUIRE_EXTENSION(CL_KHR_EXTERNAL_SEMAPHORE);

if (init_vulkan_device(1, &device))
{
Expand Down Expand Up @@ -796,7 +796,7 @@ REGISTER_TEST_VERSION(external_semaphores_multi_signal, Version(1, 2))
// Confirm that we can wait for multiple semaphores with one command
REGISTER_TEST_VERSION(external_semaphores_multi_wait, Version(1, 2))
{
REQUIRE_EXTENSION("cl_khr_external_semaphore");
REQUIRE_EXTENSION(CL_KHR_EXTERNAL_SEMAPHORE);

if (init_vulkan_device(1, &device))
{
Expand Down
8 changes: 7 additions & 1 deletion test_conformance/integer_ops/test_integer_dot_product.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,14 @@ REGISTER_TEST(integer_dot_product)
if ((deviceVersion >= Version(3, 0))
|| is_extension_available(device, "cl_khr_extended_versioning"))
{
extensionVersion =
auto version =
get_extension_version(device, "cl_khr_integer_dot_product");
if (!version)
{
return TEST_FAIL;
}

extensionVersion = *version;
}
else
{
Expand Down
5 changes: 2 additions & 3 deletions test_conformance/spir/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//
// 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
Expand Down Expand Up @@ -6911,7 +6911,7 @@ int main (int argc, const char* argv[])
cl_device_id device = get_platform_device(device_type, choosen_device_index, choosen_platform_index);
printDeviceHeader(device);

REQUIRE_EXTENSION("cl_khr_spir");
REQUIRE_EXTENSION(CL_KHR_SPIR);

std::vector<Version> versions;
get_spir_version(device, versions);
Expand Down Expand Up @@ -6986,4 +6986,3 @@ int main (int argc, const char* argv[])
return 3;
}
}

Loading