Skip to content

Commit

Permalink
[SYCL] Update various PI entry points to treat PI_ERROR_INVALID_OPERA…
Browse files Browse the repository at this point in the history
…TION as receiving UR_RESULT_ERROR_UNSUPPORTED_FEATURE from Unified Runtime

and throw an appropriate exception. Added a new e2e test to check the error is handled correctly.
  • Loading branch information
martygrant committed Apr 5, 2024
1 parent d86a500 commit cec923e
Show file tree
Hide file tree
Showing 38 changed files with 2,436 additions and 663 deletions.
129 changes: 106 additions & 23 deletions sycl/source/backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,16 @@ platform make_platform(pi_native_handle NativeHandle, backend Backend) {

// Create PI platform first.
pi::PiPlatform PiPlatform = nullptr;
Plugin->call<PiApiKind::piextPlatformCreateWithNativeHandle>(NativeHandle,
&PiPlatform);
sycl::detail::pi::PiResult Result =
Plugin->call_nocheck<PiApiKind::piextPlatformCreateWithNativeHandle>(
NativeHandle, &PiPlatform);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Platform create with native handle command not supported by backend.");
} else {
Plugin->checkPiResult(Result);
}

return detail::createSyclObjFromImpl<platform>(
platform_impl::getOrMakePlatformImpl(PiPlatform, Plugin));
Expand All @@ -84,8 +92,16 @@ __SYCL_EXPORT device make_device(pi_native_handle NativeHandle,
const auto &Plugin = getPlugin(Backend);

pi::PiDevice PiDevice = nullptr;
Plugin->call<PiApiKind::piextDeviceCreateWithNativeHandle>(
NativeHandle, nullptr, &PiDevice);
sycl::detail::pi::PiResult Result =
Plugin->call_nocheck<PiApiKind::piextDeviceCreateWithNativeHandle>(
NativeHandle, nullptr, &PiDevice);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Device create with native handle command not supported by backend.");
} else {
Plugin->checkPiResult(Result);
}
// Construct the SYCL device from PI device.
return detail::createSyclObjFromImpl<device>(
std::make_shared<device_impl>(PiDevice, Plugin));
Expand All @@ -97,8 +113,16 @@ __SYCL_EXPORT context make_context(pi_native_handle NativeHandle,
const auto &Plugin = getPlugin(Backend);

pi::PiContext PiContext = nullptr;
Plugin->call<PiApiKind::piextContextCreateWithNativeHandle>(
NativeHandle, 0, nullptr, false, &PiContext);
sycl::detail::pi::PiResult Result =
Plugin->call_nocheck<PiApiKind::piextContextCreateWithNativeHandle>(
NativeHandle, 0, nullptr, false, &PiContext);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Context create with native handle command not supported by backend.");
} else {
Plugin->checkPiResult(Result);
}
// Construct the SYCL context from PI context.
return detail::createSyclObjFromImpl<context>(
std::make_shared<context_impl>(PiContext, Handler, Plugin));
Expand Down Expand Up @@ -130,9 +154,18 @@ __SYCL_EXPORT queue make_queue(pi_native_handle NativeHandle,

// Create PI queue first.
pi::PiQueue PiQueue = nullptr;
Plugin->call<PiApiKind::piextQueueCreateWithNativeHandle>(
NativeHandle, NativeHandleDesc, ContextImpl->getHandleRef(), PiDevice,
!KeepOwnership, Properties, &PiQueue);
sycl::detail::pi::PiResult Result =
Plugin->call_nocheck<PiApiKind::piextQueueCreateWithNativeHandle>(
NativeHandle, NativeHandleDesc, ContextImpl->getHandleRef(), PiDevice,
!KeepOwnership, Properties, &PiQueue);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Queue create with native handle command not supported by backend.");
} else {
Plugin->checkPiResult(Result);
}

// Construct the SYCL queue from PI queue.
return detail::createSyclObjFromImpl<queue>(
std::make_shared<queue_impl>(PiQueue, ContextImpl, Handler, PropList));
Expand All @@ -150,8 +183,16 @@ __SYCL_EXPORT event make_event(pi_native_handle NativeHandle,
const auto &ContextImpl = getSyclObjImpl(Context);

pi::PiEvent PiEvent = nullptr;
Plugin->call<PiApiKind::piextEventCreateWithNativeHandle>(
NativeHandle, ContextImpl->getHandleRef(), !KeepOwnership, &PiEvent);
sycl::detail::pi::PiResult Result =
Plugin->call_nocheck<PiApiKind::piextEventCreateWithNativeHandle>(
NativeHandle, ContextImpl->getHandleRef(), !KeepOwnership, &PiEvent);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Event create with native handle command not supported by backend.");
} else {
Plugin->checkPiResult(Result);
}

event Event = detail::createSyclObjFromImpl<event>(
std::make_shared<event_impl>(PiEvent, Context));
Expand All @@ -168,27 +209,60 @@ make_kernel_bundle(pi_native_handle NativeHandle, const context &TargetContext,
const auto &ContextImpl = getSyclObjImpl(TargetContext);

pi::PiProgram PiProgram = nullptr;
Plugin->call<PiApiKind::piextProgramCreateWithNativeHandle>(
NativeHandle, ContextImpl->getHandleRef(), !KeepOwnership, &PiProgram);
if (ContextImpl->getBackend() == backend::opencl)
sycl::detail::pi::PiResult Result =
Plugin->call_nocheck<PiApiKind::piextProgramCreateWithNativeHandle>(
NativeHandle, ContextImpl->getHandleRef(), !KeepOwnership,
&PiProgram);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Program create with native handle command not supported by backend.");
} else {
Plugin->checkPiResult(Result);
}
if (ContextImpl->getBackend() == backend::opencl) {
Plugin->call<PiApiKind::piProgramRetain>(PiProgram);
}

std::vector<pi::PiDevice> ProgramDevices;
uint32_t NumDevices = 0;

Plugin->call<PiApiKind::piProgramGetInfo>(
Result = Plugin->call_nocheck<PiApiKind::piProgramGetInfo>(
PiProgram, PI_PROGRAM_INFO_NUM_DEVICES, sizeof(NumDevices), &NumDevices,
nullptr);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Program get info command not supported by backend.");
} else {
Plugin->checkPiResult(Result);
}
ProgramDevices.resize(NumDevices);
Plugin->call<PiApiKind::piProgramGetInfo>(PiProgram, PI_PROGRAM_INFO_DEVICES,
sizeof(pi::PiDevice) * NumDevices,
ProgramDevices.data(), nullptr);

Result = Plugin->call_nocheck<PiApiKind::piProgramGetInfo>(
PiProgram, PI_PROGRAM_INFO_DEVICES, sizeof(pi::PiDevice) * NumDevices,
ProgramDevices.data(), nullptr);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Program get info command not supported by backend.");
} else {
Plugin->checkPiResult(Result);
}

for (const auto &Dev : ProgramDevices) {
size_t BinaryType = 0;
Plugin->call<PiApiKind::piProgramGetBuildInfo>(
Result = Plugin->call_nocheck<PiApiKind::piProgramGetBuildInfo>(
PiProgram, Dev, PI_PROGRAM_BUILD_INFO_BINARY_TYPE, sizeof(size_t),
&BinaryType, nullptr);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Program get build info command not supported by backend.");
} else {
Plugin->checkPiResult(Result);
}

switch (BinaryType) {
case (PI_PROGRAM_BINARY_TYPE_NONE):
if (State == bundle_state::object)
Expand Down Expand Up @@ -280,12 +354,21 @@ kernel make_kernel(const context &TargetContext,

// Create PI kernel first.
pi::PiKernel PiKernel = nullptr;
Plugin->call<PiApiKind::piextKernelCreateWithNativeHandle>(
NativeHandle, ContextImpl->getHandleRef(), PiProgram, !KeepOwnership,
&PiKernel);
sycl::detail::pi::PiResult Result =
Plugin->call_nocheck<PiApiKind::piextKernelCreateWithNativeHandle>(
NativeHandle, ContextImpl->getHandleRef(), PiProgram, !KeepOwnership,
&PiKernel);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Kernel create with native handle not supported by backend.");
} else {
Plugin->checkPiResult(Result);
}

if (Backend == backend::opencl)
if (Backend == backend::opencl) {
Plugin->call<PiApiKind::piKernelRetain>(PiKernel);
}

// Construct the SYCL queue from PI queue.
return detail::createSyclObjFromImpl<kernel>(
Expand Down
27 changes: 22 additions & 5 deletions sycl/source/backend/level_zero.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,16 @@ __SYCL_EXPORT device make_device(const platform &Platform,
const auto &PlatformImpl = getSyclObjImpl(Platform);
// Create PI device first.
pi::PiDevice PiDevice;
Plugin->call<PiApiKind::piextDeviceCreateWithNativeHandle>(
NativeHandle, PlatformImpl->getHandleRef(), &PiDevice);
sycl::detail::pi::PiResult Result =
Plugin->call_nocheck<PiApiKind::piextDeviceCreateWithNativeHandle>(
NativeHandle, PlatformImpl->getHandleRef(), &PiDevice);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Device create with native handle command not supported by backend.");
} else {
Plugin->checkPiResult(Result);
}

return detail::createSyclObjFromImpl<device>(
PlatformImpl->getOrMakeDeviceImpl(PiDevice, PlatformImpl));
Expand All @@ -51,9 +59,18 @@ __SYCL_EXPORT context make_context(const std::vector<device> &DeviceList,
for (auto Dev : DeviceList) {
DeviceHandles.push_back(detail::getSyclObjImpl(Dev)->getHandleRef());
}
Plugin->call<PiApiKind::piextContextCreateWithNativeHandle>(
NativeHandle, DeviceHandles.size(), DeviceHandles.data(), !KeepOwnership,
&PiContext);
sycl::detail::pi::PiResult Result =
Plugin->call_nocheck<PiApiKind::piextContextCreateWithNativeHandle>(
NativeHandle, DeviceHandles.size(), DeviceHandles.data(),
!KeepOwnership, &PiContext);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Context create with native handle command not supported by backend.");
} else {
Plugin->checkPiResult(Result);
}

// Construct the SYCL context from PI context.
return detail::createSyclObjFromImpl<context>(
std::make_shared<context_impl>(PiContext, detail::defaultAsyncHandler,
Expand Down
53 changes: 40 additions & 13 deletions sycl/source/backend/opencl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,31 @@ __SYCL_EXPORT bool has_extension(const sycl::platform &SyclPlatform,
// Manual invocation of plugin API to avoid using deprecated
// info::platform::extensions call.
size_t ResultSize = 0;
Plugin->call<PiApiKind::piPlatformGetInfo>(
PluginPlatform, PI_PLATFORM_INFO_EXTENSIONS, /*param_value_size=*/0,
/*param_value_size=*/nullptr, &ResultSize);
sycl::detail::pi::PiResult PiResult =
Plugin->call_nocheck<PiApiKind::piPlatformGetInfo>(
PluginPlatform, PI_PLATFORM_INFO_EXTENSIONS, /*param_value_size=*/0,
/*param_value_size=*/nullptr, &ResultSize);
if (PiResult == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Platform get info command not supported by backend.");
} else {
Plugin->checkPiResult(PiResult);
}
if (ResultSize == 0)
return false;

std::unique_ptr<char[]> Result(new char[ResultSize]);
Plugin->call<PiApiKind::piPlatformGetInfo>(PluginPlatform,
PI_PLATFORM_INFO_EXTENSIONS,
ResultSize, Result.get(), nullptr);
PiResult = Plugin->call_nocheck<PiApiKind::piPlatformGetInfo>(
PluginPlatform, PI_PLATFORM_INFO_EXTENSIONS, ResultSize, Result.get(),
nullptr);
if (PiResult == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Platform get info command not supported by backend.");
} else {
Plugin->checkPiResult(PiResult);
}

std::string_view ExtensionsString(Result.get());
return ExtensionsString.find(Extension) != std::string::npos;
Expand All @@ -98,16 +113,28 @@ __SYCL_EXPORT bool has_extension(const sycl::device &SyclDevice,
// Manual invocation of plugin API to avoid using deprecated
// info::device::extensions call.
size_t ResultSize = 0;
Plugin->call<PiApiKind::piDeviceGetInfo>(
PluginDevice, PI_DEVICE_INFO_EXTENSIONS, /*param_value_size=*/0,
/*param_value_size=*/nullptr, &ResultSize);
if (ResultSize == 0)
sycl::detail::pi::PiResult PiResult =
Plugin->call_nocheck<PiApiKind::piDeviceGetInfo>(
PluginDevice, PI_DEVICE_INFO_EXTENSIONS, /*param_value_size=*/0,
/*param_value_size=*/nullptr, &ResultSize);
if (PiResult == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Device get info command not supported by backend.");
}
if (ResultSize == 0) {
return false;
}

std::unique_ptr<char[]> Result(new char[ResultSize]);
Plugin->call<PiApiKind::piDeviceGetInfo>(PluginDevice,
PI_DEVICE_INFO_EXTENSIONS,
ResultSize, Result.get(), nullptr);
PiResult = Plugin->call_nocheck<PiApiKind::piDeviceGetInfo>(
PluginDevice, PI_DEVICE_INFO_EXTENSIONS, ResultSize, Result.get(),
nullptr);
if (PiResult == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Device get info command not supported by backend.");
}

std::string_view ExtensionsString(Result.get());
return ExtensionsString.find(Extension) != std::string::npos;
Expand Down
13 changes: 10 additions & 3 deletions sycl/source/detail/allowlist.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -377,9 +377,16 @@ void applyAllowList(std::vector<sycl::detail::pi::PiDevice> &PiDevices,
auto DeviceImpl = PlatformImpl->getOrMakeDeviceImpl(Device, PlatformImpl);
// get DeviceType value and put it to DeviceDesc
sycl::detail::pi::PiDeviceType PiDevType;
Plugin->call<PiApiKind::piDeviceGetInfo>(
Device, PI_DEVICE_INFO_TYPE, sizeof(sycl::detail::pi::PiDeviceType),
&PiDevType, nullptr);
sycl::detail::pi::PiResult Result =
Plugin->call_nocheck<PiApiKind::piDeviceGetInfo>(
Device, PI_DEVICE_INFO_TYPE, sizeof(sycl::detail::pi::PiDeviceType),
&PiDevType, nullptr);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Device get info command not supported by backend.");
}

sycl::info::device_type DeviceType = pi::cast<info::device_type>(PiDevType);
for (const auto &SyclDeviceType :
getSyclDeviceTypeMap<true /*Enable 'acc'*/>()) {
Expand Down
13 changes: 10 additions & 3 deletions sycl/source/detail/bindless_images.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,9 +172,16 @@ alloc_image_mem(const image_descriptor &desc, const sycl::device &syclDevice,
image_mem_handle retHandle;

// Call impl.
Plugin->call<sycl::errc::memory_allocation,
sycl::detail::PiApiKind::piextMemImageAllocate>(
C, Device, &piFormat, &piDesc, &retHandle.raw_handle);
sycl::detail::pi::PiResult Error =
Plugin->call_nocheck<sycl::detail::PiApiKind::piextMemImageAllocate>(
C, Device, &piFormat, &piDesc, &retHandle.raw_handle);
if (Error == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Bindless image alloc mem command not supported by backend.");
} else {
Plugin->checkPiResult(Error);
}

return retHandle;
}
Expand Down
12 changes: 10 additions & 2 deletions sycl/source/detail/buffer_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,16 @@ buffer_impl::getNativeVector(backend BackendName) const {
// When doing buffer interop we don't know what device the memory should be
// resident on, so pass nullptr for Device param. Buffer interop may not be
// supported by all backends.
Plugin->call<PiApiKind::piextMemGetNativeHandle>(NativeMem, /*Dev*/ nullptr,
&Handle);
sycl::detail::pi::PiResult Result =
Plugin->call_nocheck<PiApiKind::piextMemGetNativeHandle>(NativeMem,
&Handle);
if (Result == PI_ERROR_INVALID_OPERATION) {
throw sycl::exception(
sycl::make_error_code(sycl::errc::feature_not_supported),
"Mem get native handle command not supported by backend.");
} else {
Plugin->checkPiResult(Result);
}
Handles.push_back(Handle);
}

Expand Down
Loading

0 comments on commit cec923e

Please sign in to comment.