diff --git a/test_common/harness/extensionHelpers.h b/test_common/harness/extensionHelpers.h index e98f67c2..abaa0ba6 100644 --- a/test_common/harness/extensionHelpers.h +++ b/test_common/harness/extensionHelpers.h @@ -32,5 +32,15 @@ } \ } while (false) +#define GET_FUNCTION_EXTENSION_ADDRESS(device, FUNC) \ + FUNC = \ + reinterpret_cast(clGetExtensionFunctionAddressForPlatform( \ + getPlatformFromDevice(device), #FUNC)); \ + if (FUNC == nullptr) \ + { \ + log_error("ERROR: clGetExtensionFunctionAddressForPlatform failed" \ + " with " #FUNC "\n"); \ + return TEST_FAIL; \ + } #endif // _extensionHelpers_h diff --git a/test_conformance/common/directx_wrapper/directx_wrapper.hpp b/test_conformance/common/directx_wrapper/directx_wrapper.hpp index dec85b78..fb758880 100644 --- a/test_conformance/common/directx_wrapper/directx_wrapper.hpp +++ b/test_conformance/common/directx_wrapper/directx_wrapper.hpp @@ -26,9 +26,9 @@ class DirectXWrapper { public: DirectXWrapper(); - ID3D12Device* getDXDevice() const; - ID3D12CommandQueue* getDXCommandQueue() const; - ID3D12CommandAllocator* getDXCommandAllocator() const; + [[nodiscard]] ID3D12Device* getDXDevice() const; + [[nodiscard]] ID3D12CommandQueue* getDXCommandQueue() const; + [[nodiscard]] ID3D12CommandAllocator* getDXCommandAllocator() const; protected: ComPtr dx_device = nullptr; @@ -39,7 +39,7 @@ protected: class DirectXFenceWrapper { public: DirectXFenceWrapper(ID3D12Device* dx_device); - ID3D12Fence* operator*() const { return dx_fence.Get(); } + [[nodiscard]] ID3D12Fence* get() const { return dx_fence.Get(); } private: ComPtr dx_fence = nullptr; diff --git a/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/main.cpp b/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/main.cpp index 85c8fc7f..8a0de351 100644 --- a/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/main.cpp +++ b/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/main.cpp @@ -17,6 +17,7 @@ int main(int argc, const char *argv[]) { - return runTestHarness(argc, argv, test_registry::getInstance().num_tests(), - test_registry::getInstance().definitions(), false, 0); + return runTestHarness( + argc, argv, static_cast(test_registry::getInstance().num_tests()), + test_registry::getInstance().definitions(), false, 0); } \ No newline at end of file diff --git a/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/semaphore_dx_fence_base.h b/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/semaphore_dx_fence_base.h index f8ccb570..31488d9d 100644 --- a/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/semaphore_dx_fence_base.h +++ b/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/semaphore_dx_fence_base.h @@ -21,23 +21,118 @@ #include "harness/errorHelpers.h" #include "directx_wrapper.hpp" -class CLDXSemaphoreWrapper { -public: - CLDXSemaphoreWrapper(cl_device_id device, cl_context context, - ID3D12Device* dx_device) - : device(device), context(context), dx_device(dx_device){}; - - int createSemaphoreFromFence(ID3D12Fence* fence) +struct DXFenceTestBase +{ + DXFenceTestBase(cl_device_id device, cl_context context, + cl_command_queue queue, cl_int num_elems) + : device(device), context(context), queue(queue), num_elems(num_elems) + {} + virtual ~DXFenceTestBase() { - cl_int errcode = CL_SUCCESS; + if (fence_handle) + { + CloseHandle(fence_handle); + fence_handle = nullptr; + } + if (fence_wrapper) + { + delete fence_wrapper; + fence_wrapper = nullptr; + } + if (semaphore) + { + clReleaseSemaphoreKHR(semaphore); + semaphore = nullptr; + } + }; - GET_PFN(device, clCreateSemaphoreWithPropertiesKHR); + virtual int SetUp() + { + REQUIRE_EXTENSION("cl_khr_external_semaphore"); + REQUIRE_EXTENSION("cl_khr_external_semaphore_dx_fence"); - const HRESULT hr = dx_device->CreateSharedHandle( - fence, nullptr, GENERIC_ALL, nullptr, &fence_handle); - test_error(FAILED(hr), "Failed to get shared handle from D3D12 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); - cl_semaphore_properties_khr sem_props[] = { + 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) + { + size_t import_types_size = 0; + errcode = + clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR, + 0, nullptr, &import_types_size); + if (errcode != CL_SUCCESS) + { + log_error("Could not query import semaphore handle types"); + return false; + } + std::vector import_types( + import_types_size / sizeof(cl_external_semaphore_handle_type_khr)); + errcode = + clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR, + import_types_size, import_types.data(), nullptr); + if (errcode != CL_SUCCESS) + { + log_error("Could not query import semaphore handle types"); + return false; + } + + return std::find(import_types.begin(), import_types.end(), handle_type) + != 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_TYPE_KHR), static_cast( CL_SEMAPHORE_TYPE_BINARY_KHR), @@ -45,73 +140,30 @@ public: CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR), reinterpret_cast(fence_handle), 0 }; - semaphore = + cl_semaphore_khr tmp_semaphore = clCreateSemaphoreWithPropertiesKHR(context, sem_props, &errcode); - test_error(errcode, "Could not create semaphore"); + if (errcode != CL_SUCCESS) return nullptr; - return CL_SUCCESS; - } - - ~CLDXSemaphoreWrapper() - { - releaseSemaphore(); - if (fence_handle) - { - CloseHandle(fence_handle); - } - }; - - 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 fence; - HANDLE fence_handle; - cl_device_id device; - cl_context context; - ComPtr dx_device; - - int releaseSemaphore() const - { - GET_PFN(device, clReleaseSemaphoreKHR); - - if (semaphore) - { - clReleaseSemaphoreKHR(semaphore); - } - - return CL_SUCCESS; + return tmp_semaphore; } }; -static bool -is_import_handle_available(cl_device_id device, - const cl_external_memory_handle_type_khr handle_type) +template +int MakeAndRunTest(cl_device_id device, cl_context context, + cl_command_queue queue, cl_int nelems) { - int errcode = CL_SUCCESS; - size_t import_types_size = 0; - errcode = - clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR, 0, - nullptr, &import_types_size); - if (errcode != CL_SUCCESS) + cl_int status = TEST_PASS; + try { - log_error("Could not query import semaphore handle types"); - return false; - } - std::vector import_types( - import_types_size / sizeof(cl_external_semaphore_handle_type_khr)); - errcode = - clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR, - import_types_size, import_types.data(), nullptr); - if (errcode != CL_SUCCESS) + 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("Could not query import semaphore handle types"); - return false; + log_error("%s", e.what()); + return TEST_FAIL; } - return std::find(import_types.begin(), import_types.end(), handle_type) - != import_types.end(); + return status; } \ No newline at end of file diff --git a/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence.cpp b/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence.cpp index 569fb204..db303bf6 100644 --- a/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence.cpp +++ b/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence.cpp @@ -16,309 +16,279 @@ #include "semaphore_dx_fence_base.h" +struct SignalWait final : DXFenceTestBase +{ + using DXFenceTestBase::DXFenceTestBase; + + cl_int Run() override + { + log_info("Calling clEnqueueSignalSemaphoresKHR\n"); + clEventWrapper signal_event; + errcode = clEnqueueSignalSemaphoresKHR(queue, 1, &semaphore, + &semaphore_payload, 0, nullptr, + &signal_event); + test_error(errcode, "Failed to signal semaphore"); + + log_info("Calling clEnqueueWaitSemaphoresKHR\n"); + clEventWrapper wait_event; + errcode = clEnqueueWaitSemaphoresKHR( + queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event); + test_error(errcode, "Failed to wait semaphore"); + + errcode = clFinish(queue); + test_error(errcode, "Could not finish queue"); + + // Verify that the events completed. + test_assert_event_complete(signal_event); + test_assert_event_complete(wait_event); + + return TEST_PASS; + } +}; + // Confirm that a signal followed by a wait in OpenCL will complete successfully REGISTER_TEST(test_external_semaphores_signal_wait) { - int errcode = CL_SUCCESS; - 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"); - - log_info("Calling clEnqueueSignalSemaphoresKHR\n"); - constexpr cl_semaphore_payload_khr semaphore_payload = 1; - clEventWrapper signal_event; - errcode = clEnqueueSignalSemaphoresKHR( - queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &signal_event); - test_error(errcode, "Failed to signal semaphore"); - - log_info("Calling clEnqueueWaitSemaphoresKHR\n"); - clEventWrapper wait_event; - errcode = clEnqueueWaitSemaphoresKHR( - queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event); - test_error(errcode, "Failed to wait semaphore"); - - errcode = clFinish(queue); - test_error(errcode, "Could not finish queue"); - - // Verify that the events completed. - test_assert_event_complete(signal_event); - test_assert_event_complete(wait_event); - - return TEST_PASS; + return MakeAndRunTest(device, context, queue, num_elements); } +struct SignalDXCPU final : DXFenceTestBase +{ + using DXFenceTestBase::DXFenceTestBase; + + cl_int Run() override + { + log_info("Calling clEnqueueWaitSemaphoresKHR\n"); + clEventWrapper wait_event; + errcode = clEnqueueWaitSemaphoresKHR( + queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event); + test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR"); + + log_info("Calling d3d12_fence->Signal()\n"); + const HRESULT hr = fence_wrapper->get()->Signal(semaphore_payload); + test_error(FAILED(hr), "Failed to signal D3D12 fence"); + + errcode = clFinish(queue); + test_error(errcode, "Could not finish queue"); + + test_assert_event_complete(wait_event); + + return TEST_PASS; + } +}; + // Confirm that a wait in OpenCL followed by a CPU signal in DX12 will complete // successfully REGISTER_TEST(test_external_semaphores_signal_dx_cpu) { - int errcode = CL_SUCCESS; - 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"); - - log_info("Calling clEnqueueWaitSemaphoresKHR\n"); - constexpr cl_semaphore_payload_khr semaphore_payload = 1; - clEventWrapper wait_event; - errcode = clEnqueueWaitSemaphoresKHR( - queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event); - test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR"); - - log_info("Calling d3d12_fence->Signal()\n"); - const HRESULT hr = (*fence)->Signal(semaphore_payload); - test_error(FAILED(hr), "Failed to signal D3D12 fence"); - - errcode = clFinish(queue); - test_error(errcode, "Could not finish queue"); - - test_assert_event_complete(wait_event); - - return TEST_PASS; + return MakeAndRunTest(device, context, queue, num_elements); } +struct SignalDXGPU final : DXFenceTestBase +{ + using DXFenceTestBase::DXFenceTestBase; + + cl_int Run() override + { + log_info("Calling clEnqueueWaitSemaphoresKHR\n"); + clEventWrapper wait_event; + errcode = clEnqueueWaitSemaphoresKHR( + queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event); + test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR"); + + log_info("Calling d3d12_command_queue->Signal()\n"); + const HRESULT hr = dx_wrapper.getDXCommandQueue()->Signal( + fence_wrapper->get(), semaphore_payload); + test_error(FAILED(hr), "Failed to signal D3D12 fence"); + + errcode = clFinish(queue); + test_error(errcode, "Could not finish queue"); + + test_assert_event_complete(wait_event); + + return TEST_PASS; + } +}; + // Confirm that a wait in OpenCL followed by a GPU signal in DX12 will complete // successfully REGISTER_TEST(test_external_semaphores_signal_dx_gpu) { - int errcode = CL_SUCCESS; - 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"); - - log_info("Calling clEnqueueWaitSemaphoresKHR\n"); - constexpr cl_semaphore_payload_khr semaphore_payload = 1; - clEventWrapper wait_event; - errcode = clEnqueueWaitSemaphoresKHR( - queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event); - test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR"); - - log_info("Calling d3d12_command_queue->Signal()\n"); - const HRESULT hr = - dx_wrapper.getDXCommandQueue()->Signal(*fence, semaphore_payload); - test_error(FAILED(hr), "Failed to signal D3D12 fence"); - - errcode = clFinish(queue); - test_error(errcode, "Could not finish queue"); - - test_assert_event_complete(wait_event); - - return TEST_PASS; + return MakeAndRunTest(device, context, queue, num_elements); } +struct CLDXInterlock final : DXFenceTestBase +{ + using DXFenceTestBase::DXFenceTestBase; + + cl_int Run() override + { + log_info("Calling d3d12_command_queue->Wait(1)\n"); + HRESULT hr = dx_wrapper.getDXCommandQueue()->Wait(fence_wrapper->get(), + semaphore_payload); + test_error(FAILED(hr), "Failed to wait on D3D12 fence"); + + log_info("Calling d3d12_command_queue->Signal(2)\n"); + hr = dx_wrapper.getDXCommandQueue()->Signal(fence_wrapper->get(), + semaphore_payload + 1); + test_error(FAILED(hr), "Failed to signal D3D12 fence"); + + log_info("Calling clEnqueueSignalSemaphoresKHR(1)\n"); + clEventWrapper signal_event; + errcode = clEnqueueSignalSemaphoresKHR(queue, 1, &semaphore, + &semaphore_payload, 0, nullptr, + &signal_event); + test_error(errcode, "Failed to call clEnqueueSignalSemaphoresKHR"); + + log_info("Calling clEnqueueWaitSemaphoresKHR(2)\n"); + semaphore_payload += 1; + clEventWrapper wait_event; + errcode = clEnqueueWaitSemaphoresKHR( + queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event); + test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR"); + + errcode = clFinish(queue); + test_error(errcode, "Could not finish queue"); + + test_assert_event_complete(wait_event); + test_assert_event_complete(signal_event); + + return TEST_PASS; + } +}; + // Confirm that interlocking waits between OpenCL and DX12 will complete // successfully REGISTER_TEST(test_external_semaphores_cl_dx_interlock) { - int errcode = CL_SUCCESS; - 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"); - - log_info("Calling d3d12_command_queue->Wait(1)\n"); - cl_semaphore_payload_khr semaphore_payload = 1; - HRESULT hr = - dx_wrapper.getDXCommandQueue()->Wait(*fence, semaphore_payload); - test_error(FAILED(hr), "Failed to wait on D3D12 fence"); - - log_info("Calling d3d12_command_queue->Signal(2)\n"); - hr = dx_wrapper.getDXCommandQueue()->Signal(*fence, semaphore_payload + 1); - test_error(FAILED(hr), "Failed to signal D3D12 fence"); - - log_info("Calling clEnqueueSignalSemaphoresKHR(1)\n"); - clEventWrapper signal_event; - errcode = clEnqueueSignalSemaphoresKHR( - queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &signal_event); - test_error(errcode, "Failed to call clEnqueueSignalSemaphoresKHR"); - - log_info("Calling clEnqueueWaitSemaphoresKHR(2)\n"); - semaphore_payload += 1; - clEventWrapper wait_event; - errcode = clEnqueueWaitSemaphoresKHR( - queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event); - test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR"); - - errcode = clFinish(queue); - test_error(errcode, "Could not finish queue"); - - test_assert_event_complete(wait_event); - test_assert_event_complete(signal_event); - - return TEST_PASS; + return MakeAndRunTest(device, context, queue, num_elements); } +struct MultipleWaitSignal final : DXFenceTestBase +{ + using DXFenceTestBase::DXFenceTestBase; + + ~MultipleWaitSignal() override + { + if (fence_handle_2) + { + 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(); + }; + + int SetUp() override + { + DXFenceTestBase::SetUp(); + fence_wrapper_2 = new DirectXFenceWrapper(dx_wrapper.getDXDevice()); + semaphore_2 = createSemaphoreFromFence(fence_wrapper_2->get()); + test_assert_error(!!semaphore_2, "Could not create semaphore"); + + return TEST_PASS; + } + + cl_int Run() override + { + const cl_semaphore_khr semaphore_list[] = { semaphore, semaphore_2 }; + cl_semaphore_payload_khr semaphore_payload_list[] = { + semaphore_payload, semaphore_payload + 1 + }; + + log_info("Calling clEnqueueWaitSemaphoresKHR\n"); + clEventWrapper wait_event; + errcode = clEnqueueWaitSemaphoresKHR(queue, 2, semaphore_list, + semaphore_payload_list, 0, nullptr, + &wait_event); + test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR"); + + log_info("Calling d3d12_command_queue->Signal()\n"); + HRESULT hr = dx_wrapper.getDXCommandQueue()->Signal( + fence_wrapper_2->get(), semaphore_payload + 1); + test_error(FAILED(hr), "Failed to signal D3D12 fence 2"); + hr = dx_wrapper.getDXCommandQueue()->Signal(fence_wrapper->get(), + semaphore_payload); + test_error(FAILED(hr), "Failed to signal D3D12 fence 1"); + + log_info( + "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"); + hr = dx_wrapper.getDXCommandQueue()->Wait(fence_wrapper_2->get(), + semaphore_payload + 2); + test_error(FAILED(hr), "Failed to wait on D3D12 fence 2"); + + errcode = clFinish(queue); + test_error(errcode, "Could not finish queue"); + + test_assert_event_complete(wait_event); + + semaphore_payload_list[0] = semaphore_payload + 3; + semaphore_payload_list[1] = semaphore_payload + 2; + + log_info("Calling clEnqueueSignalSemaphoresKHR\n"); + clEventWrapper signal_event; + errcode = clEnqueueSignalSemaphoresKHR(queue, 2, semaphore_list, + semaphore_payload_list, 0, + nullptr, &signal_event); + test_error(errcode, "Could not call clEnqueueSignalSemaphoresKHR"); + + // Wait until the GPU has completed commands up to this fence point. + log_info("Waiting for D3D12 command queue completion\n"); + if (fence_wrapper->get()->GetCompletedValue() + < semaphore_payload_list[0]) + { + const HANDLE event_handle = + CreateEventEx(nullptr, nullptr, false, EVENT_ALL_ACCESS); + hr = fence_wrapper->get()->SetEventOnCompletion( + semaphore_payload_list[0], event_handle); + test_error(FAILED(hr), + "Failed to set D3D12 fence 1 event on completion"); + WaitForSingleObject(event_handle, INFINITE); + CloseHandle(event_handle); + } + if (fence_wrapper_2->get()->GetCompletedValue() + < semaphore_payload_list[1]) + { + const HANDLE event_handle = + CreateEventEx(nullptr, nullptr, false, EVENT_ALL_ACCESS); + hr = fence_wrapper_2->get()->SetEventOnCompletion( + semaphore_payload_list[1], event_handle); + test_error(FAILED(hr), + "Failed to set D3D12 fence 2 event on completion"); + WaitForSingleObject(event_handle, INFINITE); + CloseHandle(event_handle); + } + + errcode = clFinish(queue); + test_error(errcode, "Could not finish queue"); + + test_assert_event_complete(signal_event); + + 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) { - int errcode = CL_SUCCESS; - 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_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()); - CLDXSemaphoreWrapper semaphore_2(device, context, dx_wrapper.getDXDevice()); - test_error(semaphore_2.createSemaphoreFromFence(*fence_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[] = { - semaphore_payload, semaphore_payload + 1 - }; - - log_info("Calling clEnqueueWaitSemaphoresKHR\n"); - clEventWrapper wait_event; - errcode = clEnqueueWaitSemaphoresKHR(queue, 2, semaphore_list, - semaphore_payload_list, 0, nullptr, - &wait_event); - test_error(errcode, "Failed to call clEnqueueWaitSemaphoresKHR"); - - log_info("Calling d3d12_command_queue->Signal()\n"); - HRESULT hr = - dx_wrapper.getDXCommandQueue()->Signal(*fence_2, semaphore_payload + 1); - test_error(FAILED(hr), "Failed to signal D3D12 fence 2"); - hr = dx_wrapper.getDXCommandQueue()->Signal(*fence_1, semaphore_payload); - test_error(FAILED(hr), "Failed to signal D3D12 fence 1"); - - log_info("Calling d3d12_command_queue->Wait() with different payloads\n"); - hr = dx_wrapper.getDXCommandQueue()->Wait(*fence_1, semaphore_payload + 3); - test_error(FAILED(hr), "Failed to wait on D3D12 fence 1"); - hr = dx_wrapper.getDXCommandQueue()->Wait(*fence_2, semaphore_payload + 2); - test_error(FAILED(hr), "Failed to wait on D3D12 fence 2"); - - errcode = clFinish(queue); - test_error(errcode, "Could not finish queue"); - - test_assert_event_complete(wait_event); - - semaphore_payload_list[0] = semaphore_payload + 3; - semaphore_payload_list[1] = semaphore_payload + 2; - - log_info("Calling clEnqueueSignalSemaphoresKHR\n"); - clEventWrapper signal_event; - errcode = clEnqueueSignalSemaphoresKHR(queue, 2, semaphore_list, - semaphore_payload_list, 0, nullptr, - &signal_event); - test_error(errcode, "Could not call clEnqueueSignalSemaphoresKHR"); - - // Wait until the GPU has completed commands up to this fence point. - log_info("Waiting for D3D12 command queue completion\n"); - if ((*fence_1)->GetCompletedValue() < semaphore_payload_list[0]) - { - const HANDLE event_handle = - CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS); - hr = (*fence_1)->SetEventOnCompletion(semaphore_payload_list[0], - event_handle); - test_error(FAILED(hr), - "Failed to set D3D12 fence 1 event on completion"); - WaitForSingleObject(event_handle, INFINITE); - CloseHandle(event_handle); - } - if ((*fence_2)->GetCompletedValue() < semaphore_payload_list[1]) - { - const HANDLE event_handle = - CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS); - hr = (*fence_2)->SetEventOnCompletion(semaphore_payload_list[1], - event_handle); - test_error(FAILED(hr), - "Failed to set D3D12 fence 2 event on completion"); - WaitForSingleObject(event_handle, INFINITE); - CloseHandle(event_handle); - } - - errcode = clFinish(queue); - test_error(errcode, "Could not finish queue"); - - test_assert_event_complete(signal_event); - - return TEST_PASS; + return MakeAndRunTest(device, context, queue, + num_elements); } \ No newline at end of file diff --git a/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence_export.cpp b/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence_export.cpp index c54cf61b..ce7db56f 100644 --- a/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence_export.cpp +++ b/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence_export.cpp @@ -16,205 +16,205 @@ #include "semaphore_dx_fence_base.h" +struct ExportDXSignal final : DXFenceTestBase +{ + using DXFenceTestBase::DXFenceTestBase; + + int Run() override + { + size_t export_types_size = 0; + errcode = + clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR, + 0, nullptr, &export_types_size); + test_error(errcode, "Could not query export semaphore handle types"); + std::vector export_types( + export_types_size / sizeof(cl_external_semaphore_handle_type_khr)); + errcode = + clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR, + export_types_size, export_types.data(), nullptr); + test_error(errcode, "Could not query export semaphore handle types"); + + if (std::find(export_types.begin(), export_types.end(), + CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR) + == export_types.end()) + { + log_info( + "Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between " + "the supported export types\n"); + return TEST_FAIL; + } + + constexpr cl_semaphore_properties_khr sem_props[] = { + static_cast(CL_SEMAPHORE_TYPE_KHR), + static_cast( + CL_SEMAPHORE_TYPE_BINARY_KHR), + static_cast( + CL_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR), + static_cast( + CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR), + static_cast( + CL_SEMAPHORE_EXPORT_HANDLE_TYPES_LIST_END_KHR), + 0 + }; + cl_semaphore_khr exportable_semaphore = + clCreateSemaphoreWithPropertiesKHR(context, sem_props, &errcode); + test_error(errcode, "Could not create semaphore"); + + cl_bool is_exportable = CL_FALSE; + errcode = clGetSemaphoreInfoKHR( + exportable_semaphore, CL_SEMAPHORE_EXPORTABLE_KHR, + sizeof(is_exportable), &is_exportable, nullptr); + test_error(errcode, "Could not get semaphore info"); + test_error(!is_exportable, "Semaphore is not exportable"); + + log_info("Calling clEnqueueWaitSemaphoresKHR\n"); + clEventWrapper wait_event; + errcode = clEnqueueWaitSemaphoresKHR(queue, 1, &exportable_semaphore, + &semaphore_payload, 0, nullptr, + &wait_event); + test_error(errcode, "Failed to wait semaphore"); + + HANDLE semaphore_handle = nullptr; + errcode = clGetSemaphoreHandleForTypeKHR( + exportable_semaphore, device, CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR, + sizeof(semaphore_handle), &semaphore_handle, nullptr); + test_error(errcode, "Could not get semaphore handle"); + + ID3D12Fence *exported_fence = nullptr; + errcode = dx_wrapper.getDXDevice()->OpenSharedHandle( + semaphore_handle, IID_PPV_ARGS(&exported_fence)); + test_error(errcode, "Could not open semaphore handle"); + + log_info("Calling fence->Signal()\n"); + const HRESULT hr = exported_fence->Signal(semaphore_payload); + test_error(FAILED(hr), "Failed to signal D3D12 fence"); + + errcode = clFinish(queue); + test_error(errcode, "Could not finish queue"); + + test_assert_event_complete(wait_event); + + // Release resources + CloseHandle(semaphore_handle); + test_error(clReleaseSemaphoreKHR(exportable_semaphore), + "Could not release semaphore"); + exported_fence->Release(); + + return TEST_PASS; + } +}; + // Confirm that a wait followed by a signal in DirectX 12 using an exported // semaphore will complete successfully REGISTER_TEST(test_external_semaphores_export_dx_signal) { - int errcode = CL_SUCCESS; - 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); - - size_t export_types_size = 0; - errcode = - clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR, 0, - nullptr, &export_types_size); - test_error(errcode, "Could not query export semaphore handle types"); - std::vector export_types( - export_types_size / sizeof(cl_external_semaphore_handle_type_khr)); - errcode = - clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR, - export_types_size, export_types.data(), nullptr); - test_error(errcode, "Could not query export semaphore handle types"); - - if (std::find(export_types.begin(), export_types.end(), - CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR) - == export_types.end()) - { - log_info("Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between " - "the supported export types\n"); - return TEST_FAIL; - } - - constexpr cl_semaphore_properties_khr sem_props[] = { - static_cast(CL_SEMAPHORE_TYPE_KHR), - static_cast(CL_SEMAPHORE_TYPE_BINARY_KHR), - static_cast( - CL_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR), - static_cast( - CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR), - static_cast( - CL_SEMAPHORE_EXPORT_HANDLE_TYPES_LIST_END_KHR), - 0 - }; - cl_semaphore_khr semaphore = - clCreateSemaphoreWithPropertiesKHR(context, sem_props, &errcode); - test_error(errcode, "Could not create semaphore"); - - cl_bool is_exportable = CL_FALSE; - errcode = - clGetSemaphoreInfoKHR(semaphore, CL_SEMAPHORE_EXPORTABLE_KHR, - sizeof(is_exportable), &is_exportable, nullptr); - test_error(errcode, "Could not get semaphore info"); - test_error(!is_exportable, "Semaphore is not exportable"); - - log_info("Calling clEnqueueWaitSemaphoresKHR\n"); - constexpr cl_semaphore_payload_khr semaphore_payload = 1; - clEventWrapper wait_event; - errcode = clEnqueueWaitSemaphoresKHR( - queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &wait_event); - test_error(errcode, "Failed to wait semaphore"); - - HANDLE semaphore_handle = nullptr; - errcode = clGetSemaphoreHandleForTypeKHR( - semaphore, device, CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR, - sizeof(semaphore_handle), &semaphore_handle, nullptr); - test_error(errcode, "Could not get semaphore handle"); - - ID3D12Fence *fence = nullptr; - errcode = dx_wrapper.getDXDevice()->OpenSharedHandle(semaphore_handle, - IID_PPV_ARGS(&fence)); - test_error(errcode, "Could not open semaphore handle"); - - log_info("Calling fence->Signal()\n"); - const HRESULT hr = fence->Signal(semaphore_payload); - test_error(FAILED(hr), "Failed to signal D3D12 fence"); - - errcode = clFinish(queue); - test_error(errcode, "Could not finish queue"); - - test_assert_event_complete(wait_event); - - // Release resources - CloseHandle(semaphore_handle); - test_error(clReleaseSemaphoreKHR(semaphore), "Could not release semaphore"); - fence->Release(); - - return TEST_PASS; + return MakeAndRunTest(device, context, queue, num_elements); } +struct ExportDXWait final : DXFenceTestBase +{ + using DXFenceTestBase::DXFenceTestBase; + + int Run() override + { + size_t export_types_size = 0; + errcode = + clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR, + 0, nullptr, &export_types_size); + test_error(errcode, "Could not query export semaphore handle types"); + std::vector export_types( + export_types_size / sizeof(cl_external_semaphore_handle_type_khr)); + errcode = + clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR, + export_types_size, export_types.data(), nullptr); + test_error(errcode, "Could not query export semaphore handle types"); + + if (std::find(export_types.begin(), export_types.end(), + CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR) + == export_types.end()) + { + log_info( + "Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between " + "the supported export types\n"); + return TEST_FAIL; + } + + constexpr cl_semaphore_properties_khr sem_props[] = { + static_cast(CL_SEMAPHORE_TYPE_KHR), + static_cast( + CL_SEMAPHORE_TYPE_BINARY_KHR), + static_cast( + CL_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR), + static_cast( + CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR), + static_cast( + CL_SEMAPHORE_EXPORT_HANDLE_TYPES_LIST_END_KHR), + 0 + }; + cl_semaphore_khr exportable_semaphore = + clCreateSemaphoreWithPropertiesKHR(context, sem_props, &errcode); + test_error(errcode, "Could not create semaphore"); + + cl_bool is_exportable = CL_FALSE; + errcode = clGetSemaphoreInfoKHR( + exportable_semaphore, CL_SEMAPHORE_EXPORTABLE_KHR, + sizeof(is_exportable), &is_exportable, nullptr); + test_error(errcode, "Could not get semaphore info"); + test_error(!is_exportable, "Semaphore is not exportable"); + + log_info("Calling clEnqueueSignalSemaphoresKHR\n"); + constexpr cl_semaphore_payload_khr semaphore_payload = 1; + clEventWrapper signal_event; + errcode = clEnqueueSignalSemaphoresKHR(queue, 1, &exportable_semaphore, + &semaphore_payload, 0, nullptr, + &signal_event); + test_error(errcode, "Failed to signal semaphore"); + + HANDLE semaphore_handle = nullptr; + errcode = clGetSemaphoreHandleForTypeKHR( + exportable_semaphore, device, CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR, + sizeof(semaphore_handle), &semaphore_handle, nullptr); + test_error(errcode, "Could not get semaphore handle"); + + ID3D12Fence *exported_fence = nullptr; + errcode = dx_wrapper.getDXDevice()->OpenSharedHandle( + semaphore_handle, IID_PPV_ARGS(&exported_fence)); + test_error(errcode, "Could not open semaphore handle"); + + log_info("Calling dx_wrapper.get_d3d12_command_queue()->Wait()\n"); + HRESULT hr = dx_wrapper.getDXCommandQueue()->Wait(exported_fence, + semaphore_payload); + test_error(FAILED(hr), "Failed to wait on D3D12 fence"); + + log_info("Calling WaitForSingleObject\n"); + if (exported_fence->GetCompletedValue() < semaphore_payload) + { + const HANDLE event = + CreateEventEx(nullptr, nullptr, false, EVENT_ALL_ACCESS); + hr = exported_fence->SetEventOnCompletion(semaphore_payload, event); + test_error(FAILED(hr), "Failed to set event on completion"); + WaitForSingleObject(event, INFINITE); + CloseHandle(event); + } + + errcode = clFinish(queue); + test_error(errcode, "Could not finish queue"); + + test_assert_event_complete(signal_event); + + // Release resources + CloseHandle(semaphore_handle); + test_error(clReleaseSemaphoreKHR(exportable_semaphore), + "Could not release semaphore"); + exported_fence->Release(); + + 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) { - int errcode = CL_SUCCESS; - 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); - - size_t export_types_size = 0; - errcode = - clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR, 0, - nullptr, &export_types_size); - test_error(errcode, "Could not query export semaphore handle types"); - std::vector export_types( - export_types_size / sizeof(cl_external_semaphore_handle_type_khr)); - errcode = - clGetDeviceInfo(device, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR, - export_types_size, export_types.data(), nullptr); - test_error(errcode, "Could not query export semaphore handle types"); - - if (std::find(export_types.begin(), export_types.end(), - CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR) - == export_types.end()) - { - log_info("Could not find CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR between " - "the supported export types\n"); - return TEST_FAIL; - } - - constexpr cl_semaphore_properties_khr sem_props[] = { - static_cast(CL_SEMAPHORE_TYPE_KHR), - static_cast(CL_SEMAPHORE_TYPE_BINARY_KHR), - static_cast( - CL_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR), - static_cast( - CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR), - static_cast( - CL_SEMAPHORE_EXPORT_HANDLE_TYPES_LIST_END_KHR), - 0 - }; - cl_semaphore_khr semaphore = - clCreateSemaphoreWithPropertiesKHR(context, sem_props, &errcode); - test_error(errcode, "Could not create semaphore"); - - cl_bool is_exportable = CL_FALSE; - errcode = - clGetSemaphoreInfoKHR(semaphore, CL_SEMAPHORE_EXPORTABLE_KHR, - sizeof(is_exportable), &is_exportable, nullptr); - test_error(errcode, "Could not get semaphore info"); - test_error(!is_exportable, "Semaphore is not exportable"); - - log_info("Calling clEnqueueSignalSemaphoresKHR\n"); - constexpr cl_semaphore_payload_khr semaphore_payload = 1; - clEventWrapper signal_event; - errcode = clEnqueueSignalSemaphoresKHR( - queue, 1, &semaphore, &semaphore_payload, 0, nullptr, &signal_event); - test_error(errcode, "Failed to signal semaphore"); - - HANDLE semaphore_handle = nullptr; - errcode = clGetSemaphoreHandleForTypeKHR( - semaphore, device, CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR, - sizeof(semaphore_handle), &semaphore_handle, nullptr); - test_error(errcode, "Could not get semaphore handle"); - - ID3D12Fence *fence = nullptr; - errcode = dx_wrapper.getDXDevice()->OpenSharedHandle(semaphore_handle, - IID_PPV_ARGS(&fence)); - test_error(errcode, "Could not open semaphore handle"); - - log_info("Calling dx_wrapper.get_d3d12_command_queue()->Wait()\n"); - HRESULT hr = dx_wrapper.getDXCommandQueue()->Wait(fence, semaphore_payload); - test_error(FAILED(hr), "Failed to wait on D3D12 fence"); - - log_info("Calling WaitForSingleObject\n"); - if (fence->GetCompletedValue() < semaphore_payload) - { - const HANDLE event = - CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS); - hr = fence->SetEventOnCompletion(semaphore_payload, event); - test_error(FAILED(hr), "Failed to set event on completion"); - WaitForSingleObject(event, INFINITE); - CloseHandle(event); - } - - errcode = clFinish(queue); - test_error(errcode, "Could not finish queue"); - - test_assert_event_complete(signal_event); - - // Release resources - CloseHandle(semaphore_handle); - test_error(clReleaseSemaphoreKHR(semaphore), "Could not release semaphore"); - fence->Release(); - - return TEST_PASS; + return MakeAndRunTest(device, context, queue, num_elements); } \ No newline at end of file diff --git a/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence_negative_wait_signal.cpp b/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence_negative_wait_signal.cpp index 6c032c56..398eb2b1 100644 --- a/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence_negative_wait_signal.cpp +++ b/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence_negative_wait_signal.cpp @@ -16,74 +16,52 @@ #include "semaphore_dx_fence_base.h" +struct DXFenceNegativeWait final : DXFenceTestBase +{ + using DXFenceTestBase::DXFenceTestBase; + + int Run() override + { + log_info("Calling clEnqueueWaitSemaphoresKHR\n"); + errcode = clEnqueueWaitSemaphoresKHR(queue, 1, &semaphore, nullptr, 0, + nullptr, nullptr); + test_assert_error( + errcode == CL_INVALID_VALUE, + "Unexpected error code returned from clEnqueueWaitSemaphores"); + + return TEST_PASS; + } +}; + // Confirm that a wait without a semaphore payload list will return // CL_INVALID_VALUE REGISTER_TEST(test_external_semaphores_dx_fence_negative_wait) { - int errcode = CL_SUCCESS; - 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"); - - log_info("Calling clEnqueueWaitSemaphoresKHR\n"); - errcode = clEnqueueWaitSemaphoresKHR(queue, 1, &semaphore, nullptr, 0, - nullptr, nullptr); - test_assert_error( - errcode == CL_INVALID_VALUE, - "Unexpected error code returned from clEnqueueWaitSemaphores"); - - return TEST_PASS; + return MakeAndRunTest(device, context, queue, + num_elements); } +struct DXFenceNegativeSignal final : DXFenceTestBase +{ + using DXFenceTestBase::DXFenceTestBase; + + int Run() override + { + log_info("Calling clEnqueueWaitSemaphoresKHR\n"); + errcode = clEnqueueSignalSemaphoresKHR(queue, 1, &semaphore, nullptr, 0, + nullptr, nullptr); + test_assert_error( + errcode == CL_INVALID_VALUE, + "Unexpected error code returned from clEnqueueSignalSemaphores"); + + 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) { - int errcode = CL_SUCCESS; - 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); - - 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"); - - log_info("Calling clEnqueueWaitSemaphoresKHR\n"); - errcode = clEnqueueSignalSemaphoresKHR(queue, 1, &semaphore, nullptr, 0, - nullptr, nullptr); - test_assert_error( - errcode == CL_INVALID_VALUE, - "Unexpected error code returned from clEnqueueSignalSemaphores"); - - return TEST_PASS; + return MakeAndRunTest(device, context, queue, + num_elements); } \ No newline at end of file diff --git a/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence_queries.cpp b/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence_queries.cpp index 03aa2b15..87cb0caa 100644 --- a/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence_queries.cpp +++ b/test_conformance/extensions/cl_khr_external_semaphore_dx_fence/test_external_semaphore_dx_fence_queries.cpp @@ -16,54 +16,43 @@ #include "semaphore_dx_fence_base.h" +struct DXFenceQueryProperties final : DXFenceTestBase +{ + using DXFenceTestBase::DXFenceTestBase; + + int Run() override + { + size_t properties_size_bytes = 0; + errcode = clGetSemaphoreInfoKHR(semaphore, CL_SEMAPHORE_PROPERTIES_KHR, + 0, nullptr, &properties_size_bytes); + test_error(errcode, "Could not get semaphore info"); + std::vector semaphore_properties( + properties_size_bytes / sizeof(cl_semaphore_properties_khr)); + errcode = clGetSemaphoreInfoKHR(semaphore, CL_SEMAPHORE_PROPERTIES_KHR, + properties_size_bytes, + semaphore_properties.data(), nullptr); + test_error(errcode, "Could not get semaphore info"); + + for (unsigned i = 0; i < semaphore_properties.size() - 1; i++) + { + if (semaphore_properties[i] == CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR + && semaphore_properties[i + 1] + == reinterpret_cast( + fence_handle)) + { + return TEST_PASS; + } + } + log_error("Failed to find the dx fence handle type in the semaphore " + "properties"); + 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) { - int errcode = CL_SUCCESS; - 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"); - - size_t properties_size_bytes = 0; - errcode = clGetSemaphoreInfoKHR(*semaphore, CL_SEMAPHORE_PROPERTIES_KHR, 0, - nullptr, &properties_size_bytes); - test_error(errcode, "Could not get semaphore info"); - std::vector semaphore_properties( - properties_size_bytes / sizeof(cl_semaphore_properties_khr)); - errcode = clGetSemaphoreInfoKHR(*semaphore, CL_SEMAPHORE_PROPERTIES_KHR, - properties_size_bytes, - semaphore_properties.data(), nullptr); - test_error(errcode, "Could not get semaphore info"); - - for (unsigned i = 0; i < semaphore_properties.size() - 1; i++) - { - if (semaphore_properties[i] == CL_SEMAPHORE_HANDLE_D3D12_FENCE_KHR - && semaphore_properties[i + 1] - == reinterpret_cast( - semaphore.getHandle())) - { - return TEST_PASS; - } - } - log_error( - "Failed to find the dx fence handle type in the semaphore properties"); - return TEST_FAIL; + return MakeAndRunTest(device, context, queue, + num_elements); } \ No newline at end of file diff --git a/test_conformance/extensions/cl_khr_semaphore/semaphore_base.h b/test_conformance/extensions/cl_khr_semaphore/semaphore_base.h index 372bdd1e..828a5e46 100644 --- a/test_conformance/extensions/cl_khr_semaphore/semaphore_base.h +++ b/test_conformance/extensions/cl_khr_semaphore/semaphore_base.h @@ -23,6 +23,7 @@ #include "harness/deviceInfo.h" #include "harness/testHarness.h" #include "harness/typeWrappers.h" +#include "harness/extensionHelpers.h" struct SemaphoreBase { @@ -37,27 +38,15 @@ struct SemaphoreBase test_error(error, "clGetDeviceInfo for CL_DEVICE_PLATFORM failed"); // If it is supported get the addresses of all the APIs here. - // clang-format off -#define GET_EXTENSION_ADDRESS(FUNC) \ - FUNC = reinterpret_cast( \ - clGetExtensionFunctionAddressForPlatform(platform, #FUNC)); \ - if (FUNC == nullptr) \ - { \ - log_error("ERROR: clGetExtensionFunctionAddressForPlatform failed" \ - " with " #FUNC "\n"); \ - return TEST_FAIL; \ - } - // clang-format on + GET_FUNCTION_EXTENSION_ADDRESS(device, + clCreateSemaphoreWithPropertiesKHR); + GET_FUNCTION_EXTENSION_ADDRESS(device, clEnqueueSignalSemaphoresKHR); + GET_FUNCTION_EXTENSION_ADDRESS(device, clEnqueueWaitSemaphoresKHR); + GET_FUNCTION_EXTENSION_ADDRESS(device, clReleaseSemaphoreKHR); + GET_FUNCTION_EXTENSION_ADDRESS(device, clGetSemaphoreInfoKHR); + GET_FUNCTION_EXTENSION_ADDRESS(device, clRetainSemaphoreKHR); + GET_FUNCTION_EXTENSION_ADDRESS(device, clGetSemaphoreHandleForTypeKHR); - 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; }