Clean up cl_khr_external_semaphore_dx_fence test (#2580)

Removes the duplicated code from the tests. Improves the Base test
class.
This commit is contained in:
Jose Lopez
2026-01-20 18:02:26 +00:00
committed by GitHub
parent 5af0e74ef4
commit 584f27afd4
9 changed files with 662 additions and 673 deletions

View File

@@ -32,5 +32,15 @@
} \ } \
} while (false) } while (false)
#define GET_FUNCTION_EXTENSION_ADDRESS(device, FUNC) \
FUNC = \
reinterpret_cast<FUNC##_fn>(clGetExtensionFunctionAddressForPlatform( \
getPlatformFromDevice(device), #FUNC)); \
if (FUNC == nullptr) \
{ \
log_error("ERROR: clGetExtensionFunctionAddressForPlatform failed" \
" with " #FUNC "\n"); \
return TEST_FAIL; \
}
#endif // _extensionHelpers_h #endif // _extensionHelpers_h

View File

@@ -26,9 +26,9 @@ class DirectXWrapper {
public: public:
DirectXWrapper(); DirectXWrapper();
ID3D12Device* getDXDevice() const; [[nodiscard]] ID3D12Device* getDXDevice() const;
ID3D12CommandQueue* getDXCommandQueue() const; [[nodiscard]] ID3D12CommandQueue* getDXCommandQueue() const;
ID3D12CommandAllocator* getDXCommandAllocator() const; [[nodiscard]] ID3D12CommandAllocator* getDXCommandAllocator() const;
protected: protected:
ComPtr<ID3D12Device> dx_device = nullptr; ComPtr<ID3D12Device> dx_device = nullptr;
@@ -39,7 +39,7 @@ protected:
class DirectXFenceWrapper { class DirectXFenceWrapper {
public: public:
DirectXFenceWrapper(ID3D12Device* dx_device); DirectXFenceWrapper(ID3D12Device* dx_device);
ID3D12Fence* operator*() const { return dx_fence.Get(); } [[nodiscard]] ID3D12Fence* get() const { return dx_fence.Get(); }
private: private:
ComPtr<ID3D12Fence> dx_fence = nullptr; ComPtr<ID3D12Fence> dx_fence = nullptr;

View File

@@ -17,6 +17,7 @@
int main(int argc, const char *argv[]) int main(int argc, const char *argv[])
{ {
return runTestHarness(argc, argv, test_registry::getInstance().num_tests(), return runTestHarness(
argc, argv, static_cast<int>(test_registry::getInstance().num_tests()),
test_registry::getInstance().definitions(), false, 0); test_registry::getInstance().definitions(), false, 0);
} }

View File

@@ -21,81 +21,91 @@
#include "harness/errorHelpers.h" #include "harness/errorHelpers.h"
#include "directx_wrapper.hpp" #include "directx_wrapper.hpp"
class CLDXSemaphoreWrapper { struct DXFenceTestBase
public:
CLDXSemaphoreWrapper(cl_device_id device, cl_context context,
ID3D12Device* dx_device)
: device(device), context(context), dx_device(dx_device){};
int createSemaphoreFromFence(ID3D12Fence* fence)
{ {
cl_int errcode = CL_SUCCESS; DXFenceTestBase(cl_device_id device, cl_context context,
cl_command_queue queue, cl_int num_elems)
GET_PFN(device, clCreateSemaphoreWithPropertiesKHR); : device(device), context(context), queue(queue), num_elems(num_elems)
{}
const HRESULT hr = dx_device->CreateSharedHandle( virtual ~DXFenceTestBase()
fence, nullptr, GENERIC_ALL, nullptr, &fence_handle);
test_error(FAILED(hr), "Failed to get shared handle from D3D12 fence");
cl_semaphore_properties_khr sem_props[] = {
static_cast<cl_semaphore_properties_khr>(CL_SEMAPHORE_TYPE_KHR),
static_cast<cl_semaphore_properties_khr>(
CL_SEMAPHORE_TYPE_BINARY_KHR),
static_cast<cl_semaphore_properties_khr>(
CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR),
reinterpret_cast<cl_semaphore_properties_khr>(fence_handle), 0
};
semaphore =
clCreateSemaphoreWithPropertiesKHR(context, sem_props, &errcode);
test_error(errcode, "Could not create semaphore");
return CL_SUCCESS;
}
~CLDXSemaphoreWrapper()
{ {
releaseSemaphore();
if (fence_handle) if (fence_handle)
{ {
CloseHandle(fence_handle); CloseHandle(fence_handle);
fence_handle = nullptr;
} }
}; if (fence_wrapper)
const cl_semaphore_khr* operator&() const { return &semaphore; };
cl_semaphore_khr operator*() const { return semaphore; };
HANDLE getHandle() const { return fence_handle; };
private:
cl_semaphore_khr semaphore;
ComPtr<ID3D12Fence> fence;
HANDLE fence_handle;
cl_device_id device;
cl_context context;
ComPtr<ID3D12Device> dx_device;
int releaseSemaphore() const
{ {
GET_PFN(device, clReleaseSemaphoreKHR); delete fence_wrapper;
fence_wrapper = nullptr;
}
if (semaphore) if (semaphore)
{ {
clReleaseSemaphoreKHR(semaphore); clReleaseSemaphoreKHR(semaphore);
} semaphore = nullptr;
return CL_SUCCESS;
} }
}; };
static bool virtual int SetUp()
is_import_handle_available(cl_device_id device, {
REQUIRE_EXTENSION("cl_khr_external_semaphore");
REQUIRE_EXTENSION("cl_khr_external_semaphore_dx_fence");
// Obtain pointers to semaphore's API
GET_FUNCTION_EXTENSION_ADDRESS(device,
clCreateSemaphoreWithPropertiesKHR);
GET_FUNCTION_EXTENSION_ADDRESS(device, clReleaseSemaphoreKHR);
GET_FUNCTION_EXTENSION_ADDRESS(device, clEnqueueSignalSemaphoresKHR);
GET_FUNCTION_EXTENSION_ADDRESS(device, clEnqueueWaitSemaphoresKHR);
GET_FUNCTION_EXTENSION_ADDRESS(device, clGetSemaphoreHandleForTypeKHR);
GET_FUNCTION_EXTENSION_ADDRESS(device, clRetainSemaphoreKHR);
GET_FUNCTION_EXTENSION_ADDRESS(device, clGetSemaphoreInfoKHR);
test_error(
!is_import_handle_available(CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR),
"Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between the "
"supported import types");
// Import D3D12 fence into OpenCL
fence_wrapper = new DirectXFenceWrapper(dx_wrapper.getDXDevice());
semaphore = createSemaphoreFromFence(fence_wrapper->get());
test_assert_error(!!semaphore, "Could not create semaphore");
return TEST_PASS;
}
virtual cl_int Run() = 0;
protected:
int errcode = CL_SUCCESS;
cl_device_id device = nullptr;
cl_context context = nullptr;
cl_command_queue queue = nullptr;
cl_int num_elems = 0;
DirectXWrapper dx_wrapper;
cl_semaphore_payload_khr semaphore_payload = 1;
cl_semaphore_khr semaphore = nullptr;
HANDLE fence_handle = nullptr;
DirectXFenceWrapper *fence_wrapper = nullptr;
clCreateSemaphoreWithPropertiesKHR_fn clCreateSemaphoreWithPropertiesKHR =
nullptr;
clEnqueueSignalSemaphoresKHR_fn clEnqueueSignalSemaphoresKHR = nullptr;
clEnqueueWaitSemaphoresKHR_fn clEnqueueWaitSemaphoresKHR = nullptr;
clReleaseSemaphoreKHR_fn clReleaseSemaphoreKHR = nullptr;
clGetSemaphoreInfoKHR_fn clGetSemaphoreInfoKHR = nullptr;
clRetainSemaphoreKHR_fn clRetainSemaphoreKHR = nullptr;
clGetSemaphoreHandleForTypeKHR_fn clGetSemaphoreHandleForTypeKHR = nullptr;
[[nodiscard]] bool is_import_handle_available(
const cl_external_memory_handle_type_khr handle_type) const cl_external_memory_handle_type_khr handle_type)
{ {
int errcode = CL_SUCCESS;
size_t import_types_size = 0; size_t import_types_size = 0;
errcode = errcode =
clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR, 0, clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR,
nullptr, &import_types_size); 0, nullptr, &import_types_size);
if (errcode != CL_SUCCESS) if (errcode != CL_SUCCESS)
{ {
log_error("Could not query import semaphore handle types"); log_error("Could not query import semaphore handle types");
@@ -115,3 +125,45 @@ is_import_handle_available(cl_device_id device,
return std::find(import_types.begin(), import_types.end(), handle_type) return std::find(import_types.begin(), import_types.end(), handle_type)
!= import_types.end(); != import_types.end();
} }
cl_semaphore_khr createSemaphoreFromFence(ID3D12Fence *src_fence)
{
const HRESULT hr = dx_wrapper.getDXDevice()->CreateSharedHandle(
src_fence, nullptr, GENERIC_ALL, nullptr, &fence_handle);
if (FAILED(hr)) return nullptr;
const cl_semaphore_properties_khr sem_props[] = {
static_cast<cl_semaphore_properties_khr>(CL_SEMAPHORE_TYPE_KHR),
static_cast<cl_semaphore_properties_khr>(
CL_SEMAPHORE_TYPE_BINARY_KHR),
static_cast<cl_semaphore_properties_khr>(
CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR),
reinterpret_cast<cl_semaphore_properties_khr>(fence_handle), 0
};
cl_semaphore_khr tmp_semaphore =
clCreateSemaphoreWithPropertiesKHR(context, sem_props, &errcode);
if (errcode != CL_SUCCESS) return nullptr;
return tmp_semaphore;
}
};
template <class T>
int MakeAndRunTest(cl_device_id device, cl_context context,
cl_command_queue queue, cl_int nelems)
{
cl_int status = TEST_PASS;
try
{
auto test_fixture = T(device, context, queue, nelems);
status = test_fixture.SetUp();
if (status != TEST_PASS) return status;
status = test_fixture.Run();
} catch (const std::runtime_error &e)
{
log_error("%s", e.what());
return TEST_FAIL;
}
return status;
}

View File

@@ -16,37 +16,17 @@
#include "semaphore_dx_fence_base.h" #include "semaphore_dx_fence_base.h"
// Confirm that a signal followed by a wait in OpenCL will complete successfully struct SignalWait final : DXFenceTestBase
REGISTER_TEST(test_external_semaphores_signal_wait)
{ {
int errcode = CL_SUCCESS; using DXFenceTestBase::DXFenceTestBase;
const DirectXWrapper dx_wrapper;
REQUIRE_EXTENSION("cl_khr_external_semaphore");
REQUIRE_EXTENSION("cl_khr_external_semaphore_dx_fence");
// Obtain pointers to semaphore's API
GET_PFN(device, clCreateSemaphoreWithPropertiesKHR);
GET_PFN(device, clReleaseSemaphoreKHR);
GET_PFN(device, clEnqueueSignalSemaphoresKHR);
GET_PFN(device, clEnqueueWaitSemaphoresKHR);
test_error(!is_import_handle_available(device,
CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR),
"Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between the "
"supported import types");
// Import D3D12 fence into OpenCL
const DirectXFenceWrapper fence(dx_wrapper.getDXDevice());
CLDXSemaphoreWrapper semaphore(device, context, dx_wrapper.getDXDevice());
test_error(semaphore.createSemaphoreFromFence(*fence),
"Could not create semaphore");
cl_int Run() override
{
log_info("Calling clEnqueueSignalSemaphoresKHR\n"); log_info("Calling clEnqueueSignalSemaphoresKHR\n");
constexpr cl_semaphore_payload_khr semaphore_payload = 1;
clEventWrapper signal_event; clEventWrapper signal_event;
errcode = clEnqueueSignalSemaphoresKHR( errcode = clEnqueueSignalSemaphoresKHR(queue, 1, &semaphore,
queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &signal_event); &semaphore_payload, 0, nullptr,
&signal_event);
test_error(errcode, "Failed to signal semaphore"); test_error(errcode, "Failed to signal semaphore");
log_info("Calling clEnqueueWaitSemaphoresKHR\n"); log_info("Calling clEnqueueWaitSemaphoresKHR\n");
@@ -64,43 +44,28 @@ REGISTER_TEST(test_external_semaphores_signal_wait)
return TEST_PASS; return TEST_PASS;
} }
};
// Confirm that a wait in OpenCL followed by a CPU signal in DX12 will complete // Confirm that a signal followed by a wait in OpenCL will complete successfully
// successfully REGISTER_TEST(test_external_semaphores_signal_wait)
REGISTER_TEST(test_external_semaphores_signal_dx_cpu)
{ {
int errcode = CL_SUCCESS; return MakeAndRunTest<SignalWait>(device, context, queue, num_elements);
const DirectXWrapper dx_wrapper; }
REQUIRE_EXTENSION("cl_khr_external_semaphore"); struct SignalDXCPU final : DXFenceTestBase
REQUIRE_EXTENSION("cl_khr_external_semaphore_dx_fence"); {
using DXFenceTestBase::DXFenceTestBase;
// Obtain pointers to semaphore's API
GET_PFN(device, clCreateSemaphoreWithPropertiesKHR);
GET_PFN(device, clReleaseSemaphoreKHR);
GET_PFN(device, clEnqueueSignalSemaphoresKHR);
GET_PFN(device, clEnqueueWaitSemaphoresKHR);
test_error(!is_import_handle_available(device,
CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR),
"Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between the "
"supported import types");
// Import D3D12 fence into OpenCL
const DirectXFenceWrapper fence(dx_wrapper.getDXDevice());
CLDXSemaphoreWrapper semaphore(device, context, dx_wrapper.getDXDevice());
test_error(semaphore.createSemaphoreFromFence(*fence),
"Could not create semaphore");
cl_int Run() override
{
log_info("Calling clEnqueueWaitSemaphoresKHR\n"); log_info("Calling clEnqueueWaitSemaphoresKHR\n");
constexpr cl_semaphore_payload_khr semaphore_payload = 1;
clEventWrapper wait_event; clEventWrapper wait_event;
errcode = clEnqueueWaitSemaphoresKHR( errcode = clEnqueueWaitSemaphoresKHR(
queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event); queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event);
test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR"); test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR");
log_info("Calling d3d12_fence->Signal()\n"); log_info("Calling d3d12_fence->Signal()\n");
const HRESULT hr = (*fence)->Signal(semaphore_payload); const HRESULT hr = fence_wrapper->get()->Signal(semaphore_payload);
test_error(FAILED(hr), "Failed to signal D3D12 fence"); test_error(FAILED(hr), "Failed to signal D3D12 fence");
errcode = clFinish(queue); errcode = clFinish(queue);
@@ -110,44 +75,30 @@ REGISTER_TEST(test_external_semaphores_signal_dx_cpu)
return TEST_PASS; return TEST_PASS;
} }
};
// Confirm that a wait in OpenCL followed by a GPU signal in DX12 will complete // Confirm that a wait in OpenCL followed by a CPU signal in DX12 will complete
// successfully // successfully
REGISTER_TEST(test_external_semaphores_signal_dx_gpu) REGISTER_TEST(test_external_semaphores_signal_dx_cpu)
{ {
int errcode = CL_SUCCESS; return MakeAndRunTest<SignalDXCPU>(device, context, queue, num_elements);
const DirectXWrapper dx_wrapper; }
REQUIRE_EXTENSION("cl_khr_external_semaphore"); struct SignalDXGPU final : DXFenceTestBase
REQUIRE_EXTENSION("cl_khr_external_semaphore_dx_fence"); {
using DXFenceTestBase::DXFenceTestBase;
// Obtain pointers to semaphore's API
GET_PFN(device, clCreateSemaphoreWithPropertiesKHR);
GET_PFN(device, clReleaseSemaphoreKHR);
GET_PFN(device, clEnqueueSignalSemaphoresKHR);
GET_PFN(device, clEnqueueWaitSemaphoresKHR);
test_error(!is_import_handle_available(device,
CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR),
"Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between the "
"supported import types");
// Import D3D12 fence into OpenCL
const DirectXFenceWrapper fence(dx_wrapper.getDXDevice());
CLDXSemaphoreWrapper semaphore(device, context, dx_wrapper.getDXDevice());
test_error(semaphore.createSemaphoreFromFence(*fence),
"Could not create semaphore");
cl_int Run() override
{
log_info("Calling clEnqueueWaitSemaphoresKHR\n"); log_info("Calling clEnqueueWaitSemaphoresKHR\n");
constexpr cl_semaphore_payload_khr semaphore_payload = 1;
clEventWrapper wait_event; clEventWrapper wait_event;
errcode = clEnqueueWaitSemaphoresKHR( errcode = clEnqueueWaitSemaphoresKHR(
queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event); queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event);
test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR"); test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR");
log_info("Calling d3d12_command_queue->Signal()\n"); log_info("Calling d3d12_command_queue->Signal()\n");
const HRESULT hr = const HRESULT hr = dx_wrapper.getDXCommandQueue()->Signal(
dx_wrapper.getDXCommandQueue()->Signal(*fence, semaphore_payload); fence_wrapper->get(), semaphore_payload);
test_error(FAILED(hr), "Failed to signal D3D12 fence"); test_error(FAILED(hr), "Failed to signal D3D12 fence");
errcode = clFinish(queue); errcode = clFinish(queue);
@@ -157,48 +108,36 @@ REGISTER_TEST(test_external_semaphores_signal_dx_gpu)
return TEST_PASS; return TEST_PASS;
} }
};
// Confirm that interlocking waits between OpenCL and DX12 will complete // Confirm that a wait in OpenCL followed by a GPU signal in DX12 will complete
// successfully // successfully
REGISTER_TEST(test_external_semaphores_cl_dx_interlock) REGISTER_TEST(test_external_semaphores_signal_dx_gpu)
{ {
int errcode = CL_SUCCESS; return MakeAndRunTest<SignalDXGPU>(device, context, queue, num_elements);
const DirectXWrapper dx_wrapper; }
REQUIRE_EXTENSION("cl_khr_external_semaphore"); struct CLDXInterlock final : DXFenceTestBase
REQUIRE_EXTENSION("cl_khr_external_semaphore_dx_fence"); {
using DXFenceTestBase::DXFenceTestBase;
// Obtain pointers to semaphore's API
GET_PFN(device, clCreateSemaphoreWithPropertiesKHR);
GET_PFN(device, clReleaseSemaphoreKHR);
GET_PFN(device, clEnqueueSignalSemaphoresKHR);
GET_PFN(device, clEnqueueWaitSemaphoresKHR);
test_error(!is_import_handle_available(device,
CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR),
"Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between the "
"supported import types");
// Import D3D12 fence into OpenCL
const DirectXFenceWrapper fence(dx_wrapper.getDXDevice());
CLDXSemaphoreWrapper semaphore(device, context, dx_wrapper.getDXDevice());
test_error(semaphore.createSemaphoreFromFence(*fence),
"Could not create semaphore");
cl_int Run() override
{
log_info("Calling d3d12_command_queue->Wait(1)\n"); log_info("Calling d3d12_command_queue->Wait(1)\n");
cl_semaphore_payload_khr semaphore_payload = 1; HRESULT hr = dx_wrapper.getDXCommandQueue()->Wait(fence_wrapper->get(),
HRESULT hr = semaphore_payload);
dx_wrapper.getDXCommandQueue()->Wait(*fence, semaphore_payload);
test_error(FAILED(hr), "Failed to wait on D3D12 fence"); test_error(FAILED(hr), "Failed to wait on D3D12 fence");
log_info("Calling d3d12_command_queue->Signal(2)\n"); log_info("Calling d3d12_command_queue->Signal(2)\n");
hr = dx_wrapper.getDXCommandQueue()->Signal(*fence, semaphore_payload + 1); hr = dx_wrapper.getDXCommandQueue()->Signal(fence_wrapper->get(),
semaphore_payload + 1);
test_error(FAILED(hr), "Failed to signal D3D12 fence"); test_error(FAILED(hr), "Failed to signal D3D12 fence");
log_info("Calling clEnqueueSignalSemaphoresKHR(1)\n"); log_info("Calling clEnqueueSignalSemaphoresKHR(1)\n");
clEventWrapper signal_event; clEventWrapper signal_event;
errcode = clEnqueueSignalSemaphoresKHR( errcode = clEnqueueSignalSemaphoresKHR(queue, 1, &semaphore,
queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &signal_event); &semaphore_payload, 0, nullptr,
&signal_event);
test_error(errcode, "Failed to call clEnqueueSignalSemaphoresKHR"); test_error(errcode, "Failed to call clEnqueueSignalSemaphoresKHR");
log_info("Calling clEnqueueWaitSemaphoresKHR(2)\n"); log_info("Calling clEnqueueWaitSemaphoresKHR(2)\n");
@@ -216,41 +155,52 @@ REGISTER_TEST(test_external_semaphores_cl_dx_interlock)
return TEST_PASS; return TEST_PASS;
} }
};
// Confirm that multiple waits in OpenCL followed by signals in DX12 and waits // Confirm that interlocking waits between OpenCL and DX12 will complete
// in DX12 followed by signals in OpenCL complete successfully // successfully
REGISTER_TEST(test_external_semaphores_multiple_wait_signal) REGISTER_TEST(test_external_semaphores_cl_dx_interlock)
{ {
int errcode = CL_SUCCESS; return MakeAndRunTest<CLDXInterlock>(device, context, queue, num_elements);
const DirectXWrapper dx_wrapper; }
REQUIRE_EXTENSION("cl_khr_external_semaphore"); struct MultipleWaitSignal final : DXFenceTestBase
REQUIRE_EXTENSION("cl_khr_external_semaphore_dx_fence"); {
using DXFenceTestBase::DXFenceTestBase;
// Obtain pointers to semaphore's API ~MultipleWaitSignal() override
GET_PFN(device, clCreateSemaphoreWithPropertiesKHR); {
GET_PFN(device, clReleaseSemaphoreKHR); if (fence_handle_2)
GET_PFN(device, clEnqueueSignalSemaphoresKHR); {
GET_PFN(device, clEnqueueWaitSemaphoresKHR); CloseHandle(fence_handle_2);
fence_handle_2 = nullptr;
}
if (fence_wrapper_2)
{
delete fence_wrapper_2;
fence_wrapper_2 = nullptr;
}
if (semaphore_2)
{
clReleaseSemaphoreKHR(semaphore_2);
semaphore_2 = nullptr;
}
DXFenceTestBase::~DXFenceTestBase();
};
test_error(!is_import_handle_available(device, int SetUp() override
CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR), {
"Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between the " DXFenceTestBase::SetUp();
"supported import types"); fence_wrapper_2 = new DirectXFenceWrapper(dx_wrapper.getDXDevice());
semaphore_2 = createSemaphoreFromFence(fence_wrapper_2->get());
test_assert_error(!!semaphore_2, "Could not create semaphore");
// Import D3D12 fence into OpenCL return TEST_PASS;
const DirectXFenceWrapper fence_1(dx_wrapper.getDXDevice()); }
CLDXSemaphoreWrapper semaphore_1(device, context, dx_wrapper.getDXDevice());
test_error(semaphore_1.createSemaphoreFromFence(*fence_1),
"Could not create semaphore");
const DirectXFenceWrapper fence_2(dx_wrapper.getDXDevice()); cl_int Run() override
CLDXSemaphoreWrapper semaphore_2(device, context, dx_wrapper.getDXDevice()); {
test_error(semaphore_2.createSemaphoreFromFence(*fence_2), const cl_semaphore_khr semaphore_list[] = { semaphore, semaphore_2 };
"Could not create semaphore");
const cl_semaphore_khr semaphore_list[] = { *semaphore_1, *semaphore_2 };
constexpr cl_semaphore_payload_khr semaphore_payload = 1;
cl_semaphore_payload_khr semaphore_payload_list[] = { cl_semaphore_payload_khr semaphore_payload_list[] = {
semaphore_payload, semaphore_payload + 1 semaphore_payload, semaphore_payload + 1
}; };
@@ -263,16 +213,20 @@ REGISTER_TEST(test_external_semaphores_multiple_wait_signal)
test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR"); test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR");
log_info("Calling d3d12_command_queue->Signal()\n"); log_info("Calling d3d12_command_queue->Signal()\n");
HRESULT hr = HRESULT hr = dx_wrapper.getDXCommandQueue()->Signal(
dx_wrapper.getDXCommandQueue()->Signal(*fence_2, semaphore_payload + 1); fence_wrapper_2->get(), semaphore_payload + 1);
test_error(FAILED(hr), "Failed to signal D3D12 fence 2"); test_error(FAILED(hr), "Failed to signal D3D12 fence 2");
hr = dx_wrapper.getDXCommandQueue()->Signal(*fence_1, semaphore_payload); hr = dx_wrapper.getDXCommandQueue()->Signal(fence_wrapper->get(),
semaphore_payload);
test_error(FAILED(hr), "Failed to signal D3D12 fence 1"); test_error(FAILED(hr), "Failed to signal D3D12 fence 1");
log_info("Calling d3d12_command_queue->Wait() with different payloads\n"); log_info(
hr = dx_wrapper.getDXCommandQueue()->Wait(*fence_1, semaphore_payload + 3); "Calling d3d12_command_queue->Wait() with different payloads\n");
hr = dx_wrapper.getDXCommandQueue()->Wait(fence_wrapper->get(),
semaphore_payload + 3);
test_error(FAILED(hr), "Failed to wait on D3D12 fence 1"); test_error(FAILED(hr), "Failed to wait on D3D12 fence 1");
hr = dx_wrapper.getDXCommandQueue()->Wait(*fence_2, semaphore_payload + 2); hr = dx_wrapper.getDXCommandQueue()->Wait(fence_wrapper_2->get(),
semaphore_payload + 2);
test_error(FAILED(hr), "Failed to wait on D3D12 fence 2"); test_error(FAILED(hr), "Failed to wait on D3D12 fence 2");
errcode = clFinish(queue); errcode = clFinish(queue);
@@ -286,29 +240,31 @@ REGISTER_TEST(test_external_semaphores_multiple_wait_signal)
log_info("Calling clEnqueueSignalSemaphoresKHR\n"); log_info("Calling clEnqueueSignalSemaphoresKHR\n");
clEventWrapper signal_event; clEventWrapper signal_event;
errcode = clEnqueueSignalSemaphoresKHR(queue, 2, semaphore_list, errcode = clEnqueueSignalSemaphoresKHR(queue, 2, semaphore_list,
semaphore_payload_list, 0, nullptr, semaphore_payload_list, 0,
&signal_event); nullptr, &signal_event);
test_error(errcode, "Could not call clEnqueueSignalSemaphoresKHR"); test_error(errcode, "Could not call clEnqueueSignalSemaphoresKHR");
// Wait until the GPU has completed commands up to this fence point. // Wait until the GPU has completed commands up to this fence point.
log_info("Waiting for D3D12 command queue completion\n"); log_info("Waiting for D3D12 command queue completion\n");
if ((*fence_1)->GetCompletedValue() < semaphore_payload_list[0]) if (fence_wrapper->get()->GetCompletedValue()
< semaphore_payload_list[0])
{ {
const HANDLE event_handle = const HANDLE event_handle =
CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS); CreateEventEx(nullptr, nullptr, false, EVENT_ALL_ACCESS);
hr = (*fence_1)->SetEventOnCompletion(semaphore_payload_list[0], hr = fence_wrapper->get()->SetEventOnCompletion(
event_handle); semaphore_payload_list[0], event_handle);
test_error(FAILED(hr), test_error(FAILED(hr),
"Failed to set D3D12 fence 1 event on completion"); "Failed to set D3D12 fence 1 event on completion");
WaitForSingleObject(event_handle, INFINITE); WaitForSingleObject(event_handle, INFINITE);
CloseHandle(event_handle); CloseHandle(event_handle);
} }
if ((*fence_2)->GetCompletedValue() < semaphore_payload_list[1]) if (fence_wrapper_2->get()->GetCompletedValue()
< semaphore_payload_list[1])
{ {
const HANDLE event_handle = const HANDLE event_handle =
CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS); CreateEventEx(nullptr, nullptr, false, EVENT_ALL_ACCESS);
hr = (*fence_2)->SetEventOnCompletion(semaphore_payload_list[1], hr = fence_wrapper_2->get()->SetEventOnCompletion(
event_handle); semaphore_payload_list[1], event_handle);
test_error(FAILED(hr), test_error(FAILED(hr),
"Failed to set D3D12 fence 2 event on completion"); "Failed to set D3D12 fence 2 event on completion");
WaitForSingleObject(event_handle, INFINITE); WaitForSingleObject(event_handle, INFINITE);
@@ -322,3 +278,17 @@ REGISTER_TEST(test_external_semaphores_multiple_wait_signal)
return TEST_PASS; return TEST_PASS;
} }
protected:
cl_semaphore_khr semaphore_2 = nullptr;
HANDLE fence_handle_2 = nullptr;
DirectXFenceWrapper *fence_wrapper_2 = nullptr;
};
// Confirm that multiple waits in OpenCL followed by signals in DX12 and waits
// in DX12 followed by signals in OpenCL complete successfully
REGISTER_TEST(test_external_semaphores_multiple_wait_signal)
{
return MakeAndRunTest<MultipleWaitSignal>(device, context, queue,
num_elements);
}

View File

@@ -16,28 +16,16 @@
#include "semaphore_dx_fence_base.h" #include "semaphore_dx_fence_base.h"
// Confirm that a wait followed by a signal in DirectX 12 using an exported struct ExportDXSignal final : DXFenceTestBase
// semaphore will complete successfully
REGISTER_TEST(test_external_semaphores_export_dx_signal)
{ {
int errcode = CL_SUCCESS; using DXFenceTestBase::DXFenceTestBase;
const DirectXWrapper dx_wrapper;
REQUIRE_EXTENSION("cl_khr_external_semaphore");
REQUIRE_EXTENSION("cl_khr_external_semaphore_dx_fence");
// Obtain pointers to semaphore's API
GET_PFN(device, clCreateSemaphoreWithPropertiesKHR);
GET_PFN(device, clReleaseSemaphoreKHR);
GET_PFN(device, clEnqueueSignalSemaphoresKHR);
GET_PFN(device, clEnqueueWaitSemaphoresKHR);
GET_PFN(device, clGetSemaphoreInfoKHR);
GET_PFN(device, clGetSemaphoreHandleForTypeKHR);
int Run() override
{
size_t export_types_size = 0; size_t export_types_size = 0;
errcode = errcode =
clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR, 0, clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR,
nullptr, &export_types_size); 0, nullptr, &export_types_size);
test_error(errcode, "Could not query export semaphore handle types"); test_error(errcode, "Could not query export semaphore handle types");
std::vector<cl_external_semaphore_handle_type_khr> export_types( std::vector<cl_external_semaphore_handle_type_khr> export_types(
export_types_size / sizeof(cl_external_semaphore_handle_type_khr)); export_types_size / sizeof(cl_external_semaphore_handle_type_khr));
@@ -50,14 +38,16 @@ REGISTER_TEST(test_external_semaphores_export_dx_signal)
CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR) CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR)
== export_types.end()) == export_types.end())
{ {
log_info("Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between " log_info(
"Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between "
"the supported export types\n"); "the supported export types\n");
return TEST_FAIL; return TEST_FAIL;
} }
constexpr cl_semaphore_properties_khr sem_props[] = { constexpr cl_semaphore_properties_khr sem_props[] = {
static_cast<cl_semaphore_properties_khr>(CL_SEMAPHORE_TYPE_KHR), static_cast<cl_semaphore_properties_khr>(CL_SEMAPHORE_TYPE_KHR),
static_cast<cl_semaphore_properties_khr>(CL_SEMAPHORE_TYPE_BINARY_KHR), static_cast<cl_semaphore_properties_khr>(
CL_SEMAPHORE_TYPE_BINARY_KHR),
static_cast<cl_semaphore_properties_khr>( static_cast<cl_semaphore_properties_khr>(
CL_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR), CL_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR),
static_cast<cl_semaphore_properties_khr>( static_cast<cl_semaphore_properties_khr>(
@@ -66,37 +56,37 @@ REGISTER_TEST(test_external_semaphores_export_dx_signal)
CL_SEMAPHORE_EXPORT_HANDLE_TYPES_LIST_END_KHR), CL_SEMAPHORE_EXPORT_HANDLE_TYPES_LIST_END_KHR),
0 0
}; };
cl_semaphore_khr semaphore = cl_semaphore_khr exportable_semaphore =
clCreateSemaphoreWithPropertiesKHR(context, sem_props, &errcode); clCreateSemaphoreWithPropertiesKHR(context, sem_props, &errcode);
test_error(errcode, "Could not create semaphore"); test_error(errcode, "Could not create semaphore");
cl_bool is_exportable = CL_FALSE; cl_bool is_exportable = CL_FALSE;
errcode = errcode = clGetSemaphoreInfoKHR(
clGetSemaphoreInfoKHR(semaphore, CL_SEMAPHORE_EXPORTABLE_KHR, exportable_semaphore, CL_SEMAPHORE_EXPORTABLE_KHR,
sizeof(is_exportable), &is_exportable, nullptr); sizeof(is_exportable), &is_exportable, nullptr);
test_error(errcode, "Could not get semaphore info"); test_error(errcode, "Could not get semaphore info");
test_error(!is_exportable, "Semaphore is not exportable"); test_error(!is_exportable, "Semaphore is not exportable");
log_info("Calling clEnqueueWaitSemaphoresKHR\n"); log_info("Calling clEnqueueWaitSemaphoresKHR\n");
constexpr cl_semaphore_payload_khr semaphore_payload = 1;
clEventWrapper wait_event; clEventWrapper wait_event;
errcode = clEnqueueWaitSemaphoresKHR( errcode = clEnqueueWaitSemaphoresKHR(queue, 1, &exportable_semaphore,
queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event); &semaphore_payload, 0, nullptr,
&wait_event);
test_error(errcode, "Failed to wait semaphore"); test_error(errcode, "Failed to wait semaphore");
HANDLE semaphore_handle = nullptr; HANDLE semaphore_handle = nullptr;
errcode = clGetSemaphoreHandleForTypeKHR( errcode = clGetSemaphoreHandleForTypeKHR(
semaphore, device, CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR, exportable_semaphore, device, CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR,
sizeof(semaphore_handle), &semaphore_handle, nullptr); sizeof(semaphore_handle), &semaphore_handle, nullptr);
test_error(errcode, "Could not get semaphore handle"); test_error(errcode, "Could not get semaphore handle");
ID3D12Fence *fence = nullptr; ID3D12Fence *exported_fence = nullptr;
errcode = dx_wrapper.getDXDevice()->OpenSharedHandle(semaphore_handle, errcode = dx_wrapper.getDXDevice()->OpenSharedHandle(
IID_PPV_ARGS(&fence)); semaphore_handle, IID_PPV_ARGS(&exported_fence));
test_error(errcode, "Could not open semaphore handle"); test_error(errcode, "Could not open semaphore handle");
log_info("Calling fence->Signal()\n"); log_info("Calling fence->Signal()\n");
const HRESULT hr = fence->Signal(semaphore_payload); const HRESULT hr = exported_fence->Signal(semaphore_payload);
test_error(FAILED(hr), "Failed to signal D3D12 fence"); test_error(FAILED(hr), "Failed to signal D3D12 fence");
errcode = clFinish(queue); errcode = clFinish(queue);
@@ -106,34 +96,31 @@ REGISTER_TEST(test_external_semaphores_export_dx_signal)
// Release resources // Release resources
CloseHandle(semaphore_handle); CloseHandle(semaphore_handle);
test_error(clReleaseSemaphoreKHR(semaphore), "Could not release semaphore"); test_error(clReleaseSemaphoreKHR(exportable_semaphore),
fence->Release(); "Could not release semaphore");
exported_fence->Release();
return TEST_PASS; return TEST_PASS;
} }
};
// Confirm that a signal in OpenCL followed by a wait in DirectX 12 using an // Confirm that a wait followed by a signal in DirectX 12 using an exported
// exported semaphore will complete successfully // semaphore will complete successfully
REGISTER_TEST(test_external_semaphores_export_dx_wait) REGISTER_TEST(test_external_semaphores_export_dx_signal)
{ {
int errcode = CL_SUCCESS; return MakeAndRunTest<ExportDXSignal>(device, context, queue, num_elements);
const DirectXWrapper dx_wrapper; }
REQUIRE_EXTENSION("cl_khr_external_semaphore"); struct ExportDXWait final : DXFenceTestBase
REQUIRE_EXTENSION("cl_khr_external_semaphore_dx_fence"); {
using DXFenceTestBase::DXFenceTestBase;
// Obtain pointers to semaphore's API
GET_PFN(device, clCreateSemaphoreWithPropertiesKHR);
GET_PFN(device, clReleaseSemaphoreKHR);
GET_PFN(device, clEnqueueSignalSemaphoresKHR);
GET_PFN(device, clEnqueueWaitSemaphoresKHR);
GET_PFN(device, clGetSemaphoreInfoKHR);
GET_PFN(device, clGetSemaphoreHandleForTypeKHR);
int Run() override
{
size_t export_types_size = 0; size_t export_types_size = 0;
errcode = errcode =
clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR, 0, clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR,
nullptr, &export_types_size); 0, nullptr, &export_types_size);
test_error(errcode, "Could not query export semaphore handle types"); test_error(errcode, "Could not query export semaphore handle types");
std::vector<cl_external_semaphore_handle_type_khr> export_types( std::vector<cl_external_semaphore_handle_type_khr> export_types(
export_types_size / sizeof(cl_external_semaphore_handle_type_khr)); export_types_size / sizeof(cl_external_semaphore_handle_type_khr));
@@ -146,14 +133,16 @@ REGISTER_TEST(test_external_semaphores_export_dx_wait)
CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR) CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR)
== export_types.end()) == export_types.end())
{ {
log_info("Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between " log_info(
"Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between "
"the supported export types\n"); "the supported export types\n");
return TEST_FAIL; return TEST_FAIL;
} }
constexpr cl_semaphore_properties_khr sem_props[] = { constexpr cl_semaphore_properties_khr sem_props[] = {
static_cast<cl_semaphore_properties_khr>(CL_SEMAPHORE_TYPE_KHR), static_cast<cl_semaphore_properties_khr>(CL_SEMAPHORE_TYPE_KHR),
static_cast<cl_semaphore_properties_khr>(CL_SEMAPHORE_TYPE_BINARY_KHR), static_cast<cl_semaphore_properties_khr>(
CL_SEMAPHORE_TYPE_BINARY_KHR),
static_cast<cl_semaphore_properties_khr>( static_cast<cl_semaphore_properties_khr>(
CL_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR), CL_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR),
static_cast<cl_semaphore_properties_khr>( static_cast<cl_semaphore_properties_khr>(
@@ -162,13 +151,13 @@ REGISTER_TEST(test_external_semaphores_export_dx_wait)
CL_SEMAPHORE_EXPORT_HANDLE_TYPES_LIST_END_KHR), CL_SEMAPHORE_EXPORT_HANDLE_TYPES_LIST_END_KHR),
0 0
}; };
cl_semaphore_khr semaphore = cl_semaphore_khr exportable_semaphore =
clCreateSemaphoreWithPropertiesKHR(context, sem_props, &errcode); clCreateSemaphoreWithPropertiesKHR(context, sem_props, &errcode);
test_error(errcode, "Could not create semaphore"); test_error(errcode, "Could not create semaphore");
cl_bool is_exportable = CL_FALSE; cl_bool is_exportable = CL_FALSE;
errcode = errcode = clGetSemaphoreInfoKHR(
clGetSemaphoreInfoKHR(semaphore, CL_SEMAPHORE_EXPORTABLE_KHR, exportable_semaphore, CL_SEMAPHORE_EXPORTABLE_KHR,
sizeof(is_exportable), &is_exportable, nullptr); sizeof(is_exportable), &is_exportable, nullptr);
test_error(errcode, "Could not get semaphore info"); test_error(errcode, "Could not get semaphore info");
test_error(!is_exportable, "Semaphore is not exportable"); test_error(!is_exportable, "Semaphore is not exportable");
@@ -176,31 +165,33 @@ REGISTER_TEST(test_external_semaphores_export_dx_wait)
log_info("Calling clEnqueueSignalSemaphoresKHR\n"); log_info("Calling clEnqueueSignalSemaphoresKHR\n");
constexpr cl_semaphore_payload_khr semaphore_payload = 1; constexpr cl_semaphore_payload_khr semaphore_payload = 1;
clEventWrapper signal_event; clEventWrapper signal_event;
errcode = clEnqueueSignalSemaphoresKHR( errcode = clEnqueueSignalSemaphoresKHR(queue, 1, &exportable_semaphore,
queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &signal_event); &semaphore_payload, 0, nullptr,
&signal_event);
test_error(errcode, "Failed to signal semaphore"); test_error(errcode, "Failed to signal semaphore");
HANDLE semaphore_handle = nullptr; HANDLE semaphore_handle = nullptr;
errcode = clGetSemaphoreHandleForTypeKHR( errcode = clGetSemaphoreHandleForTypeKHR(
semaphore, device, CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR, exportable_semaphore, device, CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR,
sizeof(semaphore_handle), &semaphore_handle, nullptr); sizeof(semaphore_handle), &semaphore_handle, nullptr);
test_error(errcode, "Could not get semaphore handle"); test_error(errcode, "Could not get semaphore handle");
ID3D12Fence *fence = nullptr; ID3D12Fence *exported_fence = nullptr;
errcode = dx_wrapper.getDXDevice()->OpenSharedHandle(semaphore_handle, errcode = dx_wrapper.getDXDevice()->OpenSharedHandle(
IID_PPV_ARGS(&fence)); semaphore_handle, IID_PPV_ARGS(&exported_fence));
test_error(errcode, "Could not open semaphore handle"); test_error(errcode, "Could not open semaphore handle");
log_info("Calling dx_wrapper.get_d3d12_command_queue()->Wait()\n"); log_info("Calling dx_wrapper.get_d3d12_command_queue()->Wait()\n");
HRESULT hr = dx_wrapper.getDXCommandQueue()->Wait(fence, semaphore_payload); HRESULT hr = dx_wrapper.getDXCommandQueue()->Wait(exported_fence,
semaphore_payload);
test_error(FAILED(hr), "Failed to wait on D3D12 fence"); test_error(FAILED(hr), "Failed to wait on D3D12 fence");
log_info("Calling WaitForSingleObject\n"); log_info("Calling WaitForSingleObject\n");
if (fence->GetCompletedValue() < semaphore_payload) if (exported_fence->GetCompletedValue() < semaphore_payload)
{ {
const HANDLE event = const HANDLE event =
CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS); CreateEventEx(nullptr, nullptr, false, EVENT_ALL_ACCESS);
hr = fence->SetEventOnCompletion(semaphore_payload, event); hr = exported_fence->SetEventOnCompletion(semaphore_payload, event);
test_error(FAILED(hr), "Failed to set event on completion"); test_error(FAILED(hr), "Failed to set event on completion");
WaitForSingleObject(event, INFINITE); WaitForSingleObject(event, INFINITE);
CloseHandle(event); CloseHandle(event);
@@ -213,8 +204,17 @@ REGISTER_TEST(test_external_semaphores_export_dx_wait)
// Release resources // Release resources
CloseHandle(semaphore_handle); CloseHandle(semaphore_handle);
test_error(clReleaseSemaphoreKHR(semaphore), "Could not release semaphore"); test_error(clReleaseSemaphoreKHR(exportable_semaphore),
fence->Release(); "Could not release semaphore");
exported_fence->Release();
return TEST_PASS; return TEST_PASS;
} }
};
// Confirm that a signal in OpenCL followed by a wait in DirectX 12 using an
// exported semaphore will complete successfully
REGISTER_TEST(test_external_semaphores_export_dx_wait)
{
return MakeAndRunTest<ExportDXWait>(device, context, queue, num_elements);
}

View File

@@ -16,32 +16,12 @@
#include "semaphore_dx_fence_base.h" #include "semaphore_dx_fence_base.h"
// Confirm that a wait without a semaphore payload list will return struct DXFenceNegativeWait final : DXFenceTestBase
// CL_INVALID_VALUE
REGISTER_TEST(test_external_semaphores_dx_fence_negative_wait)
{ {
int errcode = CL_SUCCESS; using DXFenceTestBase::DXFenceTestBase;
const DirectXWrapper dx_wrapper;
REQUIRE_EXTENSION("cl_khr_external_semaphore");
REQUIRE_EXTENSION("cl_khr_external_semaphore_dx_fence");
// Obtain pointers to semaphore's API
GET_PFN(device, clCreateSemaphoreWithPropertiesKHR);
GET_PFN(device, clReleaseSemaphoreKHR);
GET_PFN(device, clEnqueueWaitSemaphoresKHR);
test_error(!is_import_handle_available(device,
CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR),
"Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between the "
"supported import types");
// Import D3D12 fence into OpenCL
const DirectXFenceWrapper fence(dx_wrapper.getDXDevice());
CLDXSemaphoreWrapper semaphore(device, context, dx_wrapper.getDXDevice());
test_error(semaphore.createSemaphoreFromFence(*fence),
"Could not create semaphore");
int Run() override
{
log_info("Calling clEnqueueWaitSemaphoresKHR\n"); log_info("Calling clEnqueueWaitSemaphoresKHR\n");
errcode = clEnqueueWaitSemaphoresKHR(queue, 1, &semaphore, nullptr, 0, errcode = clEnqueueWaitSemaphoresKHR(queue, 1, &semaphore, nullptr, 0,
nullptr, nullptr); nullptr, nullptr);
@@ -51,33 +31,22 @@ REGISTER_TEST(test_external_semaphores_dx_fence_negative_wait)
return TEST_PASS; return TEST_PASS;
} }
};
// Confirm that a signal without a semaphore payload list will return // Confirm that a wait without a semaphore payload list will return
// CL_INVALID_VALUE // CL_INVALID_VALUE
REGISTER_TEST(test_external_semaphores_dx_fence_negative_signal) REGISTER_TEST(test_external_semaphores_dx_fence_negative_wait)
{ {
int errcode = CL_SUCCESS; return MakeAndRunTest<DXFenceNegativeWait>(device, context, queue,
const DirectXWrapper dx_wrapper; num_elements);
}
REQUIRE_EXTENSION("cl_khr_external_semaphore"); struct DXFenceNegativeSignal final : DXFenceTestBase
REQUIRE_EXTENSION("cl_khr_external_semaphore_dx_fence"); {
using DXFenceTestBase::DXFenceTestBase;
// Obtain pointers to semaphore's API
GET_PFN(device, clCreateSemaphoreWithPropertiesKHR);
GET_PFN(device, clReleaseSemaphoreKHR);
GET_PFN(device, clEnqueueSignalSemaphoresKHR);
test_error(!is_import_handle_available(device,
CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR),
"Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between the "
"supported import types");
// Import D3D12 fence into OpenCL
const DirectXFenceWrapper fence(dx_wrapper.getDXDevice());
CLDXSemaphoreWrapper semaphore(device, context, dx_wrapper.getDXDevice());
test_error(semaphore.createSemaphoreFromFence(*fence),
"Could not create semaphore");
int Run() override
{
log_info("Calling clEnqueueWaitSemaphoresKHR\n"); log_info("Calling clEnqueueWaitSemaphoresKHR\n");
errcode = clEnqueueSignalSemaphoresKHR(queue, 1, &semaphore, nullptr, 0, errcode = clEnqueueSignalSemaphoresKHR(queue, 1, &semaphore, nullptr, 0,
nullptr, nullptr); nullptr, nullptr);
@@ -87,3 +56,12 @@ REGISTER_TEST(test_external_semaphores_dx_fence_negative_signal)
return TEST_PASS; return TEST_PASS;
} }
};
// Confirm that a signal without a semaphore payload list will return
// CL_INVALID_VALUE
REGISTER_TEST(test_external_semaphores_dx_fence_negative_signal)
{
return MakeAndRunTest<DXFenceNegativeSignal>(device, context, queue,
num_elements);
}

View File

@@ -16,39 +16,19 @@
#include "semaphore_dx_fence_base.h" #include "semaphore_dx_fence_base.h"
// Confirm that the CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR property is in the struct DXFenceQueryProperties final : DXFenceTestBase
// properties returned by clGetSemaphoreInfo
REGISTER_TEST(test_external_semaphores_dx_fence_query_properties)
{ {
int errcode = CL_SUCCESS; using DXFenceTestBase::DXFenceTestBase;
const DirectXWrapper dx_wrapper;
REQUIRE_EXTENSION("cl_khr_external_semaphore");
REQUIRE_EXTENSION("cl_khr_external_semaphore_dx_fence");
// Obtain pointers to semaphore's API
GET_PFN(device, clCreateSemaphoreWithPropertiesKHR);
GET_PFN(device, clReleaseSemaphoreKHR);
GET_PFN(device, clGetSemaphoreInfoKHR);
test_error(!is_import_handle_available(device,
CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR),
"Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between the "
"supported import types");
// Import D3D12 fence into OpenCL
const DirectXFenceWrapper fence(dx_wrapper.getDXDevice());
CLDXSemaphoreWrapper semaphore(device, context, dx_wrapper.getDXDevice());
test_error(semaphore.createSemaphoreFromFence(*fence),
"Could not create semaphore");
int Run() override
{
size_t properties_size_bytes = 0; size_t properties_size_bytes = 0;
errcode = clGetSemaphoreInfoKHR(*semaphore, CL_SEMAPHORE_PROPERTIES_KHR, 0, errcode = clGetSemaphoreInfoKHR(semaphore, CL_SEMAPHORE_PROPERTIES_KHR,
nullptr, &properties_size_bytes); 0, nullptr, &properties_size_bytes);
test_error(errcode, "Could not get semaphore info"); test_error(errcode, "Could not get semaphore info");
std::vector<cl_semaphore_properties_khr> semaphore_properties( std::vector<cl_semaphore_properties_khr> semaphore_properties(
properties_size_bytes / sizeof(cl_semaphore_properties_khr)); properties_size_bytes / sizeof(cl_semaphore_properties_khr));
errcode = clGetSemaphoreInfoKHR(*semaphore, CL_SEMAPHORE_PROPERTIES_KHR, errcode = clGetSemaphoreInfoKHR(semaphore, CL_SEMAPHORE_PROPERTIES_KHR,
properties_size_bytes, properties_size_bytes,
semaphore_properties.data(), nullptr); semaphore_properties.data(), nullptr);
test_error(errcode, "Could not get semaphore info"); test_error(errcode, "Could not get semaphore info");
@@ -58,12 +38,21 @@ REGISTER_TEST(test_external_semaphores_dx_fence_query_properties)
if (semaphore_properties[i] == CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR if (semaphore_properties[i] == CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR
&& semaphore_properties[i + 1] && semaphore_properties[i + 1]
== reinterpret_cast<cl_semaphore_properties_khr>( == reinterpret_cast<cl_semaphore_properties_khr>(
semaphore.getHandle())) fence_handle))
{ {
return TEST_PASS; return TEST_PASS;
} }
} }
log_error( log_error("Failed to find the dx fence handle type in the semaphore "
"Failed to find the dx fence handle type in the semaphore properties"); "properties");
return TEST_FAIL; return TEST_FAIL;
} }
};
// Confirm that the CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR property is in the
// properties returned by clGetSemaphoreInfo
REGISTER_TEST(test_external_semaphores_dx_fence_query_properties)
{
return MakeAndRunTest<DXFenceQueryProperties>(device, context, queue,
num_elements);
}

View File

@@ -23,6 +23,7 @@
#include "harness/deviceInfo.h" #include "harness/deviceInfo.h"
#include "harness/testHarness.h" #include "harness/testHarness.h"
#include "harness/typeWrappers.h" #include "harness/typeWrappers.h"
#include "harness/extensionHelpers.h"
struct SemaphoreBase struct SemaphoreBase
{ {
@@ -37,27 +38,15 @@ struct SemaphoreBase
test_error(error, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed"); test_error(error, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed");
// If it is supported get the addresses of all the APIs here. // If it is supported get the addresses of all the APIs here.
// clang-format off GET_FUNCTION_EXTENSION_ADDRESS(device,
#define GET_EXTENSION_ADDRESS(FUNC) \ clCreateSemaphoreWithPropertiesKHR);
FUNC = reinterpret_cast<FUNC##_fn>( \ GET_FUNCTION_EXTENSION_ADDRESS(device, clEnqueueSignalSemaphoresKHR);
clGetExtensionFunctionAddressForPlatform(platform, #FUNC)); \ GET_FUNCTION_EXTENSION_ADDRESS(device, clEnqueueWaitSemaphoresKHR);
if (FUNC == nullptr) \ GET_FUNCTION_EXTENSION_ADDRESS(device, clReleaseSemaphoreKHR);
{ \ GET_FUNCTION_EXTENSION_ADDRESS(device, clGetSemaphoreInfoKHR);
log_error("ERROR: clGetExtensionFunctionAddressForPlatform failed" \ GET_FUNCTION_EXTENSION_ADDRESS(device, clRetainSemaphoreKHR);
" with " #FUNC "\n"); \ GET_FUNCTION_EXTENSION_ADDRESS(device, clGetSemaphoreHandleForTypeKHR);
return TEST_FAIL; \
}
// clang-format on
GET_EXTENSION_ADDRESS(clCreateSemaphoreWithPropertiesKHR);
GET_EXTENSION_ADDRESS(clEnqueueSignalSemaphoresKHR);
GET_EXTENSION_ADDRESS(clEnqueueWaitSemaphoresKHR);
GET_EXTENSION_ADDRESS(clReleaseSemaphoreKHR);
GET_EXTENSION_ADDRESS(clGetSemaphoreInfoKHR);
GET_EXTENSION_ADDRESS(clRetainSemaphoreKHR);
GET_EXTENSION_ADDRESS(clGetSemaphoreHandleForTypeKHR);
#undef GET_EXTENSION_ADDRESS
return CL_SUCCESS; return CL_SUCCESS;
} }