diff --git a/projects/clr/hipamd/src/hip_device.cpp b/projects/clr/hipamd/src/hip_device.cpp index bc284eb15afe..b3462e5f4201 100644 --- a/projects/clr/hipamd/src/hip_device.cpp +++ b/projects/clr/hipamd/src/hip_device.cpp @@ -625,15 +625,14 @@ hipError_t hipDeviceGetLuid(char* luid, unsigned int* deviceNodeMask, hipDevice_ HIP_RETURN(hipErrorInvalidValue); } - if (IS_LINUX) { - // The LUID is a Windows/DXGI adapter concept; unsupported elsewhere and the - // output parameters are left untouched. - HIP_RETURN(hipErrorNotSupported); - } - auto* deviceHandle = g_devices[device]->devices()[0]; const auto& info = deviceHandle->info(); + // No WDDM/DXGI adapter behind this device, so no LUID to report. + if (info.luidLowPart_ == 0 && info.luidHighPart_ == 0) { + HIP_RETURN(hipErrorNotSupported); + } + // The LUID is an 8-byte value formed from the low and high parts reported by the backend. static_assert(sizeof(info.luidLowPart_) + sizeof(info.luidHighPart_) == 8, "LUID is expected to be 8 bytes"); diff --git a/projects/hip-tests/catch/unit/device/hipDeviceGetLuid.cc b/projects/hip-tests/catch/unit/device/hipDeviceGetLuid.cc index 80b6c01bf963..bf7e57a9d353 100644 --- a/projects/hip-tests/catch/unit/device/hipDeviceGetLuid.cc +++ b/projects/hip-tests/catch/unit/device/hipDeviceGetLuid.cc @@ -6,8 +6,21 @@ #include #include +#if !defined(_WIN32) +#include +#endif static constexpr size_t LUID_LEN = 8; +static constexpr unsigned int kSentinel = 0xdeadbeefU; + +static bool LuidMustBeSupported() { +#if defined(_WIN32) + return true; +#else + static const bool kIsWsl = (access("/dev/dxg", F_OK) == 0); + return kIsWsl; +#endif +} /** * @addtogroup hipDeviceGetLuid hipDeviceGetLuid @@ -21,9 +34,10 @@ static constexpr size_t LUID_LEN = 8; * Test Description * ------------------------ * - Query the LUID for each available device. - * - The LUID is a Windows/DXGI adapter concept. On Windows the call succeeds; - * on other platforms it returns `hipErrorNotSupported` without writing the - * output parameters. + * - Where an adapter backs the device (Windows, or Linux under WSL - detected by + * the presence of `/dev/dxg`) the call must succeed and write a non-zero LUID + * and node mask; everywhere else it must return `hipErrorNotSupported` without + * touching the output parameters. * Test source * ------------------------ * - unit/device/hipDeviceGetLuid.cc @@ -37,32 +51,36 @@ HIP_TEST_CASE(Unit_hipDeviceGetLuid_Positive) { HIP_CHECK(hipDeviceGet(&device, deviceId)); char luid[LUID_LEN] = {0}; - unsigned int deviceNodeMask = 0; -#if defined(_WIN32) - HIP_CHECK(hipDeviceGetLuid(luid, &deviceNodeMask, device)); - // A valid adapter LUID is never all-zero and the node mask has at least one - // bit set, so verify the outputs were actually written. + unsigned int deviceNodeMask = kSentinel; + const hipError_t err = hipDeviceGetLuid(luid, &deviceNodeMask, device); + + const bool supported = (err == hipSuccess); + const bool mustSupport = LuidMustBeSupported(); + INFO("device " << deviceId << ", hipDeviceGetLuid returned " << hipGetErrorString(err)); + REQUIRE(supported == mustSupport); + char zeroLuid[LUID_LEN] = {0}; - REQUIRE(memcmp(luid, zeroLuid, LUID_LEN) != 0); - REQUIRE(deviceNodeMask != 0); -#else - const unsigned int kSentinel = 0xdeadbeefU; - deviceNodeMask = kSentinel; - REQUIRE(hipDeviceGetLuid(luid, &deviceNodeMask, device) == hipErrorNotSupported); - // Outputs must be left untouched on the unsupported path. - char zero[LUID_LEN] = {0}; - REQUIRE(memcmp(luid, zero, LUID_LEN) == 0); - REQUIRE(deviceNodeMask == kSentinel); -#endif + if (err == hipSuccess) { + // A valid adapter LUID is never all-zero and the node mask has at least one + // bit set, so verify the outputs were actually written. + REQUIRE(memcmp(luid, zeroLuid, LUID_LEN) != 0); + REQUIRE(deviceNodeMask != 0); + } else { + REQUIRE(err == hipErrorNotSupported); + // Outputs must be left untouched on the unsupported path. + REQUIRE(memcmp(luid, zeroLuid, LUID_LEN) == 0); + REQUIRE(deviceNodeMask == kSentinel); + } } /** * Test Description * ------------------------ - * - On Windows, verify that the LUID and device node mask returned by - * hipDeviceGetLuid match the values reported by hipGetDeviceProperties. - * - On other platforms, verify the API reports `hipErrorNotSupported` and that - * hipGetDeviceProperties reports an all-zero LUID and zero node mask. + * - Verify hipDeviceGetLuid and hipGetDeviceProperties agree for every device: + * on success the LUID and node mask must match; on `hipErrorNotSupported` + * the properties must report an all-zero LUID and zero node mask. + * - Success is required on Windows and WSL, and `hipErrorNotSupported` is + * required everywhere else. * Test source * ------------------------ * - unit/device/hipDeviceGetLuid.cc @@ -79,22 +97,28 @@ HIP_TEST_CASE(Unit_hipDeviceGetLuid_VerifyLuidFrm_hipGetDeviceProperties) { hipDevice_t device; HIP_CHECK(hipDeviceGet(&device, dev)); - char luid[LUID_LEN] = {0}; - unsigned int deviceNodeMask = 0; - hipDeviceProp_t prop; HIP_CHECK(hipGetDeviceProperties(&prop, dev)); -#if defined(_WIN32) - HIP_CHECK(hipDeviceGetLuid(luid, &deviceNodeMask, device)); - REQUIRE(memcmp(luid, prop.luid, LUID_LEN) == 0); - REQUIRE(deviceNodeMask == prop.luidDeviceNodeMask); -#else - REQUIRE(hipDeviceGetLuid(luid, &deviceNodeMask, device) == hipErrorNotSupported); - char zero[LUID_LEN] = {0}; - REQUIRE(memcmp(prop.luid, zero, LUID_LEN) == 0); - REQUIRE(prop.luidDeviceNodeMask == 0); -#endif + char luid[LUID_LEN] = {0}; + unsigned int deviceNodeMask = kSentinel; + const hipError_t err = hipDeviceGetLuid(luid, &deviceNodeMask, device); + + const bool supported = (err == hipSuccess); + const bool mustSupport = LuidMustBeSupported(); + INFO("device " << dev << ", hipDeviceGetLuid returned " << hipGetErrorString(err)); + REQUIRE(supported == mustSupport); + + if (err == hipSuccess) { + REQUIRE(memcmp(luid, prop.luid, LUID_LEN) == 0); + REQUIRE(deviceNodeMask == prop.luidDeviceNodeMask); + } else { + REQUIRE(err == hipErrorNotSupported); + // Properties must not report a LUID either. + char zero[LUID_LEN] = {0}; + REQUIRE(memcmp(prop.luid, zero, LUID_LEN) == 0); + REQUIRE(prop.luidDeviceNodeMask == 0); + } } }