mirror of
https://github.com/KhronosGroup/OpenCL-CTS.git
synced 2026-03-26 08:49:02 +00:00
Fix cross-context semaphore signals (#1886)
Multi-context test was not correctly testing cross-context functionality. Use semaphore import/export mechanism to signal across contexts.
This commit is contained in:
@@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
test_definition test_list[] = {
|
test_definition test_list[] = {
|
||||||
ADD_TEST(external_semaphores_queries),
|
ADD_TEST(external_semaphores_queries),
|
||||||
ADD_TEST(external_semaphores_multi_context),
|
ADD_TEST(external_semaphores_cross_context),
|
||||||
ADD_TEST(external_semaphores_simple_1),
|
ADD_TEST(external_semaphores_simple_1),
|
||||||
// ADD_TEST(external_semaphores_simple_2),
|
// ADD_TEST(external_semaphores_simple_2),
|
||||||
ADD_TEST(external_semaphores_reuse),
|
ADD_TEST(external_semaphores_reuse),
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ extern int test_external_semaphores_queries(cl_device_id deviceID,
|
|||||||
cl_context context,
|
cl_context context,
|
||||||
cl_command_queue defaultQueue,
|
cl_command_queue defaultQueue,
|
||||||
int num_elements);
|
int num_elements);
|
||||||
extern int test_external_semaphores_multi_context(cl_device_id deviceID,
|
extern int test_external_semaphores_cross_context(cl_device_id deviceID,
|
||||||
cl_context context,
|
cl_context context,
|
||||||
cl_command_queue defaultQueue,
|
cl_command_queue defaultQueue,
|
||||||
int num_elements);
|
int num_elements);
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "opencl_vulkan_wrapper.hpp"
|
#include "opencl_vulkan_wrapper.hpp"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <unordered_set>
|
||||||
|
|
||||||
#define FLUSH_DELAY_S 5
|
#define FLUSH_DELAY_S 5
|
||||||
|
|
||||||
@@ -82,6 +83,34 @@ static int init_vuikan_device(cl_uint num_devices, cl_device_id* deviceIds)
|
|||||||
return CL_SUCCESS;
|
return CL_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cl_int get_device_semaphore_handle_types(
|
||||||
|
cl_device_id deviceID, cl_device_info param,
|
||||||
|
std::vector<cl_external_semaphore_handle_type_khr>& handle_types)
|
||||||
|
{
|
||||||
|
int err = CL_SUCCESS;
|
||||||
|
// Query for export support
|
||||||
|
size_t size_handle_types = 0;
|
||||||
|
size_t num_handle_types = 0;
|
||||||
|
err = clGetDeviceInfo(deviceID, param, 0, nullptr, &size_handle_types);
|
||||||
|
test_error(err, "Failed to get number of exportable handle types");
|
||||||
|
|
||||||
|
num_handle_types =
|
||||||
|
size_handle_types / sizeof(cl_external_semaphore_handle_type_khr);
|
||||||
|
std::vector<cl_external_semaphore_handle_type_khr>
|
||||||
|
handle_types_query_result(num_handle_types);
|
||||||
|
err = clGetDeviceInfo(deviceID, param,
|
||||||
|
handle_types_query_result.size()
|
||||||
|
* sizeof(cl_external_semaphore_handle_type_khr),
|
||||||
|
handle_types_query_result.data(), nullptr);
|
||||||
|
test_error(err, "Failed to get exportable handle types");
|
||||||
|
|
||||||
|
for (auto handle_type : handle_types_query_result)
|
||||||
|
{
|
||||||
|
handle_types.push_back(handle_type);
|
||||||
|
}
|
||||||
|
return CL_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
// Confirm the semaphores can be successfully queried
|
// Confirm the semaphores can be successfully queried
|
||||||
int test_external_semaphores_queries(cl_device_id deviceID, cl_context context,
|
int test_external_semaphores_queries(cl_device_id deviceID, cl_context context,
|
||||||
cl_command_queue defaultQueue,
|
cl_command_queue defaultQueue,
|
||||||
@@ -169,11 +198,12 @@ int test_external_semaphores_queries(cl_device_id deviceID, cl_context context,
|
|||||||
return TEST_PASS;
|
return TEST_PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int test_external_semaphores_multi_context(cl_device_id deviceID,
|
int test_external_semaphores_cross_context(cl_device_id deviceID,
|
||||||
cl_context context,
|
cl_context context,
|
||||||
cl_command_queue defaultQueue,
|
cl_command_queue defaultQueue,
|
||||||
int num_elements)
|
int num_elements)
|
||||||
{
|
{
|
||||||
|
cl_int err = CL_SUCCESS;
|
||||||
if (!is_extension_available(deviceID, "cl_khr_external_semaphore"))
|
if (!is_extension_available(deviceID, "cl_khr_external_semaphore"))
|
||||||
{
|
{
|
||||||
log_info("cl_khr_semaphore is not supported on this platoform. "
|
log_info("cl_khr_semaphore is not supported on this platoform. "
|
||||||
@@ -181,97 +211,116 @@ int test_external_semaphores_multi_context(cl_device_id deviceID,
|
|||||||
return TEST_SKIPPED_ITSELF;
|
return TEST_SKIPPED_ITSELF;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_vuikan_device(1, &deviceID))
|
GET_PFN(deviceID, clEnqueueSignalSemaphoresKHR);
|
||||||
|
GET_PFN(deviceID, clEnqueueWaitSemaphoresKHR);
|
||||||
|
GET_PFN(deviceID, clCreateSemaphoreWithPropertiesKHR);
|
||||||
|
GET_PFN(deviceID, clGetSemaphoreHandleForTypeKHR);
|
||||||
|
GET_PFN(deviceID, clReleaseSemaphoreKHR);
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<cl_external_semaphore_handle_type_khr> import_handle_types;
|
||||||
|
std::vector<cl_external_semaphore_handle_type_khr> export_handle_types;
|
||||||
|
|
||||||
|
err = get_device_semaphore_handle_types(
|
||||||
|
deviceID, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR,
|
||||||
|
import_handle_types);
|
||||||
|
test_error(err, "Failed to query import handle types");
|
||||||
|
|
||||||
|
err = get_device_semaphore_handle_types(
|
||||||
|
deviceID, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR,
|
||||||
|
export_handle_types);
|
||||||
|
test_error(err, "Failed to query export handle types");
|
||||||
|
|
||||||
|
// Find handles that support both import and export
|
||||||
|
std::unordered_set<cl_external_semaphore_handle_type_khr>
|
||||||
|
import_export_handle_types;
|
||||||
|
|
||||||
|
std::copy(import_handle_types.begin(), import_handle_types.end(),
|
||||||
|
std::inserter(import_export_handle_types,
|
||||||
|
import_export_handle_types.end()));
|
||||||
|
std::copy(export_handle_types.begin(), export_handle_types.end(),
|
||||||
|
std::inserter(import_export_handle_types,
|
||||||
|
import_export_handle_types.end()));
|
||||||
|
|
||||||
|
cl_context context2 =
|
||||||
|
clCreateContext(NULL, 1, &deviceID, notify_callback, NULL, &err);
|
||||||
|
test_error(err, "Failed to create context2");
|
||||||
|
|
||||||
|
clCommandQueueWrapper queue1 =
|
||||||
|
clCreateCommandQueue(context, deviceID, 0, &err);
|
||||||
|
test_error(err, "Could not create command queue");
|
||||||
|
|
||||||
|
clCommandQueueWrapper queue2 =
|
||||||
|
clCreateCommandQueue(context2, deviceID, 0, &err);
|
||||||
|
test_error(err, "Could not create command queue");
|
||||||
|
|
||||||
|
if (import_export_handle_types.empty())
|
||||||
{
|
{
|
||||||
log_info("Cannot initialise Vulkan. "
|
log_info("Could not find a handle type that supports both import and "
|
||||||
"Skipping test.\n");
|
"export");
|
||||||
return TEST_SKIPPED_ITSELF;
|
return TEST_SKIPPED_ITSELF;
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanDevice vkDevice;
|
for (auto handle_type : import_export_handle_types)
|
||||||
|
|
||||||
GET_PFN(deviceID, clEnqueueSignalSemaphoresKHR);
|
|
||||||
GET_PFN(deviceID, clEnqueueWaitSemaphoresKHR);
|
|
||||||
|
|
||||||
std::vector<VulkanExternalSemaphoreHandleType>
|
|
||||||
vkExternalSemaphoreHandleTypeList =
|
|
||||||
getSupportedInteropExternalSemaphoreHandleTypes(deviceID, vkDevice);
|
|
||||||
|
|
||||||
if (vkExternalSemaphoreHandleTypeList.empty())
|
|
||||||
{
|
{
|
||||||
test_fail("No external semaphore handle types found\n");
|
cl_semaphore_properties_khr export_props[] = {
|
||||||
}
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_KHR,
|
||||||
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_BINARY_KHR,
|
||||||
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR,
|
||||||
|
(cl_semaphore_properties_khr)handle_type,
|
||||||
|
(cl_semaphore_properties_khr)
|
||||||
|
CL_SEMAPHORE_EXPORT_HANDLE_TYPES_LIST_END_KHR,
|
||||||
|
(cl_semaphore_properties_khr)0
|
||||||
|
};
|
||||||
|
|
||||||
for (VulkanExternalSemaphoreHandleType vkExternalSemaphoreHandleType :
|
// Signal semaphore on context1
|
||||||
vkExternalSemaphoreHandleTypeList)
|
cl_semaphore_khr exportable_semaphore =
|
||||||
{
|
clCreateSemaphoreWithPropertiesKHR(context, export_props, &err);
|
||||||
log_info_semaphore_type(vkExternalSemaphoreHandleType);
|
test_error(err, "Failed to create exportable semaphore");
|
||||||
VulkanSemaphore vkVk2CLSemaphore(vkDevice,
|
|
||||||
vkExternalSemaphoreHandleType);
|
|
||||||
|
|
||||||
cl_int err = CL_SUCCESS;
|
err = clEnqueueSignalSemaphoresKHR(queue1, 1, &exportable_semaphore,
|
||||||
|
nullptr, 0, nullptr, nullptr);
|
||||||
|
test_error(err, "Failed to signal semaphore on context1");
|
||||||
|
|
||||||
cl_context context2 =
|
cl_semaphore_properties_khr handle =
|
||||||
clCreateContext(NULL, 1, &deviceID, notify_callback, NULL, &err);
|
0; // The handle must fit in cl_semaphore_properties_khr
|
||||||
if (!context2)
|
err = clGetSemaphoreHandleForTypeKHR(exportable_semaphore, deviceID,
|
||||||
{
|
handle_type, sizeof(handle),
|
||||||
print_error(err, "Unable to create testing context");
|
&handle, nullptr);
|
||||||
return TEST_FAIL;
|
test_error(err, "Failed to export handle from semaphore");
|
||||||
}
|
|
||||||
|
|
||||||
clExternalExportableSemaphore sema_ext_1(
|
// Import semaphore into context2
|
||||||
vkVk2CLSemaphore, context, vkExternalSemaphoreHandleType, deviceID);
|
cl_semaphore_properties_khr import_props[] = {
|
||||||
clExternalExportableSemaphore sema_ext_2(vkVk2CLSemaphore, context2,
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_KHR,
|
||||||
vkExternalSemaphoreHandleType,
|
(cl_semaphore_properties_khr)CL_SEMAPHORE_TYPE_BINARY_KHR,
|
||||||
deviceID);
|
(cl_semaphore_properties_khr)handle_type,
|
||||||
|
(cl_semaphore_properties_khr)handle, (cl_semaphore_properties_khr)0
|
||||||
|
};
|
||||||
|
|
||||||
clCommandQueueWrapper queue1 =
|
cl_semaphore_khr imported_semaphore =
|
||||||
clCreateCommandQueue(context, deviceID, 0, &err);
|
clCreateSemaphoreWithPropertiesKHR(context2, import_props, &err);
|
||||||
test_error(err, "Could not create command queue");
|
test_error(err, "Failed to import semaphore into context2 semaphore");
|
||||||
|
|
||||||
clCommandQueueWrapper queue2 =
|
err = clEnqueueWaitSemaphoresKHR(queue2, 1, &imported_semaphore,
|
||||||
clCreateCommandQueue(context2, deviceID, 0, &err);
|
nullptr, 0, nullptr, nullptr);
|
||||||
test_error(err, "Could not create command queue");
|
test_error(err, "Failed to signal semaphore on context1");
|
||||||
|
|
||||||
// Signal semaphore 1 and 2
|
err = clFlush(queue1);
|
||||||
clEventWrapper signal_event;
|
test_error(err, "Failed to flush queue1");
|
||||||
err = clEnqueueSignalSemaphoresKHR(queue1, 1,
|
|
||||||
&sema_ext_1.getCLSemaphore(),
|
|
||||||
nullptr, 0, nullptr, &signal_event);
|
|
||||||
test_error(err, "Could not signal semaphore");
|
|
||||||
|
|
||||||
// Wait semaphore 1
|
|
||||||
clEventWrapper wait_1_event;
|
|
||||||
err =
|
|
||||||
clEnqueueWaitSemaphoresKHR(queue1, 1, &sema_ext_1.getCLSemaphore(),
|
|
||||||
nullptr, 0, nullptr, &wait_1_event);
|
|
||||||
test_error(err, "Could not wait semaphore");
|
|
||||||
|
|
||||||
err = clEnqueueSignalSemaphoresKHR(queue2, 1,
|
|
||||||
&sema_ext_2.getCLSemaphore(),
|
|
||||||
nullptr, 0, nullptr, &signal_event);
|
|
||||||
test_error(err, "Could not signal semaphore");
|
|
||||||
|
|
||||||
// Wait semaphore 2
|
|
||||||
clEventWrapper wait_2_event;
|
|
||||||
err =
|
|
||||||
clEnqueueWaitSemaphoresKHR(queue2, 1, &sema_ext_2.getCLSemaphore(),
|
|
||||||
nullptr, 0, nullptr, &wait_2_event);
|
|
||||||
test_error(err, "Could not wait semaphore");
|
|
||||||
|
|
||||||
// Finish
|
|
||||||
err = clFinish(queue1);
|
|
||||||
test_error(err, "Could not finish queue");
|
|
||||||
|
|
||||||
err = clFinish(queue2);
|
err = clFinish(queue2);
|
||||||
test_error(err, "Could not finish queue");
|
test_error(err, "Failed to finish queue2");
|
||||||
|
|
||||||
// Ensure all events are completed
|
err = clReleaseSemaphoreKHR(exportable_semaphore);
|
||||||
test_assert_event_complete(signal_event);
|
test_error(err, "Failed to release semaphore");
|
||||||
test_assert_event_complete(wait_1_event);
|
|
||||||
test_assert_event_complete(wait_2_event);
|
err = clReleaseSemaphoreKHR(imported_semaphore);
|
||||||
|
test_error(err, "Failed to release semaphore");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = clReleaseContext(context2);
|
||||||
|
test_error(err, "Failed to release context2");
|
||||||
|
|
||||||
return TEST_PASS;
|
return TEST_PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user