Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SYCL] Throw exception for unsupported UR features #12361

Open
wants to merge 2 commits into
base: sycl
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 100 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);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern seems to repeat a lot. Could we maybe make a new call_optional or call_ext or something along those lines?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your suggestion, it certainly would be good to refactor out the repetitiveness here. I wonder if it might be worth putting the check inside the pre-existing call or call_nocheck functions?


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,54 @@ 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.");
}
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.");
}

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.");
}

switch (BinaryType) {
case (PI_PROGRAM_BINARY_TYPE_NONE):
if (State == bundle_state::object)
Expand Down Expand Up @@ -280,12 +348,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
49 changes: 36 additions & 13 deletions sycl/source/backend/opencl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,27 @@ __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.");
}
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.");
}

std::string_view ExtensionsString(Result.get());
return ExtensionsString.find(Extension) != std::string::npos;
Expand All @@ -98,16 +109,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, /*Dev*/ nullptr, &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
Loading