diff --git a/opencl/source/sharings/gl/windows/cl_gl_api.cpp b/opencl/source/sharings/gl/windows/cl_gl_api.cpp index f0c2fd976e..4e85c981b3 100644 --- a/opencl/source/sharings/gl/windows/cl_gl_api.cpp +++ b/opencl/source/sharings/gl/windows/cl_gl_api.cpp @@ -6,6 +6,7 @@ */ #include "shared/source/helpers/get_info.h" +#include "shared/source/os_interface/windows/os_interface.h" #include "shared/source/utilities/api_intercept.h" #include "opencl/source/api/api.h" @@ -350,11 +351,23 @@ cl_int CL_API_CALL clGetGLContextInfoKHR(const cl_context_properties *properties } if (paramName == CL_DEVICES_FOR_GL_CONTEXT_KHR || paramName == CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR) { - if (platform) { - info.set(platform->getClDevice(0)); - } else { - info.set(platformsImpl[0]->getClDevice(0)); + if (!platform) { + platform = platformsImpl[0].get(); } + + ClDevice *deviceToReturn = nullptr; + for (auto i = 0u; i < platform->getNumDevices(); i++) { + auto device = platform->getClDevice(i); + if (device->getRootDeviceEnvironment().osInterface->get()->getWddm()->verifyHdcHandle(GLHDCHandle)) { + deviceToReturn = device; + break; + } + } + if (!deviceToReturn) { + retVal = CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR; + return retVal; + } + info.set(deviceToReturn); return retVal; } diff --git a/opencl/test/unit_test/api/gl/CMakeLists.txt b/opencl/test/unit_test/api/gl/CMakeLists.txt index 6c901fb32b..6b236558b8 100644 --- a/opencl/test/unit_test/api/gl/CMakeLists.txt +++ b/opencl/test/unit_test/api/gl/CMakeLists.txt @@ -15,7 +15,6 @@ if(WIN32) ${CMAKE_CURRENT_SOURCE_DIR}/cl_enqueue_acquire_gl_objects_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cl_enqueue_release_gl_objects_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cl_get_gl_device_info_tests.cpp - ${CMAKE_CURRENT_SOURCE_DIR}/cl_get_gl_context_info_khr_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cl_get_gl_object_info_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cl_get_gl_texture_info_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cl_gl_intel_tracing_tests.cpp diff --git a/opencl/test/unit_test/mocks/mock_wddm.h b/opencl/test/unit_test/mocks/mock_wddm.h index a9b49467a0..d8d932ffb8 100644 --- a/opencl/test/unit_test/mocks/mock_wddm.h +++ b/opencl/test/unit_test/mocks/mock_wddm.h @@ -46,6 +46,7 @@ class WddmMock : public Wddm { using Wddm::temporaryResources; using Wddm::wddmInterface; + WddmMock(std::unique_ptr hwDeviceId, RootDeviceEnvironment &rootDeviceEnvironment) : Wddm(std::move(hwDeviceId), rootDeviceEnvironment) {} WddmMock(RootDeviceEnvironment &rootDeviceEnvironment); ~WddmMock(); @@ -108,6 +109,9 @@ class WddmMock : public Wddm { ++counterVerifySharedHandle; return Wddm::verifySharedHandle(osHandle); } + bool verifyHdcHandle(size_t hdcHandle) const override { + return verifyHdcReturnValue; + } void resetGdi(Gdi *gdi); @@ -147,6 +151,7 @@ class WddmMock : public Wddm { bool makeResidentStatus = true; bool callBaseMakeResident = true; bool callBaseCreatePagingLogger = true; + bool verifyHdcReturnValue = true; }; struct GmockWddm : WddmMock { diff --git a/opencl/test/unit_test/os_interface/windows/gl/CMakeLists.txt b/opencl/test/unit_test/os_interface/windows/gl/CMakeLists.txt new file mode 100644 index 0000000000..71e28b0f5a --- /dev/null +++ b/opencl/test/unit_test/os_interface/windows/gl/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright (C) 2020 Intel Corporation +# +# SPDX-License-Identifier: MIT +# + +set(IGDRCL_SRCS_tests_os_interface_windows_gl + ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt + ${CMAKE_CURRENT_SOURCE_DIR}/cl_get_gl_context_info_khr_tests.cpp +) +if(WIN32) + target_sources(igdrcl_tests PRIVATE ${IGDRCL_SRCS_tests_os_interface_windows_gl}) +endif() diff --git a/opencl/test/unit_test/api/gl/cl_get_gl_context_info_khr_tests.cpp b/opencl/test/unit_test/os_interface/windows/gl/cl_get_gl_context_info_khr_tests.cpp similarity index 54% rename from opencl/test/unit_test/api/gl/cl_get_gl_context_info_khr_tests.cpp rename to opencl/test/unit_test/os_interface/windows/gl/cl_get_gl_context_info_khr_tests.cpp index efd70cec81..98c4d024fe 100644 --- a/opencl/test/unit_test/api/gl/cl_get_gl_context_info_khr_tests.cpp +++ b/opencl/test/unit_test/os_interface/windows/gl/cl_get_gl_context_info_khr_tests.cpp @@ -7,20 +7,28 @@ #include "shared/source/helpers/hw_info.h" #include "shared/source/os_interface/device_factory.h" +#include "shared/source/os_interface/windows/os_interface.h" #include "shared/test/unit_test/mocks/mock_device.h" #include "opencl/source/cl_device/cl_device.h" #include "opencl/test/unit_test/api/cl_api_tests.h" #include "opencl/test/unit_test/mocks/mock_platform.h" +#include "opencl/test/unit_test/mocks/mock_wddm.h" #include "opencl/test/unit_test/sharings/gl/gl_dll_helper.h" using namespace NEO; -typedef api_tests clGetGLContextInfoKHR_; +using clGetGLContextInfoKhrTest = api_tests; namespace ULT { -TEST_F(clGetGLContextInfoKHR_, successWithDefaultPlatform) { +TEST_F(clGetGLContextInfoKhrTest, successWithDefaultPlatform) { + VariableBackup backup(&ultHwConfig); + ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false; + + auto defaultPlatform = std::make_unique(); + defaultPlatform->initializeWithNewDevices(); + platformsImpl[0] = std::move(defaultPlatform); auto expectedDevice = ::platform()->getClDevice(0); cl_device_id retDevice = 0; size_t retSize = 0; @@ -44,6 +52,9 @@ using clGetGLContextInfoKHRNonDefaultPlatform = ::testing::Test; TEST_F(clGetGLContextInfoKHRNonDefaultPlatform, successWithNonDefaultPlatform) { platformsImpl.clear(); + VariableBackup backup(&ultHwConfig); + ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false; + cl_int retVal = CL_SUCCESS; auto nonDefaultPlatform = std::make_unique(); @@ -68,7 +79,7 @@ TEST_F(clGetGLContextInfoKHRNonDefaultPlatform, successWithNonDefaultPlatform) { EXPECT_EQ(sizeof(cl_device_id), retSize); } -TEST_F(clGetGLContextInfoKHR_, invalidParam) { +TEST_F(clGetGLContextInfoKhrTest, invalidParam) { cl_device_id retDevice = 0; size_t retSize = 0; const cl_context_properties properties[] = {CL_GL_CONTEXT_KHR, 1, CL_WGL_HDC_KHR, 2, 0}; @@ -79,7 +90,7 @@ TEST_F(clGetGLContextInfoKHR_, invalidParam) { EXPECT_EQ(0u, retSize); } -TEST_F(clGetGLContextInfoKHR_, givenContextFromNoIntelOpenGlDriverWhenCallClGetGLContextInfoKHRThenReturnClInvalidContext) { +TEST_F(clGetGLContextInfoKhrTest, givenContextFromNoIntelOpenGlDriverWhenCallClGetGLContextInfoKHRThenReturnClInvalidContext) { cl_device_id retDevice = 0; size_t retSize = 0; const cl_context_properties properties[] = {CL_GL_CONTEXT_KHR, 1, CL_WGL_HDC_KHR, 2, 0}; @@ -92,7 +103,7 @@ TEST_F(clGetGLContextInfoKHR_, givenContextFromNoIntelOpenGlDriverWhenCallClGetG EXPECT_EQ(0u, retSize); } -TEST_F(clGetGLContextInfoKHR_, givenNullVersionFromIntelOpenGlDriverWhenCallClGetGLContextInfoKHRThenReturnClInvalidContext) { +TEST_F(clGetGLContextInfoKhrTest, givenNullVersionFromIntelOpenGlDriverWhenCallClGetGLContextInfoKHRThenReturnClInvalidContext) { cl_device_id retDevice = 0; size_t retSize = 0; const cl_context_properties properties[] = {CL_GL_CONTEXT_KHR, 1, CL_WGL_HDC_KHR, 2, 0}; @@ -105,7 +116,7 @@ TEST_F(clGetGLContextInfoKHR_, givenNullVersionFromIntelOpenGlDriverWhenCallClGe EXPECT_EQ(0u, retSize); } -TEST_F(clGetGLContextInfoKHR_, GivenIncorrectPropertiesWhenCallclGetGLContextInfoKHRThenReturnClInvalidGlShareGroupRererencKhr) { +TEST_F(clGetGLContextInfoKhrTest, GivenIncorrectPropertiesWhenCallclGetGLContextInfoKHRThenReturnClInvalidGlShareGroupRererencKhr) { cl_device_id retDevice = 0; size_t retSize = 0; retVal = clGetGLContextInfoKHR(nullptr, 0, sizeof(cl_device_id), &retDevice, &retSize); @@ -120,4 +131,58 @@ TEST_F(clGetGLContextInfoKHR_, GivenIncorrectPropertiesWhenCallclGetGLContextInf EXPECT_EQ(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR, retVal); } +TEST_F(clGetGLContextInfoKHRNonDefaultPlatform, whenVerificationOfHdcHandleFailsThenInvalidGlReferenceErrorIsReturned) { + platformsImpl.clear(); + + VariableBackup backup(&ultHwConfig); + ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false; + + cl_int retVal = CL_SUCCESS; + + auto nonDefaultPlatform = std::make_unique(); + nonDefaultPlatform->initializeWithNewDevices(); + cl_platform_id nonDefaultPlatformCl = nonDefaultPlatform.get(); + + auto device = nonDefaultPlatform->getClDevice(0); + + static_cast(device->getRootDeviceEnvironment().osInterface->get()->getWddm())->verifyHdcReturnValue = false; + size_t retSize = 0; + cl_device_id retDevice = 0; + + const cl_context_properties properties[] = {CL_GL_CONTEXT_KHR, 1, CL_WGL_HDC_KHR, 2, CL_CONTEXT_PLATFORM, reinterpret_cast(nonDefaultPlatformCl), 0}; + retVal = clGetGLContextInfoKHR(properties, CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, sizeof(cl_device_id), &retDevice, &retSize); + + EXPECT_EQ(CL_INVALID_GL_SHAREGROUP_REFERENCE_KHR, retVal); +} +TEST_F(clGetGLContextInfoKHRNonDefaultPlatform, whenVerificationOfHdcHandleFailsForFirstDeviceButSucceedsForSecondOneThenReturnTheSecondDevice) { + platformsImpl.clear(); + + DebugManagerStateRestore restorer; + DebugManager.flags.CreateMultipleRootDevices.set(2); + VariableBackup backup(&ultHwConfig); + ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false; + + cl_int retVal = CL_SUCCESS; + + auto nonDefaultPlatform = std::make_unique(); + nonDefaultPlatform->initializeWithNewDevices(); + cl_platform_id nonDefaultPlatformCl = nonDefaultPlatform.get(); + + auto device0 = nonDefaultPlatform->getClDevice(0); + auto device1 = nonDefaultPlatform->getClDevice(0); + cl_device_id expectedDevice = device1; + + static_cast(device0->getRootDeviceEnvironment().osInterface->get()->getWddm())->verifyHdcReturnValue = false; + static_cast(device1->getRootDeviceEnvironment().osInterface->get()->getWddm())->verifyHdcReturnValue = true; + size_t retSize = 0; + cl_device_id retDevice = 0; + + const cl_context_properties properties[] = {CL_GL_CONTEXT_KHR, 1, CL_WGL_HDC_KHR, 2, CL_CONTEXT_PLATFORM, reinterpret_cast(nonDefaultPlatformCl), 0}; + retVal = clGetGLContextInfoKHR(properties, CL_CURRENT_DEVICE_FOR_GL_CONTEXT_KHR, sizeof(cl_device_id), &retDevice, &retSize); + + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_EQ(expectedDevice, retDevice); + EXPECT_EQ(sizeof(cl_device_id), retSize); +} + } // namespace ULT diff --git a/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp b/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp index 71b8927289..931c7935bd 100644 --- a/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp +++ b/opencl/test/unit_test/os_interface/windows/wddm20_tests.cpp @@ -1449,3 +1449,63 @@ TEST(DiscoverDevices, whenDriverInfoHasIncompatibleDriverStoreThenHwDeviceIdIsNo auto hwDeviceIds = OSInterface::discoverDevices(executionEnvironment); EXPECT_TRUE(hwDeviceIds.empty()); } + +TEST(VerifyHdcTest, givenHdcHandleFromCorrectAdapterLuidWhenVerifyHdcHandleIsCalledThenSuccessIsReturned) { + auto gdi = std::make_unique(); + auto osEnv = std::make_unique(); + osEnv->gdi = std::move(gdi); + + LUID adapterLuid = {0x1234, 0x5678}; + + VariableBackup luidBackup(&MockGdi::adapterLuidToReturn, adapterLuid); + + auto hwDeviceId = std::make_unique(ADAPTER_HANDLE, adapterLuid, osEnv.get()); + + MockExecutionEnvironment executionEnvironment; + executionEnvironment.osEnvironment = std::move(osEnv); + RootDeviceEnvironment rootDeviceEnvironment(executionEnvironment); + + WddmMock wddm(std::move(hwDeviceId), rootDeviceEnvironment); + + size_t hdcHandle = 0x1; + + auto status = wddm.Wddm::verifyHdcHandle(hdcHandle); + + EXPECT_TRUE(status); + + status = wddm.Wddm::verifyHdcHandle(0u); + + EXPECT_FALSE(status); +} + +TEST(VerifyHdcTest, givenHdcHandleFromInvalidAdapterLuidWhenVerifyHdcHandleIsCalledThenFailureIsReturned) { + auto gdi = std::make_unique(); + auto osEnv = std::make_unique(); + osEnv->gdi = std::move(gdi); + + LUID adapterLuid = {0x1234, 0x5678}; + + VariableBackup luidBackup(&MockGdi::adapterLuidToReturn); + + auto hwDeviceId = std::make_unique(ADAPTER_HANDLE, adapterLuid, osEnv.get()); + + MockExecutionEnvironment executionEnvironment; + executionEnvironment.osEnvironment = std::move(osEnv); + RootDeviceEnvironment rootDeviceEnvironment(executionEnvironment); + + WddmMock wddm(std::move(hwDeviceId), rootDeviceEnvironment); + + size_t hdcHandle = 0x1; + + MockGdi::adapterLuidToReturn = {0x1233, 0x5678}; + + auto status = wddm.Wddm::verifyHdcHandle(hdcHandle); + + EXPECT_FALSE(status); + + MockGdi::adapterLuidToReturn = {0x1234, 0x5679}; + + status = wddm.Wddm::verifyHdcHandle(hdcHandle); + + EXPECT_FALSE(status); +} diff --git a/shared/source/os_interface/windows/gdi_interface.cpp b/shared/source/os_interface/windows/gdi_interface.cpp index c80b9c62a1..0e821292ca 100644 --- a/shared/source/os_interface/windows/gdi_interface.cpp +++ b/shared/source/os_interface/windows/gdi_interface.cpp @@ -22,7 +22,7 @@ inline const std::string getGdiName() { Gdi::Gdi() : gdiDll(getGdiName()), initialized(false) { if (gdiDll.isLoaded()) { - initialized = getAllProcAddresses(); + initialized = Gdi::getAllProcAddresses(); } } diff --git a/shared/source/os_interface/windows/wddm/wddm.cpp b/shared/source/os_interface/windows/wddm/wddm.cpp index bdb4bdf483..1e0f10986e 100644 --- a/shared/source/os_interface/windows/wddm/wddm.cpp +++ b/shared/source/os_interface/windows/wddm/wddm.cpp @@ -1059,4 +1059,15 @@ void Wddm::createPagingFenceLogger() { } } +bool Wddm::verifyHdcHandle(size_t hdcHandle) const { + D3DKMT_OPENADAPTERFROMHDC openAdapterFromHdcStruct{}; + openAdapterFromHdcStruct.hDc = reinterpret_cast(hdcHandle); + auto status = getGdi()->openAdapterFromHdc(&openAdapterFromHdcStruct); + if (STATUS_SUCCESS != status) { + DEBUG_BREAK_IF(true); + return false; + } + return openAdapterFromHdcStruct.AdapterLuid.HighPart == hwDeviceId->getAdapterLuid().HighPart && openAdapterFromHdcStruct.AdapterLuid.LowPart == hwDeviceId->getAdapterLuid().LowPart; +} + } // namespace NEO diff --git a/shared/source/os_interface/windows/wddm/wddm.h b/shared/source/os_interface/windows/wddm/wddm.h index 7fee96f744..a597cbc10b 100644 --- a/shared/source/os_interface/windows/wddm/wddm.h +++ b/shared/source/os_interface/windows/wddm/wddm.h @@ -92,6 +92,8 @@ class Wddm { bool configureDeviceAddressSpace(); + MOCKABLE_VIRTUAL bool verifyHdcHandle(size_t hdcHandle) const; + GT_SYSTEM_INFO *getGtSysInfo() const { DEBUG_BREAK_IF(!gtSystemInfo); return gtSystemInfo.get(); diff --git a/shared/test/unit_test/os_interface/windows/mock_gdi_interface.cpp b/shared/test/unit_test/os_interface/windows/mock_gdi_interface.cpp index e8f22d169c..565aa4a513 100644 --- a/shared/test/unit_test/os_interface/windows/mock_gdi_interface.cpp +++ b/shared/test/unit_test/os_interface/windows/mock_gdi_interface.cpp @@ -9,4 +9,5 @@ namespace NEO { UINT64 MockGdi::pagingFenceReturnValue = 0x3ull; +LUID MockGdi::adapterLuidToReturn{}; } // namespace NEO diff --git a/shared/test/unit_test/os_interface/windows/mock_gdi_interface.h b/shared/test/unit_test/os_interface/windows/mock_gdi_interface.h index 98bf7b2c89..0cb0ec4483 100644 --- a/shared/test/unit_test/os_interface/windows/mock_gdi_interface.h +++ b/shared/test/unit_test/os_interface/windows/mock_gdi_interface.h @@ -15,12 +15,13 @@ namespace NEO { class MockGdi : public Gdi { public: MockGdi() { - initialized = getAllProcAddresses(); + initialized = MockGdi::getAllProcAddresses(); } ~MockGdi(){}; static UINT64 pagingFenceReturnValue; bool nonZeroNumBytesToTrim = false; + static LUID adapterLuidToReturn; void setNonZeroNumBytesToTrimInEvict() { nonZeroNumBytesToTrim = true; @@ -106,6 +107,7 @@ class MockGdi : public Gdi { waitForSynchronizationObjectFromCpu = reinterpret_cast(waitFromCpuMock); queryResourceInfo = reinterpret_cast(queryResourceInfoMock); openResource = reinterpret_cast(openResourceMock); + openAdapterFromHdc = reinterpret_cast(MockGdi::openAdapterFromHdcMock); return true; } @@ -163,6 +165,16 @@ class MockGdi : public Gdi { static D3DKMT_OPENRESOURCE openResource; return openResource; } + static NTSTATUS __stdcall openAdapterFromHdcMock(D3DKMT_OPENADAPTERFROMHDC *openAdapterFromHdcStruct) { + if (!openAdapterFromHdcStruct) { + return STATUS_INVALID_PARAMETER; + } + if (openAdapterFromHdcStruct->hDc == 0) { + return STATUS_INVALID_PARAMETER; + } + openAdapterFromHdcStruct->AdapterLuid = MockGdi::adapterLuidToReturn; + return STATUS_SUCCESS; + } }; } // namespace NEO