diff --git a/sycl/source/backend.cpp b/sycl/source/backend.cpp index ed0539f266ee2..d6190f9a08a34 100644 --- a/sycl/source/backend.cpp +++ b/sycl/source/backend.cpp @@ -72,8 +72,16 @@ platform make_platform(pi_native_handle NativeHandle, backend Backend) { // Create PI platform first. pi::PiPlatform PiPlatform = nullptr; - Plugin->call(NativeHandle, - &PiPlatform); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + 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_impl::getOrMakePlatformImpl(PiPlatform, Plugin)); @@ -84,8 +92,16 @@ __SYCL_EXPORT device make_device(pi_native_handle NativeHandle, const auto &Plugin = getPlugin(Backend); pi::PiDevice PiDevice = nullptr; - Plugin->call( - NativeHandle, nullptr, &PiDevice); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + 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( std::make_shared(PiDevice, Plugin)); @@ -97,8 +113,16 @@ __SYCL_EXPORT context make_context(pi_native_handle NativeHandle, const auto &Plugin = getPlugin(Backend); pi::PiContext PiContext = nullptr; - Plugin->call( - NativeHandle, 0, nullptr, false, &PiContext); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + 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( std::make_shared(PiContext, Handler, Plugin)); @@ -130,9 +154,18 @@ __SYCL_EXPORT queue make_queue(pi_native_handle NativeHandle, // Create PI queue first. pi::PiQueue PiQueue = nullptr; - Plugin->call( - NativeHandle, NativeHandleDesc, ContextImpl->getHandleRef(), PiDevice, - !KeepOwnership, Properties, &PiQueue); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + 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( std::make_shared(PiQueue, ContextImpl, Handler, PropList)); @@ -150,8 +183,16 @@ __SYCL_EXPORT event make_event(pi_native_handle NativeHandle, const auto &ContextImpl = getSyclObjImpl(Context); pi::PiEvent PiEvent = nullptr; - Plugin->call( - NativeHandle, ContextImpl->getHandleRef(), !KeepOwnership, &PiEvent); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + 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( std::make_shared(PiEvent, Context)); @@ -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( - NativeHandle, ContextImpl->getHandleRef(), !KeepOwnership, &PiProgram); - if (ContextImpl->getBackend() == backend::opencl) + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + 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(PiProgram); + } std::vector ProgramDevices; uint32_t NumDevices = 0; - Plugin->call( + Result = Plugin->call_nocheck( 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(PiProgram, PI_PROGRAM_INFO_DEVICES, - sizeof(pi::PiDevice) * NumDevices, - ProgramDevices.data(), nullptr); + + Result = Plugin->call_nocheck( + 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( + Result = Plugin->call_nocheck( 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) @@ -280,12 +354,21 @@ kernel make_kernel(const context &TargetContext, // Create PI kernel first. pi::PiKernel PiKernel = nullptr; - Plugin->call( - NativeHandle, ContextImpl->getHandleRef(), PiProgram, !KeepOwnership, - &PiKernel); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + 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(PiKernel); + } // Construct the SYCL queue from PI queue. return detail::createSyclObjFromImpl( diff --git a/sycl/source/backend/level_zero.cpp b/sycl/source/backend/level_zero.cpp index 7f43f12c0cc4e..51239ae8c014b 100644 --- a/sycl/source/backend/level_zero.cpp +++ b/sycl/source/backend/level_zero.cpp @@ -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( - NativeHandle, PlatformImpl->getHandleRef(), &PiDevice); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + 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( PlatformImpl->getOrMakeDeviceImpl(PiDevice, PlatformImpl)); @@ -51,9 +59,18 @@ __SYCL_EXPORT context make_context(const std::vector &DeviceList, for (auto Dev : DeviceList) { DeviceHandles.push_back(detail::getSyclObjImpl(Dev)->getHandleRef()); } - Plugin->call( - NativeHandle, DeviceHandles.size(), DeviceHandles.data(), !KeepOwnership, - &PiContext); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + 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( std::make_shared(PiContext, detail::defaultAsyncHandler, diff --git a/sycl/source/backend/opencl.cpp b/sycl/source/backend/opencl.cpp index 5a282542c5b24..009144930d357 100644 --- a/sycl/source/backend/opencl.cpp +++ b/sycl/source/backend/opencl.cpp @@ -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( - PluginPlatform, PI_PLATFORM_INFO_EXTENSIONS, /*param_value_size=*/0, - /*param_value_size=*/nullptr, &ResultSize); + sycl::detail::pi::PiResult PiResult = + Plugin->call_nocheck( + 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 Result(new char[ResultSize]); - Plugin->call(PluginPlatform, - PI_PLATFORM_INFO_EXTENSIONS, - ResultSize, Result.get(), nullptr); + PiResult = Plugin->call_nocheck( + 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; @@ -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( - 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( + 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 Result(new char[ResultSize]); - Plugin->call(PluginDevice, - PI_DEVICE_INFO_EXTENSIONS, - ResultSize, Result.get(), nullptr); + PiResult = Plugin->call_nocheck( + 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; diff --git a/sycl/source/detail/allowlist.cpp b/sycl/source/detail/allowlist.cpp index d607090b185d3..26acd47521853 100644 --- a/sycl/source/detail/allowlist.cpp +++ b/sycl/source/detail/allowlist.cpp @@ -377,9 +377,16 @@ void applyAllowList(std::vector &PiDevices, auto DeviceImpl = PlatformImpl->getOrMakeDeviceImpl(Device, PlatformImpl); // get DeviceType value and put it to DeviceDesc sycl::detail::pi::PiDeviceType PiDevType; - Plugin->call( - Device, PI_DEVICE_INFO_TYPE, sizeof(sycl::detail::pi::PiDeviceType), - &PiDevType, nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + 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(PiDevType); for (const auto &SyclDeviceType : getSyclDeviceTypeMap()) { diff --git a/sycl/source/detail/bindless_images.cpp b/sycl/source/detail/bindless_images.cpp index f16437cb0cd7a..aaa0e29e47d93 100644 --- a/sycl/source/detail/bindless_images.cpp +++ b/sycl/source/detail/bindless_images.cpp @@ -172,9 +172,16 @@ alloc_image_mem(const image_descriptor &desc, const sycl::device &syclDevice, image_mem_handle retHandle; // Call impl. - Plugin->call( - C, Device, &piFormat, &piDesc, &retHandle.raw_handle); + sycl::detail::pi::PiResult Error = + Plugin->call_nocheck( + 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; } diff --git a/sycl/source/detail/buffer_impl.cpp b/sycl/source/detail/buffer_impl.cpp index 835c732a40bf9..4e48fffaa7d64 100644 --- a/sycl/source/detail/buffer_impl.cpp +++ b/sycl/source/detail/buffer_impl.cpp @@ -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(NativeMem, /*Dev*/ nullptr, - &Handle); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(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); } diff --git a/sycl/source/detail/context_impl.cpp b/sycl/source/detail/context_impl.cpp index 388c312305d4a..66931d1769396 100644 --- a/sycl/source/detail/context_impl.cpp +++ b/sycl/source/detail/context_impl.cpp @@ -327,10 +327,20 @@ DeviceImplPtr context_impl::findMatchingDeviceImpl( pi_native_handle context_impl::getNative() const { const auto &Plugin = getPlugin(); - if (getBackend() == backend::opencl) + if (getBackend() == backend::opencl) { Plugin->call(getHandleRef()); + } pi_native_handle Handle; - Plugin->call(getHandleRef(), &Handle); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + getHandleRef(), &Handle); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Context get native handle command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } return Handle; } @@ -388,8 +398,17 @@ std::vector context_impl::initializeDeviceGlobals( Event, Plugin) == info::event_command_status::complete; }); // Release the removed events. - for (auto EventIt = NewEnd; EventIt != InitEventsRef.end(); ++EventIt) - Plugin->call(*EventIt); + for (auto EventIt = NewEnd; EventIt != InitEventsRef.end(); ++EventIt) { + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(*EventIt); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event release command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } + } // Remove them from the collection. InitEventsRef.erase(NewEnd, InitEventsRef.end()); // If there are no more events, we can mark it as fully initialized. @@ -446,10 +465,20 @@ std::vector context_impl::initializeDeviceGlobals( // initialize events list. sycl::detail::pi::PiEvent InitEvent; void *const &USMPtr = DeviceGlobalUSM.getPtr(); - Plugin->call( - QueueImpl->getHandleRef(), NativePrg, - DeviceGlobalEntry->MUniqueId.c_str(), false, sizeof(void *), 0, - &USMPtr, 0, nullptr, &InitEvent); + sycl::detail::pi::PiResult Result = + Plugin + ->call_nocheck( + QueueImpl->getHandleRef(), NativePrg, + DeviceGlobalEntry->MUniqueId.c_str(), false, sizeof(void *), + 0, &USMPtr, 0, nullptr, &InitEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue device global variable write command not supported by " + "backend."); + } else { + Plugin->checkPiResult(Result); + } InitEventsRef.push_back(InitEvent); } @@ -459,8 +488,17 @@ std::vector context_impl::initializeDeviceGlobals( void context_impl::DeviceGlobalInitializer::ClearEvents( const PluginPtr &Plugin) { - for (const sycl::detail::pi::PiEvent &Event : MDeviceGlobalInitEvents) - Plugin->call(Event); + for (const sycl::detail::pi::PiEvent &Event : MDeviceGlobalInitEvents) { + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(Event); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event release command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } + } MDeviceGlobalInitEvents.clear(); } diff --git a/sycl/source/detail/device_global_map_entry.cpp b/sycl/source/detail/device_global_map_entry.cpp index d55bf31ff2e3a..2f15bfd573d30 100644 --- a/sycl/source/detail/device_global_map_entry.cpp +++ b/sycl/source/detail/device_global_map_entry.cpp @@ -31,7 +31,15 @@ OwnedPiEvent DeviceGlobalUSMMem::getInitEvent(const PluginPtr &Plugin) { if (MInitEvent.has_value()) { if (get_event_info( *MInitEvent, Plugin) == info::event_command_status::complete) { - Plugin->call(*MInitEvent); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(*MInitEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event release command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } MInitEvent = {}; return OwnedPiEvent(Plugin); } else { @@ -98,9 +106,18 @@ void DeviceGlobalMapEntry::removeAssociatedResources( if (USMPtrIt != MDeviceToUSMPtrMap.end()) { DeviceGlobalUSMMem &USMMem = USMPtrIt->second; detail::usm::freeInternal(USMMem.MPtr, CtxImpl); - if (USMMem.MInitEvent.has_value()) - CtxImpl->getPlugin()->call( - *USMMem.MInitEvent); + if (USMMem.MInitEvent.has_value()) { + sycl::detail::pi::PiResult Result = + CtxImpl->getPlugin()->call_nocheck( + *USMMem.MInitEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event release command not supported by backend."); + } else { + CtxImpl->getPlugin()->checkPiResult(Result); + } + } #ifndef NDEBUG // For debugging we set the event and memory to some recognizable values // to allow us to check that this cleanup happens before erasure. diff --git a/sycl/source/detail/device_image_impl.hpp b/sycl/source/detail/device_image_impl.hpp index f21bf3ccd0185..05ad68ebdb7b5 100644 --- a/sycl/source/detail/device_image_impl.hpp +++ b/sycl/source/detail/device_image_impl.hpp @@ -290,11 +290,21 @@ class device_image_impl { const auto &ContextImplPtr = detail::getSyclObjImpl(MContext); const PluginPtr &Plugin = ContextImplPtr->getPlugin(); - if (ContextImplPtr->getBackend() == backend::opencl) + if (ContextImplPtr->getBackend() == backend::opencl) { Plugin->call(MProgram); + } pi_native_handle NativeProgram = 0; - Plugin->call(MProgram, - &NativeProgram); + + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + MProgram, &NativeProgram); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Program get native handle command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } return NativeProgram; } diff --git a/sycl/source/detail/device_impl.cpp b/sycl/source/detail/device_impl.cpp index 4494e790507d3..5a9a352f5c9ae 100644 --- a/sycl/source/detail/device_impl.cpp +++ b/sycl/source/detail/device_impl.cpp @@ -43,27 +43,46 @@ device_impl::device_impl(pi_native_handle InteropDeviceHandle, MDeviceHostBaseTime(std::make_pair(0, 0)) { bool InteroperabilityConstructor = false; + sycl::detail::pi::PiResult Result = PI_SUCCESS; if (Device == nullptr) { assert(InteropDeviceHandle); // Get PI device from the raw device handle. // NOTE: this is for OpenCL interop only (and should go away). // With SYCL-2020 BE generalization "make" functions are used instead. - Plugin->call( - InteropDeviceHandle, nullptr, &MDevice); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + InteropDeviceHandle, nullptr, &MDevice); + 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); + } InteroperabilityConstructor = true; } // TODO catch an exception and put it to list of asynchronous exceptions - Plugin->call( + Result = Plugin->call_nocheck( MDevice, PI_DEVICE_INFO_TYPE, sizeof(sycl::detail::pi::PiDeviceType), &MType, 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."); + } // No need to set MRootDevice when MAlwaysRootDevice is true if ((Platform == nullptr) || !Platform->MAlwaysRootDevice) { // TODO catch an exception and put it to list of asynchronous exceptions - Plugin->call( + Result = Plugin->call_nocheck( MDevice, PI_DEVICE_INFO_PARENT_DEVICE, sizeof(sycl::detail::pi::PiDevice), &MRootDevice, 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."); + } } if (!InteroperabilityConstructor) { @@ -201,13 +220,20 @@ device_impl::create_sub_devices(const cl_device_partition_property *Properties, std::vector SubDevices(SubDevicesCount); pi_uint32 ReturnedSubDevices = 0; const PluginPtr &Plugin = getPlugin(); - Plugin->call( - MDevice, Properties, SubDevicesCount, SubDevices.data(), - &ReturnedSubDevices); - if (ReturnedSubDevices != SubDevicesCount) { + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + MDevice, Properties, SubDevicesCount, SubDevices.data(), + &ReturnedSubDevices); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Device partition command not supported by backend."); + } else if (ReturnedSubDevices != SubDevicesCount) { throw sycl::exception( errc::invalid, "Could not partition to the specified number of sub-devices"); + } else { + Plugin->checkPiResult(Result); } // TODO: Need to describe the subdevice model. Some sub_device management // may be necessary. What happens if create_sub_devices is called multiple @@ -345,7 +371,16 @@ pi_native_handle device_impl::getNative() const { if (getBackend() == backend::opencl) Plugin->call(getHandleRef()); pi_native_handle Handle; - Plugin->call(getHandleRef(), &Handle); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + getHandleRef(), &Handle); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Device get native handle command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } return Handle; } @@ -412,53 +447,143 @@ bool device_impl::has(aspect Aspect) const { return get_info(); case aspect::usm_system_allocations: return get_info(); - case aspect::ext_intel_device_id: - return getPlugin()->call_nocheck( - MDevice, PI_DEVICE_INFO_DEVICE_ID, 0, nullptr, &return_size) == - PI_SUCCESS; - case aspect::ext_intel_pci_address: - return getPlugin()->call_nocheck( - MDevice, PI_DEVICE_INFO_PCI_ADDRESS, 0, nullptr, &return_size) == - PI_SUCCESS; - case aspect::ext_intel_gpu_eu_count: - return getPlugin()->call_nocheck( - MDevice, PI_DEVICE_INFO_GPU_EU_COUNT, 0, nullptr, - &return_size) == PI_SUCCESS; - case aspect::ext_intel_gpu_eu_simd_width: - return getPlugin()->call_nocheck( - MDevice, PI_DEVICE_INFO_GPU_EU_SIMD_WIDTH, 0, nullptr, - &return_size) == PI_SUCCESS; - case aspect::ext_intel_gpu_slices: - return getPlugin()->call_nocheck( - MDevice, PI_DEVICE_INFO_GPU_SLICES, 0, nullptr, &return_size) == - PI_SUCCESS; - case aspect::ext_intel_gpu_subslices_per_slice: - return getPlugin()->call_nocheck( - MDevice, PI_DEVICE_INFO_GPU_SUBSLICES_PER_SLICE, 0, nullptr, - &return_size) == PI_SUCCESS; - case aspect::ext_intel_gpu_eu_count_per_subslice: - return getPlugin()->call_nocheck( - MDevice, PI_DEVICE_INFO_GPU_EU_COUNT_PER_SUBSLICE, 0, nullptr, - &return_size) == PI_SUCCESS; - case aspect::ext_intel_gpu_hw_threads_per_eu: - return getPlugin()->call_nocheck( - MDevice, PI_DEVICE_INFO_GPU_HW_THREADS_PER_EU, 0, nullptr, - &return_size) == PI_SUCCESS; - case aspect::ext_intel_free_memory: - return getPlugin()->call_nocheck( - MDevice, PI_EXT_INTEL_DEVICE_INFO_FREE_MEMORY, 0, nullptr, - &return_size) == PI_SUCCESS; - case aspect::ext_intel_memory_clock_rate: - return getPlugin()->call_nocheck( - MDevice, PI_EXT_INTEL_DEVICE_INFO_MEMORY_CLOCK_RATE, 0, nullptr, - &return_size) == PI_SUCCESS; - case aspect::ext_intel_memory_bus_width: - return getPlugin()->call_nocheck( - MDevice, PI_EXT_INTEL_DEVICE_INFO_MEMORY_BUS_WIDTH, 0, nullptr, - &return_size) == PI_SUCCESS; + case aspect::ext_intel_device_id: { + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MDevice, PI_DEVICE_INFO_DEVICE_ID, 0, nullptr, &return_size); + 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."); + }; + return Result == PI_SUCCESS; + } + case aspect::ext_intel_pci_address: { + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MDevice, PI_DEVICE_INFO_PCI_ADDRESS, 0, nullptr, &return_size); + 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."); + }; + return Result == PI_SUCCESS; + } + case aspect::ext_intel_gpu_eu_count: { + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MDevice, PI_DEVICE_INFO_GPU_EU_COUNT, 0, nullptr, &return_size); + 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."); + }; + return Result == PI_SUCCESS; + } + case aspect::ext_intel_gpu_eu_simd_width: { + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MDevice, PI_DEVICE_INFO_GPU_EU_SIMD_WIDTH, 0, nullptr, + &return_size); + 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."); + }; + return Result == PI_SUCCESS; + } + case aspect::ext_intel_gpu_slices: { + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MDevice, PI_DEVICE_INFO_GPU_SLICES, 0, nullptr, &return_size); + 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."); + }; + return Result == PI_SUCCESS; + } + case aspect::ext_intel_gpu_subslices_per_slice: { + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MDevice, PI_DEVICE_INFO_GPU_SUBSLICES_PER_SLICE, 0, nullptr, + &return_size); + 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."); + }; + return Result == PI_SUCCESS; + } + case aspect::ext_intel_gpu_eu_count_per_subslice: { + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MDevice, PI_DEVICE_INFO_GPU_EU_COUNT_PER_SUBSLICE, 0, nullptr, + &return_size); + 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."); + }; + return Result == PI_SUCCESS; + } + case aspect::ext_intel_gpu_hw_threads_per_eu: { + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MDevice, PI_DEVICE_INFO_GPU_HW_THREADS_PER_EU, 0, nullptr, + &return_size); + 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."); + }; + return Result == PI_SUCCESS; + } + case aspect::ext_intel_free_memory: { + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MDevice, PI_EXT_INTEL_DEVICE_INFO_FREE_MEMORY, 0, nullptr, + &return_size); + 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."); + }; + return Result == PI_SUCCESS; + } + case aspect::ext_intel_memory_clock_rate: { + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MDevice, PI_EXT_INTEL_DEVICE_INFO_MEMORY_CLOCK_RATE, 0, nullptr, + &return_size); + 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."); + }; + return Result == PI_SUCCESS; + } + case aspect::ext_intel_memory_bus_width: { + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MDevice, PI_EXT_INTEL_DEVICE_INFO_MEMORY_BUS_WIDTH, 0, nullptr, + &return_size); + 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."); + }; + return Result == PI_SUCCESS; + } case aspect::ext_intel_device_info_uuid: { - auto Result = getPlugin()->call_nocheck( - MDevice, PI_DEVICE_INFO_UUID, 0, nullptr, &return_size); + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MDevice, PI_DEVICE_INFO_UUID, 0, nullptr, &return_size); + 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."); + }; if (Result != PI_SUCCESS) { return false; } @@ -466,9 +591,15 @@ bool device_impl::has(aspect Aspect) const { assert(return_size <= 16); unsigned char UUID[16]; - return getPlugin()->call_nocheck( - MDevice, PI_DEVICE_INFO_UUID, 16 * sizeof(unsigned char), UUID, - nullptr) == PI_SUCCESS; + Result = getPlugin()->call_nocheck( + MDevice, PI_DEVICE_INFO_UUID, 16 * sizeof(unsigned char), UUID, + 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."); + }; + return Result == PI_SUCCESS; } case aspect::ext_intel_max_mem_bandwidth: // currently not supported @@ -479,116 +610,200 @@ bool device_impl::has(aspect Aspect) const { return isAssertFailSupported(); case aspect::ext_oneapi_cuda_async_barrier: { int async_barrier_supported; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_EXT_ONEAPI_DEVICE_INFO_CUDA_ASYNC_BARRIER, sizeof(int), - &async_barrier_supported, nullptr) == PI_SUCCESS; - return call_successful && async_barrier_supported; + &async_barrier_supported, 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."); + }; + + return (Result == PI_SUCCESS) && async_barrier_supported; } case aspect::ext_intel_legacy_image: { pi_bool legacy_image_support = PI_FALSE; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_DEVICE_INFO_IMAGE_SUPPORT, sizeof(pi_bool), - &legacy_image_support, nullptr) == PI_SUCCESS; - return call_successful && legacy_image_support; + &legacy_image_support, 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."); + }; + + return (Result == PI_SUCCESS) && legacy_image_support; } case aspect::ext_oneapi_bindless_images: { pi_bool support = PI_FALSE; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_EXT_ONEAPI_DEVICE_INFO_BINDLESS_IMAGES_SUPPORT, - sizeof(pi_bool), &support, nullptr) == PI_SUCCESS; - return call_successful && support; + sizeof(pi_bool), &support, 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."); + }; + + return (Result == PI_SUCCESS) && support; } case aspect::ext_oneapi_bindless_images_shared_usm: { pi_bool support = PI_FALSE; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_EXT_ONEAPI_DEVICE_INFO_BINDLESS_IMAGES_SHARED_USM_SUPPORT, - sizeof(pi_bool), &support, nullptr) == PI_SUCCESS; - return call_successful && support; + sizeof(pi_bool), &support, 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."); + }; + + return (Result == PI_SUCCESS) && support; } case aspect::ext_oneapi_bindless_images_1d_usm: { pi_bool support = PI_FALSE; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_EXT_ONEAPI_DEVICE_INFO_BINDLESS_IMAGES_1D_USM_SUPPORT, - sizeof(pi_bool), &support, nullptr) == PI_SUCCESS; - return call_successful && support; + sizeof(pi_bool), &support, 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."); + }; + + return (Result == PI_SUCCESS) && support; } case aspect::ext_oneapi_bindless_images_2d_usm: { pi_bool support = PI_FALSE; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_EXT_ONEAPI_DEVICE_INFO_BINDLESS_IMAGES_2D_USM_SUPPORT, - sizeof(pi_bool), &support, nullptr) == PI_SUCCESS; - return call_successful && support; + sizeof(pi_bool), &support, 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."); + }; + + return (Result == PI_SUCCESS) && support; } case aspect::ext_oneapi_interop_memory_import: { pi_bool support = PI_FALSE; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_EXT_ONEAPI_DEVICE_INFO_INTEROP_MEMORY_IMPORT_SUPPORT, - sizeof(pi_bool), &support, nullptr) == PI_SUCCESS; - return call_successful && support; + sizeof(pi_bool), &support, 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."); + }; + + return (Result == PI_SUCCESS) && support; } case aspect::ext_oneapi_interop_memory_export: { pi_bool support = PI_FALSE; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_EXT_ONEAPI_DEVICE_INFO_INTEROP_MEMORY_EXPORT_SUPPORT, - sizeof(pi_bool), &support, nullptr) == PI_SUCCESS; - return call_successful && support; + sizeof(pi_bool), &support, 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."); + }; + + return (Result == PI_SUCCESS) && support; } case aspect::ext_oneapi_interop_semaphore_import: { pi_bool support = PI_FALSE; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_EXT_ONEAPI_DEVICE_INFO_INTEROP_SEMAPHORE_IMPORT_SUPPORT, - sizeof(pi_bool), &support, nullptr) == PI_SUCCESS; - return call_successful && support; + sizeof(pi_bool), &support, 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."); + }; + + return (Result == PI_SUCCESS) && support; } case aspect::ext_oneapi_interop_semaphore_export: { pi_bool support = PI_FALSE; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_EXT_ONEAPI_DEVICE_INFO_INTEROP_SEMAPHORE_EXPORT_SUPPORT, - sizeof(pi_bool), &support, nullptr) == PI_SUCCESS; - return call_successful && support; + sizeof(pi_bool), &support, 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."); + }; + + return (Result == PI_SUCCESS) && support; } case aspect::ext_oneapi_mipmap: { pi_bool support = PI_FALSE; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_EXT_ONEAPI_DEVICE_INFO_MIPMAP_SUPPORT, sizeof(pi_bool), - &support, nullptr) == PI_SUCCESS; - return call_successful && support; + &support, 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."); + }; + + return (Result == PI_SUCCESS) && support; } case aspect::ext_oneapi_mipmap_anisotropy: { pi_bool support = PI_FALSE; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_EXT_ONEAPI_DEVICE_INFO_MIPMAP_ANISOTROPY_SUPPORT, - sizeof(pi_bool), &support, nullptr) == PI_SUCCESS; - return call_successful && support; + sizeof(pi_bool), &support, 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."); + }; + + return (Result == PI_SUCCESS) && support; } case aspect::ext_oneapi_mipmap_level_reference: { pi_bool support = PI_FALSE; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_EXT_ONEAPI_DEVICE_INFO_MIPMAP_LEVEL_REFERENCE_SUPPORT, - sizeof(pi_bool), &support, nullptr) == PI_SUCCESS; - return call_successful && support; + sizeof(pi_bool), &support, 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."); + }; + + return (Result == PI_SUCCESS) && support; } case aspect::ext_intel_esimd: { pi_bool support = PI_FALSE; - bool call_successful = + sycl::detail::pi::PiResult Result = getPlugin()->call_nocheck( MDevice, PI_EXT_INTEL_DEVICE_INFO_ESIMD_SUPPORT, sizeof(pi_bool), - &support, nullptr) == PI_SUCCESS; - return call_successful && support; + &support, 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."); + }; + + return (Result == PI_SUCCESS) && support; } case aspect::ext_oneapi_ballot_group: case aspect::ext_oneapi_fixed_size_group: diff --git a/sycl/source/detail/device_info.hpp b/sycl/source/detail/device_info.hpp index a56281b862ef3..a633fb984636c 100644 --- a/sycl/source/detail/device_info.hpp +++ b/sycl/source/detail/device_info.hpp @@ -139,9 +139,15 @@ template <> struct check_fp_support { template struct get_device_info_impl { static ReturnT get(const DeviceImplPtr &Dev) { typename sycl_to_pi::type result; - Dev->getPlugin()->call( - Dev->getHandleRef(), PiInfoCode::value, sizeof(result), &result, - nullptr); + sycl::detail::pi::PiResult PiResult = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), PiInfoCode::value, sizeof(result), + &result, 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."); + } return ReturnT(result); } }; @@ -150,9 +156,15 @@ template struct get_device_info_impl { template struct get_device_info_impl { static platform get(const DeviceImplPtr &Dev) { typename sycl_to_pi::type result; - Dev->getPlugin()->call( - Dev->getHandleRef(), PiInfoCode::value, sizeof(result), &result, - nullptr); + sycl::detail::pi::PiResult PiResult = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), PiInfoCode::value, sizeof(result), + &result, 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."); + } // TODO: Change PiDevice to device_impl. // Use the Plugin from the device_impl class after plugin details // are added to the class. @@ -166,14 +178,26 @@ template struct get_device_info_impl { inline std::string device_impl::get_device_info_string( sycl::detail::pi::PiDeviceInfo InfoCode) const { size_t resultSize = 0; - getPlugin()->call(getHandleRef(), InfoCode, 0, - nullptr, &resultSize); + sycl::detail::pi::PiResult PiResult = + getPlugin()->call_nocheck( + getHandleRef(), InfoCode, 0, 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 std::string(); } + std::unique_ptr result(new char[resultSize]); - getPlugin()->call( + getPlugin()->call_nocheck( getHandleRef(), InfoCode, 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."); + } return std::string(result.get()); } @@ -202,9 +226,15 @@ struct get_device_info_impl, Param> { return {}; } cl_device_fp_config result; - Dev->getPlugin()->call( - Dev->getHandleRef(), PiInfoCode::value, sizeof(result), &result, - nullptr); + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), PiInfoCode::value, sizeof(result), + &result, 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."); + } return read_fp_bitfield(result); } }; @@ -223,9 +253,16 @@ struct get_device_info_impl, info::device::single_fp_config> { static std::vector get(const DeviceImplPtr &Dev) { pi_device_fp_config result; - Dev->getPlugin()->call( - Dev->getHandleRef(), PiInfoCode::value, - sizeof(result), &result, nullptr); + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, sizeof(result), + &result, 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."); + } return read_fp_bitfield(result); } }; @@ -236,9 +273,16 @@ struct get_device_info_impl, template <> struct get_device_info_impl { static bool get(const DeviceImplPtr &Dev) { pi_queue_properties Properties; - Dev->getPlugin()->call( - Dev->getHandleRef(), PiInfoCode::value, - sizeof(Properties), &Properties, nullptr); + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + sizeof(Properties), &Properties, 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."); + } return Properties & PI_QUEUE_FLAG_PROFILING_ENABLE; } }; @@ -249,10 +293,16 @@ struct get_device_info_impl, info::device::atomic_memory_order_capabilities> { static std::vector get(const DeviceImplPtr &Dev) { pi_memory_order_capabilities result; - Dev->getPlugin()->call( - Dev->getHandleRef(), - PiInfoCode::value, - sizeof(pi_memory_order_capabilities), &result, nullptr); + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + sizeof(pi_memory_order_capabilities), &result, 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."); + } return readMemoryOrderBitfield(result); } }; @@ -263,10 +313,16 @@ struct get_device_info_impl, info::device::atomic_fence_order_capabilities> { static std::vector get(const DeviceImplPtr &Dev) { pi_memory_order_capabilities result; - Dev->getPlugin()->call( - Dev->getHandleRef(), - PiInfoCode::value, - sizeof(pi_memory_order_capabilities), &result, nullptr); + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + sizeof(pi_memory_order_capabilities), &result, 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."); + } return readMemoryOrderBitfield(result); } }; @@ -277,10 +333,16 @@ struct get_device_info_impl, info::device::atomic_memory_scope_capabilities> { static std::vector get(const DeviceImplPtr &Dev) { pi_memory_scope_capabilities result; - Dev->getPlugin()->call( - Dev->getHandleRef(), - PiInfoCode::value, - sizeof(pi_memory_scope_capabilities), &result, nullptr); + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + sizeof(pi_memory_scope_capabilities), &result, 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."); + } return readMemoryScopeBitfield(result); } }; @@ -291,10 +353,16 @@ struct get_device_info_impl, info::device::atomic_fence_scope_capabilities> { static std::vector get(const DeviceImplPtr &Dev) { pi_memory_scope_capabilities result; - Dev->getPlugin()->call( - Dev->getHandleRef(), - PiInfoCode::value, - sizeof(pi_memory_scope_capabilities), &result, nullptr); + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + sizeof(pi_memory_scope_capabilities), &result, 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."); + } return readMemoryScopeBitfield(result); } }; @@ -306,13 +374,15 @@ struct get_device_info_implgetPlugin()->call_nocheck( Dev->getHandleRef(), PiInfoCode::value, sizeof(result), &result, nullptr); - if (Err != PI_SUCCESS) { - return false; + 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."); } return result; } @@ -324,10 +394,17 @@ struct get_device_info_impl, info::device::execution_capabilities> { static std::vector get(const DeviceImplPtr &Dev) { pi_device_exec_capabilities result; - Dev->getPlugin()->call( - Dev->getHandleRef(), - PiInfoCode::value, sizeof(result), - &result, nullptr); + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + sizeof(result), &result, 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."); + } + return read_execution_bitfield(result); } }; @@ -393,18 +470,30 @@ struct get_device_info_impl, const auto &Plugin = Dev->getPlugin(); size_t resultSize; - Plugin->call( - Dev->getHandleRef(), info_partition, 0, nullptr, &resultSize); + sycl::detail::pi::PiResult PiResult = + Plugin->call_nocheck( + Dev->getHandleRef(), info_partition, 0, 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."); + } size_t arrayLength = resultSize / sizeof(cl_device_partition_property); if (arrayLength == 0) { return {}; } + std::unique_ptr arrayResult( new cl_device_partition_property[arrayLength]); - Plugin->call(Dev->getHandleRef(), - info_partition, resultSize, - arrayResult.get(), nullptr); + PiResult = Plugin->call_nocheck( + Dev->getHandleRef(), info_partition, resultSize, arrayResult.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::vector result; for (size_t i = 0; i < arrayLength; ++i) { @@ -426,10 +515,17 @@ struct get_device_info_impl, static std::vector get(const DeviceImplPtr &Dev) { pi_device_affinity_domain result; - Dev->getPlugin()->call( - Dev->getHandleRef(), - PiInfoCode::value, - sizeof(result), &result, nullptr); + sycl::detail::pi::PiResult PiResult = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + sizeof(result), &result, 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."); + } + return read_domain_bitfield(result); } }; @@ -441,18 +537,31 @@ struct get_device_info_impl { static info::partition_affinity_domain get(const DeviceImplPtr &Dev) { size_t resultSize; - Dev->getPlugin()->call( - Dev->getHandleRef(), - PiInfoCode::value, 0, - nullptr, &resultSize); + sycl::detail::pi::PiResult PiResult = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, 0, + 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 != 1) { return info::partition_affinity_domain::not_applicable; } + cl_device_partition_property result; Dev->getPlugin()->call( Dev->getHandleRef(), PiInfoCode::value, sizeof(result), &result, 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."); + } + if (result == PI_DEVICE_AFFINITY_DOMAIN_NUMA || result == PI_DEVICE_AFFINITY_DOMAIN_L4_CACHE || result == PI_DEVICE_AFFINITY_DOMAIN_L3_CACHE || @@ -471,21 +580,36 @@ struct get_device_info_impl { static info::partition_property get(const DeviceImplPtr &Dev) { size_t resultSize; - Dev->getPlugin()->call( - Dev->getHandleRef(), PI_DEVICE_INFO_PARTITION_TYPE, 0, nullptr, - &resultSize); - if (!resultSize) + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), PI_DEVICE_INFO_PARTITION_TYPE, 0, nullptr, + &resultSize); + 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."); + } + if (!resultSize) { return info::partition_property::no_partition; + } size_t arrayLength = resultSize / sizeof(cl_device_partition_property); std::unique_ptr arrayResult( new cl_device_partition_property[arrayLength]); - Dev->getPlugin()->call( + Dev->getPlugin()->call_nocheck( Dev->getHandleRef(), PI_DEVICE_INFO_PARTITION_TYPE, resultSize, arrayResult.get(), nullptr); - if (!arrayResult[0]) + 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."); + } + + if (!arrayResult[0]) { return info::partition_property::no_partition; +# + } return info::partition_property(arrayResult[0]); } }; @@ -495,14 +619,27 @@ struct get_device_info_impl, info::device::sub_group_sizes> { static std::vector get(const DeviceImplPtr &Dev) { size_t resultSize = 0; - Dev->getPlugin()->call( - Dev->getHandleRef(), PiInfoCode::value, - 0, nullptr, &resultSize); + sycl::detail::pi::PiResult PiResult = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, 0, 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."); + } std::vector result(resultSize / sizeof(size_t)); - Dev->getPlugin()->call( + PiResult = Dev->getPlugin()->call_nocheck( Dev->getHandleRef(), PiInfoCode::value, resultSize, result.data(), 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."); + } + return result; } }; @@ -550,10 +687,17 @@ struct get_device_info_impl, info::device::max_work_item_sizes> { static range get(const DeviceImplPtr &Dev) { size_t result[3]; - Dev->getPlugin()->call( - Dev->getHandleRef(), - PiInfoCode>::value, - sizeof(result), &result, nullptr); + sycl::detail::pi::PiResult PiResult = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode>::value, + sizeof(result), &result, 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."); + } + return construct_range(result); } }; @@ -654,6 +798,8 @@ struct get_device_info_impl< ext::oneapi::experimental::info::device::architecture> { static ext::oneapi::experimental::architecture get(const DeviceImplPtr &Dev) { backend CurrentBackend = Dev->getBackend(); + sycl::detail::pi::PiResult Result = PI_SUCCESS; + if (Dev->is_gpu() && (backend::ext_oneapi_level_zero == CurrentBackend || backend::opencl == CurrentBackend)) { auto MapArchIDToArchName = [](const int arch) { @@ -666,12 +812,19 @@ struct get_device_info_impl< "The current device architecture is not supported by " "sycl_ext_oneapi_device_architecture."); }; + uint32_t DeviceIp; - Dev->getPlugin()->call( + Result = Dev->getPlugin()->call_nocheck( Dev->getHandleRef(), PiInfoCode< ext::oneapi::experimental::info::device::architecture>::value, sizeof(DeviceIp), &DeviceIp, 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."); + } + return MapArchIDToArchName(DeviceIp); } else if (Dev->is_gpu() && (backend::ext_oneapi_cuda == CurrentBackend || backend::ext_oneapi_hip == CurrentBackend)) { @@ -685,17 +838,31 @@ struct get_device_info_impl< "The current device architecture is not supported by " "sycl_ext_oneapi_device_architecture."); }; + size_t ResultSize = 0; - Dev->getPlugin()->call( + Result = Dev->getPlugin()->call_nocheck( Dev->getHandleRef(), PiInfoCode::value, 0, nullptr, &ResultSize); + 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."); + } + std::unique_ptr DeviceArch(new char[ResultSize]); - Dev->getPlugin()->call( + Result = Dev->getPlugin()->call_nocheck( Dev->getHandleRef(), PiInfoCode::value, ResultSize, DeviceArch.get(), 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."); + } + std::string DeviceArchCopy(DeviceArch.get()); std::string DeviceArchSubstr = DeviceArchCopy.substr(0, DeviceArchCopy.find(":")); + return MapArchIDToArchName(DeviceArchSubstr.data()); } else if (Dev->is_cpu() && backend::opencl == CurrentBackend) { auto MapArchIDToArchName = [](const int arch) { @@ -705,12 +872,19 @@ struct get_device_info_impl< } return sycl::ext::oneapi::experimental::architecture::x86_64; }; + uint32_t DeviceIp; - Dev->getPlugin()->call( + Result = Dev->getPlugin()->call_nocheck( Dev->getHandleRef(), PiInfoCode< ext::oneapi::experimental::info::device::architecture>::value, sizeof(DeviceIp), &DeviceIp, 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."); + } + return MapArchIDToArchName(DeviceIp); } // else is not needed // TODO: add support of other architectures by extending with else if @@ -955,11 +1129,18 @@ struct get_device_info_impl< size_t Limit = get_device_info_impl::get(Dev); - Dev->getPlugin()->call( - Dev->getHandleRef(), - PiInfoCode< - ext::oneapi::experimental::info::device::max_work_groups<3>>::value, - sizeof(result), &result, nullptr); + sycl::detail::pi::PiResult PiResult = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode>::value, + sizeof(result), &result, 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."); + } + return id<1>(std::min(Limit, result[0])); } }; @@ -972,11 +1153,18 @@ struct get_device_info_impl< size_t Limit = get_device_info_impl::get(Dev); - Dev->getPlugin()->call( - Dev->getHandleRef(), - PiInfoCode< - ext::oneapi::experimental::info::device::max_work_groups<3>>::value, - sizeof(result), &result, nullptr); + sycl::detail::pi::PiResult PiResult = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode>::value, + sizeof(result), &result, 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."); + } + return id<2>(std::min(Limit, result[1]), std::min(Limit, result[0])); } }; @@ -989,11 +1177,18 @@ struct get_device_info_impl< size_t Limit = get_device_info_impl::get(Dev); - Dev->getPlugin()->call( - Dev->getHandleRef(), - PiInfoCode< - ext::oneapi::experimental::info::device::max_work_groups<3>>::value, - sizeof(result), &result, nullptr); + sycl::detail::pi::PiResult PiResult = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode>::value, + sizeof(result), &result, 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."); + } + return id<3>(std::min(Limit, result[2]), std::min(Limit, result[1]), std::min(Limit, result[0])); } @@ -1051,9 +1246,16 @@ struct get_device_info_impl, template <> struct get_device_info_impl { static device get(const DeviceImplPtr &Dev) { typename sycl_to_pi::type result; - Dev->getPlugin()->call( - Dev->getHandleRef(), PiInfoCode::value, - sizeof(result), &result, nullptr); + sycl::detail::pi::PiResult PiResult = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), PiInfoCode::value, + sizeof(result), &result, 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."); + } + if (result == nullptr) throw invalid_object_error( "No parent for device because it is not a subdevice", @@ -1080,12 +1282,18 @@ template <> struct get_device_info_impl { static bool get(const DeviceImplPtr &Dev) { pi_usm_capabilities caps; - pi_result Err = Dev->getPlugin()->call_nocheck( - Dev->getHandleRef(), - PiInfoCode::value, - sizeof(pi_usm_capabilities), &caps, nullptr); + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + sizeof(pi_usm_capabilities), &caps, 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."); + } - return (Err != PI_SUCCESS) ? false : (caps & PI_USM_ACCESS); + return (Result != PI_SUCCESS) ? false : (caps & PI_USM_ACCESS); } }; @@ -1094,12 +1302,18 @@ template <> struct get_device_info_impl { static bool get(const DeviceImplPtr &Dev) { pi_usm_capabilities caps; - pi_result Err = Dev->getPlugin()->call_nocheck( - Dev->getHandleRef(), - PiInfoCode::value, - sizeof(pi_usm_capabilities), &caps, nullptr); + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + sizeof(pi_usm_capabilities), &caps, 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."); + } - return (Err != PI_SUCCESS) ? false : (caps & PI_USM_ACCESS); + return (Result != PI_SUCCESS) ? false : (caps & PI_USM_ACCESS); } }; @@ -1108,11 +1322,18 @@ template <> struct get_device_info_impl { static bool get(const DeviceImplPtr &Dev) { pi_usm_capabilities caps; - pi_result Err = Dev->getPlugin()->call_nocheck( - Dev->getHandleRef(), - PiInfoCode::value, - sizeof(pi_usm_capabilities), &caps, nullptr); - return (Err != PI_SUCCESS) ? false : (caps & PI_USM_ACCESS); + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + sizeof(pi_usm_capabilities), &caps, 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."); + } + + return (Result != PI_SUCCESS) ? false : (caps & PI_USM_ACCESS); } }; @@ -1122,12 +1343,19 @@ struct get_device_info_impl { static bool get(const DeviceImplPtr &Dev) { pi_usm_capabilities caps; - pi_result Err = Dev->getPlugin()->call_nocheck( - Dev->getHandleRef(), - PiInfoCode::value, - sizeof(pi_usm_capabilities), &caps, nullptr); + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + sizeof(pi_usm_capabilities), &caps, 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."); + } + // Check that we don't support any cross device sharing - return (Err != PI_SUCCESS) + return (Result != PI_SUCCESS) ? false : !(caps & (PI_USM_ACCESS | PI_USM_CONCURRENT_ACCESS)); } @@ -1138,11 +1366,18 @@ template <> struct get_device_info_impl { static bool get(const DeviceImplPtr &Dev) { pi_usm_capabilities caps; - pi_result Err = Dev->getPlugin()->call_nocheck( - Dev->getHandleRef(), - PiInfoCode::value, - sizeof(pi_usm_capabilities), &caps, nullptr); - return (Err != PI_SUCCESS) ? false : (caps & PI_USM_ACCESS); + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + sizeof(pi_usm_capabilities), &caps, 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."); + } + + return (Result != PI_SUCCESS) ? false : (caps & PI_USM_ACCESS); } }; @@ -1177,11 +1412,19 @@ struct get_device_info_impl< ext::codeplay::experimental::info::device::max_registers_per_work_group> { static uint32_t get(const DeviceImplPtr &Dev) { uint32_t maxRegsPerWG; - Dev->getPlugin()->call( - Dev->getHandleRef(), - PiInfoCode::value, - sizeof(maxRegsPerWG), &maxRegsPerWG, nullptr); + + sycl::detail::pi::PiResult Result = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + sizeof(maxRegsPerWG), &maxRegsPerWG, 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."); + } + return maxRegsPerWG; } }; @@ -1196,19 +1439,32 @@ struct get_device_info_impl< return {}; size_t ResultSize = 0; // First call to get DevCount. - Dev->getPlugin()->call( - Dev->getHandleRef(), - PiInfoCode< - ext::oneapi::experimental::info::device::component_devices>::value, - 0, nullptr, &ResultSize); + sycl::detail::pi::PiResult PiResult = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode::value, + 0, 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."); + } + size_t DevCount = ResultSize / sizeof(pi_device); // Second call to get the list. std::vector Devs(DevCount); - Dev->getPlugin()->call( + PiResult = Dev->getPlugin()->call_nocheck( Dev->getHandleRef(), PiInfoCode< ext::oneapi::experimental::info::device::component_devices>::value, ResultSize, Devs.data(), 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::vector Result; const auto &Platform = Dev->getPlatformImpl(); for (const auto &d : Devs) diff --git a/sycl/source/detail/error_handling/error_handling.cpp b/sycl/source/detail/error_handling/error_handling.cpp index f7ab280c6fa7f..11cdfe6ab0aa3 100644 --- a/sycl/source/detail/error_handling/error_handling.cpp +++ b/sycl/source/detail/error_handling/error_handling.cpp @@ -1,4 +1,4 @@ -//===------------------- enqueue_kernel.cpp ---------------------*- C++ -*-===// +//===------------------- error_handling.cpp ---------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -54,9 +54,15 @@ void handleInvalidWorkGroupSize(const device_impl &DeviceImpl, pi_kernel Kernel, sizeof(size_t) * 3, CompileWGSize, nullptr); size_t MaxWGSize = 0; - Plugin->call(Device, - PI_DEVICE_INFO_MAX_WORK_GROUP_SIZE, - sizeof(size_t), &MaxWGSize, nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Device, PI_DEVICE_INFO_MAX_WORK_GROUP_SIZE, sizeof(size_t), + &MaxWGSize, 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."); + } const bool HasLocalSize = (NDRDesc.LocalSize[0] != 0); @@ -97,9 +103,14 @@ void handleInvalidWorkGroupSize(const device_impl &DeviceImpl, pi_kernel Kernel, if (HasLocalSize) { size_t MaxThreadsPerBlock[3] = {}; - Plugin->call( + Result = Plugin->call_nocheck( Device, PI_DEVICE_INFO_MAX_WORK_ITEM_SIZES, sizeof(MaxThreadsPerBlock), MaxThreadsPerBlock, 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."); + } for (size_t I = 0; I < 3; ++I) { if (MaxThreadsPerBlock[I] < NDRDesc.LocalSize[I]) { @@ -191,17 +202,42 @@ void handleInvalidWorkGroupSize(const device_impl &DeviceImpl, pi_kernel Kernel, // given by local_work_size pi_program Program = nullptr; - Plugin->call( - Kernel, PI_KERNEL_INFO_PROGRAM, sizeof(pi_program), &Program, - nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Kernel, PI_KERNEL_INFO_PROGRAM, sizeof(pi_program), &Program, + nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Kernel get info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } size_t OptsSize = 0; - Plugin->call( + + Result = Plugin->call_nocheck( Program, Device, PI_PROGRAM_BUILD_INFO_OPTIONS, 0, nullptr, &OptsSize); + 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); + } + std::string Opts(OptsSize, '\0'); - Plugin->call( + Result = Plugin->call_nocheck( Program, Device, PI_PROGRAM_BUILD_INFO_OPTIONS, OptsSize, &Opts.front(), 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); + } + const bool HasStd20 = Opts.find("-cl-std=CL2.0") != std::string::npos; const bool RequiresUniformWGSize = Opts.find("-cl-uniform-work-group-size") != std::string::npos; @@ -309,16 +345,24 @@ void handleInvalidWorkItemSize(const device_impl &DeviceImpl, size_t MaxWISize[] = {0, 0, 0}; - Plugin->call( - Device, PI_DEVICE_INFO_MAX_WORK_ITEM_SIZES, sizeof(MaxWISize), &MaxWISize, - nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Device, PI_DEVICE_INFO_MAX_WORK_ITEM_SIZES, sizeof(MaxWISize), + &MaxWISize, 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."); + } + for (unsigned I = 0; I < NDRDesc.Dims; I++) { - if (NDRDesc.LocalSize[I] > MaxWISize[I]) + if (NDRDesc.LocalSize[I] > MaxWISize[I]) { throw sycl::nd_range_error( "Number of work-items in a work-group exceed limit for dimension " + std::to_string(I) + " : " + std::to_string(NDRDesc.LocalSize[I]) + " > " + std::to_string(MaxWISize[I]), PI_ERROR_INVALID_WORK_ITEM_SIZE); + } } } @@ -328,17 +372,25 @@ void handleInvalidValue(const device_impl &DeviceImpl, sycl::detail::pi::PiDevice Device = DeviceImpl.getHandleRef(); size_t MaxNWGs[] = {0, 0, 0}; - Plugin->call( - Device, PI_EXT_ONEAPI_DEVICE_INFO_MAX_WORK_GROUPS_3D, sizeof(MaxNWGs), - &MaxNWGs, nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Device, PI_EXT_ONEAPI_DEVICE_INFO_MAX_WORK_GROUPS_3D, sizeof(MaxNWGs), + &MaxNWGs, 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."); + } + for (unsigned int I = 0; I < NDRDesc.Dims; I++) { size_t NWgs = NDRDesc.GlobalSize[I] / NDRDesc.LocalSize[I]; - if (NWgs > MaxNWGs[I]) + if (NWgs > MaxNWGs[I]) { throw sycl::nd_range_error( "Number of work-groups exceed limit for dimension " + std::to_string(I) + " : " + std::to_string(NWgs) + " > " + std::to_string(MaxNWGs[I]), PI_ERROR_INVALID_VALUE); + } } // fallback diff --git a/sycl/source/detail/event_impl.cpp b/sycl/source/detail/event_impl.cpp index 30d6994e72c5c..2aa797ea87a05 100644 --- a/sycl/source/detail/event_impl.cpp +++ b/sycl/source/detail/event_impl.cpp @@ -54,24 +54,35 @@ bool event_impl::is_host() { } event_impl::~event_impl() { - if (MEvent) - getPlugin()->call(MEvent); + if (MEvent) { + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck(MEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + assert(!"Event release command not supported by backend."); + } else { + getPlugin()->checkPiResult(Result); + } + } } void event_impl::waitInternal(bool *Success) { if (!MHostEvent && MEvent) { // Wait for the native event - sycl::detail::pi::PiResult Err = + sycl::detail::pi::PiResult Error = getPlugin()->call_nocheck(1, &MEvent); // TODO drop the PI_ERROR_UKNOWN from here once the UR counterpart to // PI_ERROR_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST is added: // https://github.com/oneapi-src/unified-runtime/issues/1459 if (Success != nullptr && - (Err == PI_ERROR_UNKNOWN || - Err == PI_ERROR_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST)) + (Error == PI_ERROR_UNKNOWN || + Error == PI_ERROR_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST)) { *Success = false; - else { - getPlugin()->checkPiResult(Err); + } else if (Success == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event wait command not supported by backend."); + } else { + getPlugin()->checkPiResult(Error); if (Success != nullptr) *Success = true; } @@ -156,9 +167,18 @@ event_impl::event_impl(sycl::detail::pi::PiEvent Event, } sycl::detail::pi::PiContext TempContext; - getPlugin()->call( - MEvent, PI_EVENT_INFO_CONTEXT, sizeof(sycl::detail::pi::PiContext), - &TempContext, nullptr); + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MEvent, PI_EVENT_INFO_CONTEXT, sizeof(sycl::detail::pi::PiContext), + &TempContext, nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event get info not supported by backend."); + } else { + getPlugin()->checkPiResult(Result); + } + if (MContext->getHandleRef() != TempContext) { throw sycl::exception(sycl::make_error_code(sycl::errc::invalid), "The syclContext must match the OpenCL context " @@ -489,10 +509,21 @@ pi_native_handle event_impl::getNative() { auto TempContext = MContext.get()->getHandleRef(); Plugin->call(TempContext, &MEvent); } - if (MContext->getBackend() == backend::opencl) + if (MContext->getBackend() == backend::opencl) { Plugin->call(getHandleRef()); + } + pi_native_handle Handle; - Plugin->call(getHandleRef(), &Handle); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(getHandleRef(), + &Handle); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event get native handle command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } return Handle; } @@ -532,11 +563,28 @@ void event_impl::flushIfNeeded(const QueueImplPtr &UserQueue) { // Check if the task for this event has already been submitted. pi_event_status Status = PI_EVENT_QUEUED; - getPlugin()->call( - MEvent, PI_EVENT_INFO_COMMAND_EXECUTION_STATUS, sizeof(pi_int32), &Status, - nullptr); + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MEvent, PI_EVENT_INFO_COMMAND_EXECUTION_STATUS, sizeof(pi_int32), + &Status, nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event get info not supported by backend."); + } else { + getPlugin()->checkPiResult(Result); + } + if (Status == PI_EVENT_QUEUED) { - getPlugin()->call(Queue->getHandleRef()); + Result = getPlugin()->call_nocheck( + Queue->getHandleRef()); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Queue flush command not supported by backend."); + } else { + getPlugin()->checkPiResult(Result); + } } MIsFlushed = true; } diff --git a/sycl/source/detail/event_info.hpp b/sycl/source/detail/event_info.hpp index 05aaed8a36adb..6b9c244216741 100644 --- a/sycl/source/detail/event_info.hpp +++ b/sycl/source/detail/event_info.hpp @@ -26,8 +26,16 @@ get_event_profiling_info(sycl::detail::pi::PiEvent Event, "Unexpected event profiling info descriptor"); typename Param::return_type Result{0}; // TODO catch an exception and put it to list of asynchronous exceptions - Plugin->call( - Event, PiInfoCode::value, sizeof(Result), &Result, nullptr); + sycl::detail::pi::PiResult PiResult = + Plugin->call_nocheck( + Event, PiInfoCode::value, sizeof(Result), &Result, nullptr); + if (PiResult == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event get info not supported by backend."); + } else { + Plugin->checkPiResult(PiResult); + } return Result; } @@ -38,8 +46,16 @@ typename Param::return_type get_event_info(sycl::detail::pi::PiEvent Event, "Unexpected event info descriptor"); typename Param::return_type Result{0}; // TODO catch an exception and put it to list of asynchronous exceptions - Plugin->call(Event, PiInfoCode::value, - sizeof(Result), &Result, nullptr); + sycl::detail::pi::PiResult PiResult = + Plugin->call_nocheck( + Event, PiInfoCode::value, sizeof(Result), &Result, nullptr); + if (PiResult == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event get info not supported by backend."); + } else { + Plugin->checkPiResult(PiResult); + } return Result; } diff --git a/sycl/source/detail/graph_impl.cpp b/sycl/source/detail/graph_impl.cpp index 92dac039ed90c..3e8d85fe8be03 100644 --- a/sycl/source/detail/graph_impl.cpp +++ b/sycl/source/detail/graph_impl.cpp @@ -702,11 +702,15 @@ void exec_graph_impl::createCommandBuffers( auto ContextImpl = sycl::detail::getSyclObjImpl(MContext); const sycl::detail::PluginPtr &Plugin = ContextImpl->getPlugin(); auto DeviceImpl = sycl::detail::getSyclObjImpl(Device); - pi_result Res = + pi_result Result = Plugin->call_nocheck( ContextImpl->getHandleRef(), DeviceImpl->getHandleRef(), &Desc, &OutCommandBuffer); - if (Res != pi_result::PI_SUCCESS) { + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Create command buffer command not supported by backend."); + } else if (Result != pi_result::PI_SUCCESS) { throw sycl::exception(errc::invalid, "Failed to create PI command-buffer"); } @@ -745,10 +749,14 @@ void exec_graph_impl::createCommandBuffers( Node->MCommandGroup->getAccStorage().end()); } - Res = + Result = Plugin->call_nocheck( OutCommandBuffer); - if (Res != pi_result::PI_SUCCESS) { + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Finalize command buffer command not supported by backend."); + } else if (Result != pi_result::PI_SUCCESS) { throw sycl::exception(errc::invalid, "Failed to finalize PI command-buffer"); } @@ -789,10 +797,12 @@ exec_graph_impl::~exec_graph_impl() { Partition->MSchedule.clear(); for (const auto &Iter : Partition->MPiCommandBuffers) { if (auto CmdBuf = Iter.second; CmdBuf) { - pi_result Res = Plugin->call_nocheck< + pi_result Result = Plugin->call_nocheck< sycl::detail::PiApiKind::piextCommandBufferRelease>(CmdBuf); - (void)Res; - assert(Res == pi_result::PI_SUCCESS); + if (Result == PI_ERROR_INVALID_OPERATION) { + assert(!"Release command buffer command not supported by backend."); + } + assert(Result == pi_result::PI_SUCCESS); } } } @@ -910,6 +920,10 @@ exec_graph_impl::enqueue(const std::shared_ptr &Queue, "immediate command lists. Use " "sycl::ext::intel::property::queue::no_immediate_" "command_list to disable them."); + } else if (Res == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue command buffer command not supported by backend."); } else if (Res != pi_result::PI_SUCCESS) { throw sycl::exception( errc::event, diff --git a/sycl/source/detail/image_impl.cpp b/sycl/source/detail/image_impl.cpp index 0b512ae1aedbe..0dc6d15d9ac1e 100644 --- a/sycl/source/detail/image_impl.cpp +++ b/sycl/source/detail/image_impl.cpp @@ -266,8 +266,16 @@ static void getImageInfo(const ContextImplPtr Context, const PluginPtr &Plugin = Context->getPlugin(); sycl::detail::pi::PiMem Mem = pi::cast(InteropMemObject); - Plugin->call(Mem, Info, sizeof(T), &Dest, - nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(Mem, Info, sizeof(T), + &Dest, nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem image get info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } image_impl::image_impl(cl_mem MemObject, const context &SyclContext, @@ -281,8 +289,16 @@ image_impl::image_impl(cl_mem MemObject, const context &SyclContext, pi::cast(BaseT::MInteropMemObject); const ContextImplPtr Context = getSyclObjImpl(SyclContext); const PluginPtr &Plugin = Context->getPlugin(); - Plugin->call(Mem, PI_MEM_SIZE, sizeof(size_t), - &(BaseT::MSizeInBytes), nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Mem, PI_MEM_SIZE, sizeof(size_t), &(BaseT::MSizeInBytes), nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem get info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } sycl::detail::pi::PiMemImageFormat Format; getImageInfo(Context, PI_IMAGE_INFO_FORMAT, Format, Mem); diff --git a/sycl/source/detail/kernel_bundle_impl.hpp b/sycl/source/detail/kernel_bundle_impl.hpp index 55586b6d2b5ac..86c3432be752c 100644 --- a/sycl/source/detail/kernel_bundle_impl.hpp +++ b/sycl/source/detail/kernel_bundle_impl.hpp @@ -413,20 +413,42 @@ class kernel_bundle_impl { // Get the number of kernels in the program. size_t NumKernels; - Plugin->call( - PiProgram, PI_PROGRAM_INFO_NUM_KERNELS, sizeof(size_t), &NumKernels, - nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + PiProgram, PI_PROGRAM_INFO_NUM_KERNELS, sizeof(size_t), &NumKernels, + 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); + } // Get the kernel names. size_t KernelNamesSize; - Plugin->call( + Result = Plugin->call_nocheck( PiProgram, PI_PROGRAM_INFO_KERNEL_NAMES, 0, nullptr, &KernelNamesSize); + 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); + } // semi-colon delimited list of kernel names. std::string KernelNamesStr(KernelNamesSize, ' '); - Plugin->call( + Result = Plugin->call_nocheck( PiProgram, PI_PROGRAM_INFO_KERNEL_NAMES, KernelNamesStr.size(), &KernelNamesStr[0], 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); + } std::vector KernelNames = detail::split_string(KernelNamesStr, ';'); diff --git a/sycl/source/detail/kernel_impl.cpp b/sycl/source/detail/kernel_impl.cpp index 9c5a1851cd3b1..f659519c4ebea 100644 --- a/sycl/source/detail/kernel_impl.cpp +++ b/sycl/source/detail/kernel_impl.cpp @@ -48,12 +48,22 @@ kernel_impl::kernel_impl(sycl::detail::pi::PiKernel Kernel, sycl::detail::pi::PiContext Context = nullptr; // Using the plugin from the passed ContextImpl - getPlugin()->call( - MKernel, PI_KERNEL_INFO_CONTEXT, sizeof(Context), &Context, nullptr); - if (ContextImpl->getHandleRef() != Context) + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MKernel, PI_KERNEL_INFO_CONTEXT, sizeof(Context), &Context, nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Kernel get info command not supported by backend."); + } else { + getPlugin()->checkPiResult(Result); + } + + if (ContextImpl->getHandleRef() != Context) { throw sycl::invalid_parameter_error( "Input context must be the same as the context of cl_kernel", PI_ERROR_INVALID_CONTEXT); + } MIsInterop = ProgramImpl->isInterop(); } diff --git a/sycl/source/detail/kernel_info.hpp b/sycl/source/detail/kernel_info.hpp index 12256158eed49..f954f3fc2dd03 100644 --- a/sycl/source/detail/kernel_info.hpp +++ b/sycl/source/detail/kernel_info.hpp @@ -31,15 +31,30 @@ get_kernel_info(sycl::detail::pi::PiKernel Kernel, const PluginPtr &Plugin) { size_t ResultSize = 0; // TODO catch an exception and put it to list of asynchronous exceptions - Plugin->call(Kernel, PiInfoCode::value, 0, - nullptr, &ResultSize); + sycl::detail::pi::PiResult PiResult = + Plugin->call_nocheck( + Kernel, PiInfoCode::value, 0, nullptr, &ResultSize); + if (PiResult == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Kernel get info command not supported by backend."); + } else { + Plugin->checkPiResult(PiResult); + } if (ResultSize == 0) { return ""; } std::vector Result(ResultSize); // TODO catch an exception and put it to list of asynchronous exceptions - Plugin->call(Kernel, PiInfoCode::value, - ResultSize, Result.data(), nullptr); + PiResult = Plugin->call_nocheck( + Kernel, PiInfoCode::value, ResultSize, Result.data(), nullptr); + if (PiResult == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Kernel get info command not supported by backend."); + } else { + Plugin->checkPiResult(PiResult); + } return std::string(Result.data()); } @@ -50,8 +65,16 @@ get_kernel_info(sycl::detail::pi::PiKernel Kernel, const PluginPtr &Plugin) { uint32_t Result = 0; // TODO catch an exception and put it to list of asynchronous exceptions - Plugin->call(Kernel, PiInfoCode::value, - sizeof(uint32_t), &Result, nullptr); + sycl::detail::pi::PiResult PiResult = + Plugin->call_nocheck( + Kernel, PiInfoCode::value, sizeof(uint32_t), &Result, nullptr); + if (PiResult == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Kernel get info command not supported by backend."); + } else { + Plugin->checkPiResult(PiResult); + } return Result; } @@ -62,9 +85,17 @@ get_kernel_device_specific_info_helper(sycl::detail::pi::PiKernel Kernel, sycl::detail::pi::PiDevice Device, const PluginPtr &Plugin, void *Result, size_t Size) { - Plugin->call( - Kernel, Device, PiInfoCode::value, 0, nullptr, Size, Result, - nullptr); + sycl::detail::pi::PiResult PiResult = + Plugin->call_nocheck( + Kernel, Device, PiInfoCode::value, 0, nullptr, Size, Result, + nullptr); + if (PiResult == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Kernel get sub group info command not supported by backend."); + } else { + Plugin->checkPiResult(PiResult); + } } template @@ -130,9 +161,17 @@ uint32_t get_kernel_device_specific_info_with_input( size_t Input[3] = {In[0], In[1], In[2]}; uint32_t Result = 0; // TODO catch an exception and put it to list of asynchronous exceptions - Plugin->call( - Kernel, Device, PiInfoCode::value, sizeof(size_t) * 3, Input, - sizeof(uint32_t), &Result, nullptr); + sycl::detail::pi::PiResult PiResult = + Plugin->call_nocheck( + Kernel, Device, PiInfoCode::value, sizeof(size_t) * 3, Input, + sizeof(uint32_t), &Result, nullptr); + if (PiResult == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Kernel get sub group info command not supported by backend."); + } else { + Plugin->checkPiResult(PiResult); + } return Result; } diff --git a/sycl/source/detail/memory_manager.cpp b/sycl/source/detail/memory_manager.cpp index 989bb4ceb427d..b6b836313cc1f 100644 --- a/sycl/source/detail/memory_manager.cpp +++ b/sycl/source/detail/memory_manager.cpp @@ -125,7 +125,16 @@ static void waitForEvents(const std::vector &Events) { [](const EventImplPtr &EventImpl) { return EventImpl->getHandleRef(); }); - Plugin->call(PiEvents.size(), &PiEvents[0]); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(PiEvents.size(), + &PiEvents[0]); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event wait command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } } @@ -150,15 +159,32 @@ void memBufferCreateHelper(const PluginPtr &Plugin, pi_context Ctx, // 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_nocheck( - *RetMem, /*Dev*/ nullptr, &Ptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + *RetMem, /*Dev*/ nullptr, &Ptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem buffer get native handle command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } emitMemAllocEndTrace(MemObjID, (uintptr_t)(Ptr), Size, 0 /* guard zone */, CorrID); }}; #endif - if (Size) - Plugin->call(Ctx, Flags, Size, HostPtr, - RetMem, Props); + if (Size) { + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Ctx, Flags, Size, HostPtr, RetMem, Props); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem buffer create command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } + } } } @@ -177,8 +203,16 @@ void memReleaseHelper(const PluginPtr &Plugin, pi_mem Mem) { // 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(Mem, /*Dev*/ nullptr, - &PtrHandle); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Mem, /*Dev*/ nullptr, &PtrHandle); + 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); + } Ptr = (uintptr_t)(PtrHandle); } #endif @@ -235,7 +269,15 @@ void memUnmapHelper(const PluginPtr &Plugin, pi_queue Queue, pi_mem Mem, // Always use call_nocheck here, because call may throw an exception, // and this lambda will be called from destructor, which in combination // rewards us with UB. - Plugin->call_nocheck(1, Event); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(1, Event); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event wait command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } emitMemReleaseEndTrace(MemObjID, Ptr, CorrID); }}; #endif @@ -338,9 +380,17 @@ void *MemoryManager::allocateImageObject( sycl::detail::pi::PiMem NewMem; const PluginPtr &Plugin = TargetContext->getPlugin(); - Plugin->call(TargetContext->getHandleRef(), - CreationFlags, &Format, &Desc, - UserPtr, &NewMem); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + TargetContext->getHandleRef(), CreationFlags, &Format, &Desc, UserPtr, + &NewMem); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem image create command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } return NewMem; } @@ -443,21 +493,26 @@ void *MemoryManager::allocateMemSubBuffer(ContextImplPtr TargetContext, for (size_t I = 0; I < 3; ++I) SizeInBytes *= Range[I]; - sycl::detail::pi::PiResult Error = PI_SUCCESS; pi_buffer_region_struct Region{Offset, SizeInBytes}; sycl::detail::pi::PiMem NewMem; const PluginPtr &Plugin = TargetContext->getPlugin(); - Error = Plugin->call_nocheck( - pi::cast(ParentMemObj), PI_MEM_FLAGS_ACCESS_RW, - PI_BUFFER_CREATE_TYPE_REGION, &Region, &NewMem); - if (Error == PI_ERROR_MISALIGNED_SUB_BUFFER_OFFSET) + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + pi::cast(ParentMemObj), + PI_MEM_FLAGS_ACCESS_RW, PI_BUFFER_CREATE_TYPE_REGION, &Region, + &NewMem); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem bnuffer partition command not supported by backend."); + } else if (Result == PI_ERROR_MISALIGNED_SUB_BUFFER_OFFSET) throw invalid_object_error( "Specified offset of the sub-buffer being constructed is not a " "multiple of the memory base address alignment", PI_ERROR_INVALID_VALUE); - if (Error != PI_SUCCESS) { - Plugin->reportPiError(Error, "allocateMemSubBuffer()"); + if (Result != PI_SUCCESS) { + Plugin->reportPiError(Result, "allocateMemSubBuffer()"); } return NewMem; @@ -564,10 +619,19 @@ void copyH2D(SYCLMemObjI *SYCLMemObj, char *SrcMem, QueueImplPtr, DstAccessRange[DstPos.ZTerm]}; if (OutEventImpl != nullptr) OutEventImpl->setHostEnqueueTime(); - Plugin->call( - Queue, DstMem, - /*blocking_write=*/PI_FALSE, &Origin, &Region, InputRowPitch, - InputSlicePitch, SrcMem, DepEvents.size(), DepEvents.data(), &OutEvent); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Queue, DstMem, + /*blocking_write=*/PI_FALSE, &Origin, &Region, InputRowPitch, + InputSlicePitch, SrcMem, DepEvents.size(), DepEvents.data(), + &OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue mem image buffer write command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } } @@ -627,13 +691,24 @@ void copyD2H(SYCLMemObjI *SYCLMemObj, sycl::detail::pi::PiMem SrcMem, pi_buff_rect_region_struct RectRegion{SrcAccessRangeWidthBytes, SrcAccessRange[SrcPos.YTerm], SrcAccessRange[SrcPos.ZTerm]}; - if (OutEventImpl != nullptr) + if (OutEventImpl != nullptr) { OutEventImpl->setHostEnqueueTime(); - Plugin->call( - Queue, SrcMem, - /*blocking_read=*/PI_FALSE, &BufferOffset, &HostOffset, &RectRegion, - BufferRowPitch, BufferSlicePitch, HostRowPitch, HostSlicePitch, - DstMem, DepEvents.size(), DepEvents.data(), &OutEvent); + } + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Queue, SrcMem, + /*blocking_read=*/PI_FALSE, &BufferOffset, &HostOffset, + &RectRegion, BufferRowPitch, BufferSlicePitch, HostRowPitch, + HostSlicePitch, DstMem, DepEvents.size(), DepEvents.data(), + &OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue mem image buffer read rect command not supported by " + "backend."); + } else { + Plugin->checkPiResult(Result); + } } } else { size_t RowPitch = (1 == DimSrc) ? 0 : SrcSzWidthBytes; @@ -646,11 +721,20 @@ void copyD2H(SYCLMemObjI *SYCLMemObj, sycl::detail::pi::PiMem SrcMem, pi_image_region_struct Region{SrcAccessRange[SrcPos.XTerm], SrcAccessRange[SrcPos.YTerm], SrcAccessRange[SrcPos.ZTerm]}; - if (OutEventImpl != nullptr) + if (OutEventImpl != nullptr) { OutEventImpl->setHostEnqueueTime(); - Plugin->call( - Queue, SrcMem, PI_FALSE, &Offset, &Region, RowPitch, SlicePitch, DstMem, - DepEvents.size(), DepEvents.data(), &OutEvent); + } + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Queue, SrcMem, PI_FALSE, &Offset, &Region, RowPitch, SlicePitch, + DstMem, DepEvents.size(), DepEvents.data(), &OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue mem image buffer read command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } } @@ -724,11 +808,20 @@ void copyD2D(SYCLMemObjI *SYCLMemObj, sycl::detail::pi::PiMem SrcMem, pi_image_region_struct Region{SrcAccessRange[SrcPos.XTerm], SrcAccessRange[SrcPos.YTerm], SrcAccessRange[SrcPos.ZTerm]}; - if (OutEventImpl != nullptr) + if (OutEventImpl != nullptr) { OutEventImpl->setHostEnqueueTime(); - Plugin->call( - Queue, SrcMem, DstMem, &SrcOrigin, &DstOrigin, &Region, - DepEvents.size(), DepEvents.data(), &OutEvent); + } + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Queue, SrcMem, DstMem, &SrcOrigin, &DstOrigin, &Region, + DepEvents.size(), DepEvents.data(), &OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue mem image buffer copy command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } } @@ -949,11 +1042,20 @@ void MemoryManager::copy_usm(const void *SrcMem, QueueImplPtr SrcQueue, if (!Len) { // no-op, but ensure DepEvents will still be waited on if (!DepEvents.empty()) { - if (OutEventImpl != nullptr) + if (OutEventImpl != nullptr) { OutEventImpl->setHostEnqueueTime(); - SrcQueue->getPlugin()->call( - SrcQueue->getHandleRef(), DepEvents.size(), DepEvents.data(), - OutEvent); + } + sycl::detail::pi::PiResult Result = + SrcQueue->getPlugin()->call_nocheck( + SrcQueue->getHandleRef(), DepEvents.size(), DepEvents.data(), + OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue events wait command not supported by backend."); + } else { + SrcQueue->getPlugin()->checkPiResult(Result); + } } return; } @@ -990,10 +1092,20 @@ void MemoryManager::fill_usm(void *Mem, QueueImplPtr Queue, size_t Length, if (!Length) { // no-op, but ensure DepEvents will still be waited on if (!DepEvents.empty()) { - if (OutEventImpl != nullptr) + if (OutEventImpl != nullptr) { OutEventImpl->setHostEnqueueTime(); - Queue->getPlugin()->call( - Queue->getHandleRef(), DepEvents.size(), DepEvents.data(), OutEvent); + } + sycl::detail::pi::PiResult Result = + Queue->getPlugin()->call_nocheck( + Queue->getHandleRef(), DepEvents.size(), DepEvents.data(), + OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue events wait command not supported by backend."); + } else { + Queue->getPlugin()->checkPiResult(Result); + } } return; } @@ -1027,11 +1139,20 @@ void MemoryManager::prefetch_usm( "Host queue not supported in prefetch_usm."); const PluginPtr &Plugin = Queue->getPlugin(); - if (OutEventImpl != nullptr) + if (OutEventImpl != nullptr) { OutEventImpl->setHostEnqueueTime(); - Plugin->call( - Queue->getHandleRef(), Mem, Length, _pi_usm_migration_flags(0), - DepEvents.size(), DepEvents.data(), OutEvent); + } + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Queue->getHandleRef(), Mem, Length, _pi_usm_migration_flags(0), + DepEvents.size(), DepEvents.data(), OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue USM prefetch command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } // TODO: This function will remain until ABI-breaking change @@ -1051,10 +1172,19 @@ void MemoryManager::advise_usm( "Host queue not supported in advise_usm."); const PluginPtr &Plugin = Queue->getPlugin(); - if (OutEventImpl != nullptr) + if (OutEventImpl != nullptr) { OutEventImpl->setHostEnqueueTime(); - Plugin->call(Queue->getHandleRef(), Mem, - Length, Advice, OutEvent); + } + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Queue->getHandleRef(), Mem, Length, Advice, OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue USM advise command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } // TODO: This function will remain until ABI-breaking change @@ -1078,10 +1208,20 @@ void MemoryManager::copy_2d_usm( if (Width == 0 || Height == 0) { // no-op, but ensure DepEvents will still be waited on if (!DepEvents.empty()) { - if (OutEventImpl != nullptr) + if (OutEventImpl != nullptr) { OutEventImpl->setHostEnqueueTime(); - Queue->getPlugin()->call( - Queue->getHandleRef(), DepEvents.size(), DepEvents.data(), OutEvent); + } + sycl::detail::pi::PiResult Result = + Queue->getPlugin()->call_nocheck( + Queue->getHandleRef(), DepEvents.size(), DepEvents.data(), + OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue events wait command not supported by backend."); + } else { + Queue->getPlugin()->checkPiResult(Result); + } } return; } @@ -1102,9 +1242,19 @@ void MemoryManager::copy_2d_usm( if (OutEventImpl != nullptr) OutEventImpl->setHostEnqueueTime(); // Direct memcpy2D is supported so we use this function. - Plugin->call( - Queue->getHandleRef(), /*blocking=*/PI_FALSE, DstMem, DstPitch, SrcMem, - SrcPitch, Width, Height, DepEvents.size(), DepEvents.data(), OutEvent); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Queue->getHandleRef(), /*blocking=*/PI_FALSE, DstMem, DstPitch, + SrcMem, SrcPitch, Width, Height, DepEvents.size(), DepEvents.data(), + OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue USM mem copy 2D command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } + return; } @@ -1137,11 +1287,21 @@ void MemoryManager::copy_2d_usm( CopyEventsManaged.emplace_back(CopyEvents[I], Plugin, /*TakeOwnership=*/true); } - if (OutEventImpl != nullptr) + if (OutEventImpl != nullptr) { OutEventImpl->setHostEnqueueTime(); + } // Then insert a wait to coalesce the copy events. - Queue->getPlugin()->call( - Queue->getHandleRef(), CopyEvents.size(), CopyEvents.data(), OutEvent); + sycl::detail::pi::PiResult Result = + Queue->getPlugin()->call_nocheck( + Queue->getHandleRef(), CopyEvents.size(), CopyEvents.data(), + OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue events wait command not supported by backend."); + } else { + Queue->getPlugin()->checkPiResult(Result); + } } // TODO: This function will remain until ABI-breaking change @@ -1166,23 +1326,45 @@ void MemoryManager::fill_2d_usm( if (Width == 0 || Height == 0) { // no-op, but ensure DepEvents will still be waited on if (!DepEvents.empty()) { - if (OutEventImpl != nullptr) + if (OutEventImpl != nullptr) { OutEventImpl->setHostEnqueueTime(); - Queue->getPlugin()->call( - Queue->getHandleRef(), DepEvents.size(), DepEvents.data(), OutEvent); + } + sycl::detail::pi::PiResult Result = + Queue->getPlugin()->call_nocheck( + Queue->getHandleRef(), DepEvents.size(), DepEvents.data(), + OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue events wait command not supported by backend."); + } else { + Queue->getPlugin()->checkPiResult(Result); + } } return; } - if (!DstMem) + if (!DstMem) { throw sycl::exception(sycl::make_error_code(errc::invalid), "NULL pointer argument in 2D memory fill operation."); - if (OutEventImpl != nullptr) + } + + if (OutEventImpl != nullptr) { OutEventImpl->setHostEnqueueTime(); + } + const PluginPtr &Plugin = Queue->getPlugin(); - Plugin->call( - Queue->getHandleRef(), DstMem, Pitch, Pattern.size(), Pattern.data(), - Width, Height, DepEvents.size(), DepEvents.data(), OutEvent); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Queue->getHandleRef(), DstMem, Pitch, Pattern.size(), Pattern.data(), + Width, Height, DepEvents.size(), DepEvents.data(), OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue USM fill 2D command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } // TODO: This function will remain until ABI-breaking change @@ -1206,10 +1388,20 @@ void MemoryManager::memset_2d_usm( if (Width == 0 || Height == 0) { // no-op, but ensure DepEvents will still be waited on if (!DepEvents.empty()) { - if (OutEventImpl != nullptr) + if (OutEventImpl != nullptr) { OutEventImpl->setHostEnqueueTime(); - Queue->getPlugin()->call( - Queue->getHandleRef(), DepEvents.size(), DepEvents.data(), OutEvent); + } + sycl::detail::pi::PiResult Result = + Queue->getPlugin()->call_nocheck( + Queue->getHandleRef(), DepEvents.size(), DepEvents.data(), + OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue events wait command not supported by backend."); + } else { + Queue->getPlugin()->checkPiResult(Result); + } } return; } @@ -1346,10 +1538,19 @@ static void memcpyToDeviceGlobalDirect( sycl::detail::pi::PiProgram Program = getOrBuildProgramForDeviceGlobal(Queue, DeviceGlobalEntry); const PluginPtr &Plugin = Queue->getPlugin(); - Plugin->call( - Queue->getHandleRef(), Program, DeviceGlobalEntry->MUniqueId.c_str(), - false, NumBytes, Offset, Src, DepEvents.size(), DepEvents.data(), - OutEvent); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Queue->getHandleRef(), Program, DeviceGlobalEntry->MUniqueId.c_str(), + false, NumBytes, Offset, Src, DepEvents.size(), DepEvents.data(), + OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue device global variable write command not supported by " + "backend."); + } else { + Plugin->checkPiResult(Result); + } } static void memcpyFromDeviceGlobalDirect( @@ -1360,10 +1561,19 @@ static void memcpyFromDeviceGlobalDirect( sycl::detail::pi::PiProgram Program = getOrBuildProgramForDeviceGlobal(Queue, DeviceGlobalEntry); const PluginPtr &Plugin = Queue->getPlugin(); - Plugin->call( - Queue->getHandleRef(), Program, DeviceGlobalEntry->MUniqueId.c_str(), - false, NumBytes, Offset, Dest, DepEvents.size(), DepEvents.data(), - OutEvent); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Queue->getHandleRef(), Program, DeviceGlobalEntry->MUniqueId.c_str(), + false, NumBytes, Offset, Dest, DepEvents.size(), DepEvents.data(), + OutEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue device global variable read command not supported by " + "backend."); + } else { + Plugin->checkPiResult(Result); + } } void MemoryManager::copy_to_device_global( @@ -1465,11 +1675,20 @@ void MemoryManager::ext_oneapi_copyD2D_cmd_buffer( } if (1 == DimDst && 1 == DimSrc) { - Plugin->call( - CommandBuffer, sycl::detail::pi::cast(SrcMem), - sycl::detail::pi::cast(DstMem), SrcXOffBytes, - DstXOffBytes, SrcAccessRangeWidthBytes, Deps.size(), Deps.data(), - OutSyncPoint); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + CommandBuffer, + sycl::detail::pi::cast(SrcMem), + sycl::detail::pi::cast(DstMem), + SrcXOffBytes, DstXOffBytes, SrcAccessRangeWidthBytes, Deps.size(), + Deps.data(), OutSyncPoint); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem buffer copy command buffer command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } else { // passing 0 for pitches not allowed. Because clEnqueueCopyBufferRect will // calculate both src and dest pitch using region[0], which is not correct @@ -1491,11 +1710,21 @@ void MemoryManager::ext_oneapi_copyD2D_cmd_buffer( SrcAccessRange[SrcPos.YTerm], SrcAccessRange[SrcPos.ZTerm]}; - Plugin->call( - CommandBuffer, sycl::detail::pi::cast(SrcMem), - sycl::detail::pi::cast(DstMem), &SrcOrigin, - &DstOrigin, &Region, SrcRowPitch, SrcSlicePitch, DstRowPitch, - DstSlicePitch, Deps.size(), Deps.data(), OutSyncPoint); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + CommandBuffer, + sycl::detail::pi::cast(SrcMem), + sycl::detail::pi::cast(DstMem), &SrcOrigin, + &DstOrigin, &Region, SrcRowPitch, SrcSlicePitch, DstRowPitch, + DstSlicePitch, Deps.size(), Deps.data(), OutSyncPoint); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem buffer rect copy command buffer command not supported by " + "backend."); + } else { + Plugin->checkPiResult(Result); + } } } diff --git a/sycl/source/detail/persistent_device_code_cache.cpp b/sycl/source/detail/persistent_device_code_cache.cpp index ea71f1a80b743..2d843550e5ec6 100644 --- a/sycl/source/detail/persistent_device_code_cache.cpp +++ b/sycl/source/detail/persistent_device_code_cache.cpp @@ -106,14 +106,29 @@ void PersistentDeviceCodeCache::putItemToDisc( unsigned int DeviceNum = 0; - Plugin->call( - NativePrg, PI_PROGRAM_INFO_NUM_DEVICES, sizeof(DeviceNum), &DeviceNum, - nullptr); + sycl::detail::pi::PiResult PiResult = + Plugin->call_nocheck( + NativePrg, PI_PROGRAM_INFO_NUM_DEVICES, sizeof(DeviceNum), &DeviceNum, + nullptr); + if (PiResult == 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(PiResult); + } std::vector BinarySizes(DeviceNum); - Plugin->call( + PiResult = Plugin->call_nocheck( NativePrg, PI_PROGRAM_INFO_BINARY_SIZES, sizeof(size_t) * BinarySizes.size(), BinarySizes.data(), nullptr); + if (PiResult == 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(PiResult); + } std::vector> Result; std::vector Pointers; @@ -122,9 +137,17 @@ void PersistentDeviceCodeCache::putItemToDisc( Pointers.push_back(Result[I].data()); } - Plugin->call(NativePrg, PI_PROGRAM_INFO_BINARIES, - sizeof(char *) * Pointers.size(), - Pointers.data(), nullptr); + PiResult = Plugin->call( + NativePrg, PI_PROGRAM_INFO_BINARIES, sizeof(char *) * Pointers.size(), + Pointers.data(), nullptr); + if (PiResult == 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(PiResult); + } + size_t i = 0; std::string FileName; do { diff --git a/sycl/source/detail/pi.cpp b/sycl/source/detail/pi.cpp index 1743b3647e6ed..d8f2a3d8b3367 100644 --- a/sycl/source/detail/pi.cpp +++ b/sycl/source/detail/pi.cpp @@ -196,8 +196,16 @@ void contextSetExtendedDeleter(const sycl::context &context, auto impl = getSyclObjImpl(context); auto contextHandle = reinterpret_cast(impl->getHandleRef()); const auto &Plugin = impl->getPlugin(); - Plugin->call(contextHandle, func, - user_data); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + contextHandle, func, user_data); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Context set extended deleter command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } std::string platformInfoToString(pi_platform_info info) { diff --git a/sycl/source/detail/pi_utils.hpp b/sycl/source/detail/pi_utils.hpp index 877cbd0d14e52..0c69e6c039072 100644 --- a/sycl/source/detail/pi_utils.hpp +++ b/sycl/source/detail/pi_utils.hpp @@ -32,8 +32,15 @@ struct OwnedPiEvent { } ~OwnedPiEvent() { // Release the event if the ownership was not transferred. - if (MEvent.has_value()) - MPlugin->call(*MEvent); + if (MEvent.has_value()) { + sycl::detail::pi::PiResult Result = + MPlugin->call_nocheck(*MEvent); + if (Result == PI_ERROR_INVALID_OPERATION) { + assert(!"Event release command not supported by backend."); + } else { + MPlugin->checkPiResult(Result); + } + } } OwnedPiEvent(OwnedPiEvent &&Other) diff --git a/sycl/source/detail/platform_impl.cpp b/sycl/source/detail/platform_impl.cpp index 2bdfab26676d9..b98ff8660b9f8 100644 --- a/sycl/source/detail/platform_impl.cpp +++ b/sycl/source/detail/platform_impl.cpp @@ -67,8 +67,14 @@ platform_impl::getPlatformFromPiDevice(sycl::detail::pi::PiDevice PiDevice, sycl::detail::pi::PiPlatform Plt = nullptr; // TODO catch an exception and put it to list // of asynchronous exceptions - Plugin->call(PiDevice, PI_DEVICE_INFO_PLATFORM, - sizeof(Plt), &Plt, nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + PiDevice, PI_DEVICE_INFO_PLATFORM, sizeof(Plt), &Plt, 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."); + } return getOrMakePlatformImpl(Plt, Plugin); } @@ -244,9 +250,17 @@ std::vector platform_impl::filterDeviceFilter( // Find out backend of the platform sycl::detail::pi::PiPlatformBackend PiBackend; - MPlugin->call( - MPlatform, PI_EXT_PLATFORM_INFO_BACKEND, - sizeof(sycl::detail::pi::PiPlatformBackend), &PiBackend, nullptr); + sycl::detail::pi::PiResult Result = + MPlugin->call_nocheck( + MPlatform, PI_EXT_PLATFORM_INFO_BACKEND, + sizeof(sycl::detail::pi::PiPlatformBackend), &PiBackend, nullptr); + if (Result == 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 { + MPlugin->checkPiResult(Result); + } backend Backend = convertBackend(PiBackend); int InsertIDx = 0; @@ -256,9 +270,15 @@ std::vector platform_impl::filterDeviceFilter( int DeviceNum = MPlugin->getStartingDeviceId(MPlatform); for (sycl::detail::pi::PiDevice Device : PiDevices) { sycl::detail::pi::PiDeviceType PiDevType; - MPlugin->call( - Device, PI_DEVICE_INFO_TYPE, sizeof(sycl::detail::pi::PiDeviceType), - &PiDevType, nullptr); + sycl::detail::pi::PiResult Result = + MPlugin->call_nocheck( + 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."); + } // Assumption here is that there is 1-to-1 mapping between PiDevType and // Sycl device type for GPU, CPU, and ACC. info::device_type DeviceType = pi::cast(PiDevType); @@ -579,8 +599,16 @@ bool platform_impl::supports_usm() const { pi_native_handle platform_impl::getNative() const { const auto &Plugin = getPlugin(); pi_native_handle Handle; - Plugin->call(getHandleRef(), - &Handle); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + getHandleRef(), &Handle); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Platform get native handle command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } return Handle; } diff --git a/sycl/source/detail/platform_impl.hpp b/sycl/source/detail/platform_impl.hpp index 34537c7191af6..f9a38e48be065 100644 --- a/sycl/source/detail/platform_impl.hpp +++ b/sycl/source/detail/platform_impl.hpp @@ -46,9 +46,17 @@ class platform_impl { // Find out backend of the platform sycl::detail::pi::PiPlatformBackend PiBackend; - APlugin->call_nocheck( - APlatform, PI_EXT_PLATFORM_INFO_BACKEND, - sizeof(sycl::detail::pi::PiPlatformBackend), &PiBackend, nullptr); + sycl::detail::pi::PiResult Result = + APlugin->call_nocheck( + APlatform, PI_EXT_PLATFORM_INFO_BACKEND, + sizeof(sycl::detail::pi::PiPlatformBackend), &PiBackend, nullptr); + if (Result == 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 { + APlugin->checkPiResult(Result); + } MBackend = convertBackend(PiBackend); } @@ -99,10 +107,16 @@ class platform_impl { void getBackendOption(const char *frontend_option, const char **backend_option) const { const auto &Plugin = getPlugin(); - sycl::detail::pi::PiResult Err = + sycl::detail::pi::PiResult Result = Plugin->call_nocheck( MPlatform, frontend_option, backend_option); - Plugin->checkPiResult(Err); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Platform get backend option command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } /// \return an instance of OpenCL cl_platform_id. diff --git a/sycl/source/detail/platform_info.hpp b/sycl/source/detail/platform_info.hpp index 42c41b5063cf5..13d1ad864c6bf 100644 --- a/sycl/source/detail/platform_info.hpp +++ b/sycl/source/detail/platform_info.hpp @@ -25,15 +25,31 @@ get_platform_info_string_impl(sycl::detail::pi::PiPlatform Plt, pi_platform_info PiCode) { size_t ResultSize; // TODO catch an exception and put it to list of asynchronous exceptions - Plugin->call(Plt, PiCode, 0, nullptr, - &ResultSize); + sycl::detail::pi::PiResult PiResult = + Plugin->call_nocheck(Plt, PiCode, 0, + 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 ""; } + std::unique_ptr Result(new char[ResultSize]); // TODO catch an exception and put it to list of asynchronous exceptions - Plugin->call(Plt, PiCode, ResultSize, - Result.get(), nullptr); + PiResult = Plugin->call_nocheck( + Plt, PiCode, 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); + } return Result.get(); } // The platform information methods diff --git a/sycl/source/detail/program_impl.cpp b/sycl/source/detail/program_impl.cpp index d65f3163b961f..66b755088cd81 100644 --- a/sycl/source/detail/program_impl.cpp +++ b/sycl/source/detail/program_impl.cpp @@ -131,21 +131,47 @@ program_impl::program_impl(ContextImplPtr Context, assert(InteropProgram && "No InteropProgram/PiProgram defined with piextProgramFromNative"); // Translate the raw program handle into PI program. - Plugin->call( - InteropProgram, MContext->getHandleRef(), false, &MProgram); - } else + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + InteropProgram, MContext->getHandleRef(), false, &MProgram); + 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); + } + } else { Plugin->call(Program); + } // TODO handle the case when cl_program build is in progress pi_uint32 NumDevices; - Plugin->call( - MProgram, PI_PROGRAM_INFO_NUM_DEVICES, sizeof(pi_uint32), &NumDevices, - nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + MProgram, PI_PROGRAM_INFO_NUM_DEVICES, sizeof(pi_uint32), &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); + } + std::vector PiDevices(NumDevices); - Plugin->call(MProgram, PI_PROGRAM_INFO_DEVICES, - sizeof(sycl::detail::pi::PiDevice) * - NumDevices, - PiDevices.data(), nullptr); + Result = Plugin->call_nocheck( + MProgram, PI_PROGRAM_INFO_DEVICES, + sizeof(sycl::detail::pi::PiDevice) * NumDevices, PiDevices.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); + } std::vector PlatformDevices = MContext->getPlatformImpl()->get_devices(); @@ -162,26 +188,52 @@ program_impl::program_impl(ContextImplPtr Context, PlatformDevices.erase(NewEnd, PlatformDevices.end()); MDevices = PlatformDevices; assert(!MDevices.empty() && "No device found for this program"); + sycl::detail::pi::PiDevice Device = PiDevices[0]; // TODO check build for each device instead cl_program_binary_type BinaryType = PI_PROGRAM_BINARY_TYPE_NONE; - Plugin->call( + Result = Plugin->call_nocheck( MProgram, Device, PI_PROGRAM_BUILD_INFO_BINARY_TYPE, sizeof(cl_program_binary_type), &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); + } if (BinaryType == PI_PROGRAM_BINARY_TYPE_NONE) { throw invalid_object_error( "The native program passed to the program constructor has to be either " "compiled or linked", PI_ERROR_INVALID_PROGRAM); } + size_t Size = 0; - Plugin->call( + Result = Plugin->call_nocheck( MProgram, Device, PI_PROGRAM_BUILD_INFO_OPTIONS, 0, nullptr, &Size); + 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); + } + std::vector OptionsVector(Size); - Plugin->call( + Result = Plugin->call_nocheck( MProgram, Device, PI_PROGRAM_BUILD_INFO_OPTIONS, Size, OptionsVector.data(), 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); + } + std::string Options(OptionsVector.begin(), OptionsVector.end()); + switch (BinaryType) { case PI_PROGRAM_BINARY_TYPE_COMPILED_OBJECT: MState = program_state::compiled; @@ -278,18 +330,26 @@ bool program_impl::has_kernel(std::string KernelName, pi_uint64 function_ptr; const PluginPtr &Plugin = getPlugin(); - sycl::detail::pi::PiResult Err = PI_SUCCESS; for (sycl::detail::pi::PiDevice Device : Devices) { - Err = Plugin->call_nocheck( - Device, MProgram, KernelName.c_str(), &function_ptr); - if (Err != PI_SUCCESS && - Err != PI_ERROR_FUNCTION_ADDRESS_IS_NOT_AVAILABLE && - Err != PI_ERROR_INVALID_KERNEL_NAME) + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Device, MProgram, KernelName.c_str(), &function_ptr); + 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 if (Result != PI_SUCCESS && + Result != PI_ERROR_FUNCTION_ADDRESS_IS_NOT_AVAILABLE && + Result != PI_ERROR_INVALID_KERNEL_NAME) { throw runtime_error( "Error from piextGetDeviceFunctionPointer when called by program", - Err); - if (Err == PI_SUCCESS || Err == PI_ERROR_FUNCTION_ADDRESS_IS_NOT_AVAILABLE) + Result); + } + if (Result == PI_SUCCESS || + Result == PI_ERROR_FUNCTION_ADDRESS_IS_NOT_AVAILABLE) { return true; + } } return false; @@ -320,18 +380,36 @@ std::vector> program_impl::get_binaries() const { std::vector> Result; const PluginPtr &Plugin = getPlugin(); std::vector BinarySizes(MDevices.size()); - Plugin->call( - MProgram, PI_PROGRAM_INFO_BINARY_SIZES, - sizeof(size_t) * BinarySizes.size(), BinarySizes.data(), nullptr); + + sycl::detail::pi::PiResult PiResult = + Plugin->call_nocheck( + MProgram, PI_PROGRAM_INFO_BINARY_SIZES, + sizeof(size_t) * BinarySizes.size(), BinarySizes.data(), nullptr); + if (PiResult == 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(PiResult); + } std::vector Pointers; for (size_t I = 0; I < BinarySizes.size(); ++I) { Result.emplace_back(BinarySizes[I]); Pointers.push_back(Result[I].data()); } - Plugin->call(MProgram, PI_PROGRAM_INFO_BINARIES, - sizeof(char *) * Pointers.size(), - Pointers.data(), nullptr); + + PiResult = Plugin->call_nocheck( + MProgram, PI_PROGRAM_INFO_BINARIES, sizeof(char *) * Pointers.size(), + Pointers.data(), nullptr); + if (PiResult == 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(PiResult); + } + return Result; } @@ -389,24 +467,24 @@ std::pair program_impl::get_pi_kernel_arg_mask_pair(const std::string &KernelName) const { std::pair Result; - const PluginPtr &Plugin = getPlugin(); - sycl::detail::pi::PiResult Err = - Plugin->call_nocheck( - MProgram, KernelName.c_str(), &Result.first); - if (Err == PI_ERROR_INVALID_KERNEL_NAME) { - throw invalid_object_error( - "This instance of program does not contain the kernel requested", - Err); - } - Plugin->checkPiResult(Err); - - // Some PI Plugins (like OpenCL) require this call to enable USM - // For others, PI will turn this into a NOP. - if (getContextImplPtr()->getPlatformImpl()->supports_usm()) - Plugin->call( - Result.first, PI_USM_INDIRECT_ACCESS, sizeof(pi_bool), &PI_TRUE); + const PluginPtr &Plugin = getPlugin(); + sycl::detail::pi::PiResult Err = + Plugin->call_nocheck( + MProgram, KernelName.c_str(), &Result.first); + if (Err == PI_ERROR_INVALID_KERNEL_NAME) { + throw invalid_object_error( + "This instance of program does not contain the kernel requested", Err); + } + Plugin->checkPiResult(Err); - return Result; + // Some PI Plugins (like OpenCL) require this call to enable USM + // For others, PI will turn this into a NOP. + if (getContextImplPtr()->getPlatformImpl()->supports_usm()) { + Plugin->call( + Result.first, PI_USM_INDIRECT_ACCESS, sizeof(pi_bool), &PI_TRUE); + } + + return Result; } std::vector @@ -476,8 +554,18 @@ void program_impl::flush_spec_constants( auto [Id, Offset, Size] = Descriptors.consume(); - Ctx->getPlugin()->call( - NativePrg, Id, Size, SC.getValuePtr() + Offset); + sycl::detail::pi::PiResult Result = + Ctx->getPlugin() + ->call_nocheck( + NativePrg, Id, Size, SC.getValuePtr() + Offset); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Program set specialization constant command not supported by " + "backend."); + } else { + Ctx->getPlugin()->checkPiResult(Result); + } } } } @@ -487,7 +575,16 @@ pi_native_handle program_impl::getNative() const { if (getContextImplPtr()->getBackend() == backend::opencl) Plugin->call(MProgram); pi_native_handle Handle; - Plugin->call(MProgram, &Handle); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(MProgram, + &Handle); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Program get native handle command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } return Handle; } diff --git a/sycl/source/detail/program_manager/program_manager.cpp b/sycl/source/detail/program_manager/program_manager.cpp index 442c004278e2a..988051d5a7d5e 100644 --- a/sycl/source/detail/program_manager/program_manager.cpp +++ b/sycl/source/detail/program_manager/program_manager.cpp @@ -60,8 +60,17 @@ enableITTAnnotationsIfNeeded(const sycl::detail::pi::PiProgram &Prog, const PluginPtr &Plugin) { if (SYCLConfig::get() != nullptr) { constexpr char SpecValue = 1; - Plugin->call( - Prog, ITTSpecConstId, sizeof(char), &SpecValue); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Prog, ITTSpecConstId, sizeof(char), &SpecValue); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Program set specialization constant command not supported by " + "backend."); + } else { + Plugin->checkPiResult(Result); + } } } @@ -88,9 +97,17 @@ createBinaryProgram(const ContextImplPtr Context, const device &Device, const sycl::detail::pi::PiDevice PiDevice = getSyclObjImpl(Device)->getHandleRef(); pi_int32 BinaryStatus = CL_SUCCESS; - Plugin->call( - Context->getHandleRef(), 1 /*one binary*/, &PiDevice, &DataLen, &Data, - Metadata.size(), Metadata.data(), &BinaryStatus, &Program); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Context->getHandleRef(), 1 /*one binary*/, &PiDevice, &DataLen, &Data, + Metadata.size(), Metadata.data(), &BinaryStatus, &Program); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Program create with binary command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } if (BinaryStatus != CL_SUCCESS) { throw runtime_error("Creating program with binary failed.", BinaryStatus); @@ -546,9 +563,15 @@ sycl::detail::pi::PiProgram ProgramManager::getBuiltPIProgram( } pi_bool MustBuildOnSubdevice = PI_TRUE; - ContextImpl->getPlugin()->call( - RootDevImpl->getHandleRef(), PI_DEVICE_INFO_BUILD_ON_SUBDEVICE, - sizeof(pi_bool), &MustBuildOnSubdevice, nullptr); + sycl::detail::pi::PiResult Result = + ContextImpl->getPlugin()->call_nocheck( + RootDevImpl->getHandleRef(), PI_DEVICE_INFO_BUILD_ON_SUBDEVICE, + sizeof(pi_bool), &MustBuildOnSubdevice, 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."); + } DeviceImplPtr Dev = (MustBuildOnSubdevice == PI_TRUE) ? DeviceImpl : RootDevImpl; @@ -737,9 +760,18 @@ ProgramManager::getPiProgramFromPiKernel(sycl::detail::pi::PiKernel Kernel, const ContextImplPtr Context) { sycl::detail::pi::PiProgram Program; const PluginPtr &Plugin = Context->getPlugin(); - Plugin->call(Kernel, PI_KERNEL_INFO_PROGRAM, - sizeof(sycl::detail::pi::PiProgram), - &Program, nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Kernel, PI_KERNEL_INFO_PROGRAM, sizeof(sycl::detail::pi::PiProgram), + &Program, nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Kernel get info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } + return Program; } @@ -748,38 +780,85 @@ ProgramManager::getProgramBuildLog(const sycl::detail::pi::PiProgram &Program, const ContextImplPtr Context) { size_t PIDevicesSize = 0; const PluginPtr &Plugin = Context->getPlugin(); - Plugin->call(Program, PI_PROGRAM_INFO_DEVICES, 0, - nullptr, &PIDevicesSize); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Program, PI_PROGRAM_INFO_DEVICES, 0, nullptr, &PIDevicesSize); + 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); + } + std::vector PIDevices( PIDevicesSize / sizeof(sycl::detail::pi::PiDevice)); - Plugin->call(Program, PI_PROGRAM_INFO_DEVICES, - PIDevicesSize, PIDevices.data(), - nullptr); + Result = Plugin->call_nocheck( + Program, PI_PROGRAM_INFO_DEVICES, PIDevicesSize, PIDevices.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); + } + std::string Log = "The program was built for " + std::to_string(PIDevices.size()) + " devices"; for (sycl::detail::pi::PiDevice &Device : PIDevices) { std::string DeviceBuildInfoString; size_t DeviceBuildInfoStrSize = 0; - Plugin->call( - Program, Device, PI_PROGRAM_BUILD_INFO_LOG, 0, nullptr, - &DeviceBuildInfoStrSize); + + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Program, Device, PI_PROGRAM_BUILD_INFO_LOG, 0, nullptr, + &DeviceBuildInfoStrSize); + 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); + } + if (DeviceBuildInfoStrSize > 0) { std::vector DeviceBuildInfo(DeviceBuildInfoStrSize); - Plugin->call( - Program, Device, PI_PROGRAM_BUILD_INFO_LOG, DeviceBuildInfoStrSize, - DeviceBuildInfo.data(), nullptr); + + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Program, Device, PI_PROGRAM_BUILD_INFO_LOG, + DeviceBuildInfoStrSize, DeviceBuildInfo.data(), 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); + } DeviceBuildInfoString = std::string(DeviceBuildInfo.data()); } std::string DeviceNameString; size_t DeviceNameStrSize = 0; - Plugin->call(Device, PI_DEVICE_INFO_NAME, 0, - nullptr, &DeviceNameStrSize); + Result = Plugin->call_nocheck( + Device, PI_DEVICE_INFO_NAME, 0, nullptr, &DeviceNameStrSize); + 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."); + } + if (DeviceNameStrSize > 0) { std::vector DeviceName(DeviceNameStrSize); - Plugin->call(Device, PI_DEVICE_INFO_NAME, - DeviceNameStrSize, - DeviceName.data(), nullptr); + Result = Plugin->call_nocheck( + Device, PI_DEVICE_INFO_NAME, DeviceNameStrSize, DeviceName.data(), + 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."); + } DeviceNameString = std::string(DeviceName.data()); } Log += "\nBuild program log for '" + DeviceNameString + "':\n" + @@ -2006,9 +2085,18 @@ setSpecializationConstants(const std::shared_ptr &InputImpl, std::ignore = SpecConstNames; for (const device_image_impl::SpecConstDescT &SpecIDDesc : SpecConstDescs) { if (SpecIDDesc.IsSet) { - Plugin->call( + sycl::detail::pi::PiResult Result = Plugin->call_nocheck< + PiApiKind::piextProgramSetSpecializationConstant>( Prog, SpecIDDesc.ID, SpecIDDesc.Size, SpecConsts.data() + SpecIDDesc.BlobOffset); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Program set specialization constant command not supported by " + "backend."); + } else { + Plugin->checkPiResult(Result); + } } } } diff --git a/sycl/source/detail/queue_impl.cpp b/sycl/source/detail/queue_impl.cpp index 21dc5c4923b4a..d2fe543eae12a 100644 --- a/sycl/source/detail/queue_impl.cpp +++ b/sycl/source/detail/queue_impl.cpp @@ -42,10 +42,19 @@ getPIEvents(const std::vector &DepEvents) { template <> uint32_t queue_impl::get_info() const { sycl::detail::pi::PiResult result = PI_SUCCESS; - if (!is_host()) - getPlugin()->call( - MQueues[0], PI_QUEUE_INFO_REFERENCE_COUNT, sizeof(result), &result, - nullptr); + if (!is_host()) { + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MQueues[0], PI_QUEUE_INFO_REFERENCE_COUNT, sizeof(result), &result, + nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Queue get info command not supported by backend."); + } else { + getPlugin()->checkPiResult(Result); + } + } return result; } @@ -573,8 +582,16 @@ pi_native_handle queue_impl::getNative(int32_t &NativeHandleDesc) const { if (getContextImplPtr()->getBackend() == backend::opencl) Plugin->call(MQueues[0]); pi_native_handle Handle{}; - Plugin->call(MQueues[0], &Handle, - &NativeHandleDesc); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + MQueues[0], &Handle, &NativeHandleDesc); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Queue get native handle command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } return Handle; } @@ -597,11 +614,20 @@ bool queue_impl::ext_oneapi_empty() const { // Check the status of the backend queue if this is not a host queue. if (!is_host()) { pi_bool IsReady = false; - getPlugin()->call( - MQueues[0], PI_EXT_ONEAPI_QUEUE_INFO_EMPTY, sizeof(pi_bool), &IsReady, - nullptr); - if (!IsReady) + sycl::detail::pi::PiResult Result = + getPlugin()->call_nocheck( + MQueues[0], PI_EXT_ONEAPI_QUEUE_INFO_EMPTY, sizeof(pi_bool), + &IsReady, nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Queue get info command not supported by backend."); + } else { + getPlugin()->checkPiResult(Result); + } + if (!IsReady) { return false; + } } // We may have events like host tasks which are not submitted to the backend diff --git a/sycl/source/detail/queue_impl.hpp b/sycl/source/detail/queue_impl.hpp index 4dfe4bd39d4d1..64b48ce46533d 100644 --- a/sycl/source/detail/queue_impl.hpp +++ b/sycl/source/detail/queue_impl.hpp @@ -230,8 +230,18 @@ class queue_impl { sycl::detail::pi::PiDevice DevicePI{}; const PluginPtr &Plugin = getPlugin(); // TODO catch an exception and put it to list of asynchronous exceptions - Plugin->call( - MQueues[0], PI_QUEUE_INFO_DEVICE, sizeof(DevicePI), &DevicePI, nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + MQueues[0], PI_QUEUE_INFO_DEVICE, sizeof(DevicePI), &DevicePI, + nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Queue get info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } + MDevice = MContext->findMatchingDeviceImpl(DevicePI); if (MDevice == nullptr) { throw sycl::exception( diff --git a/sycl/source/detail/sampler_impl.cpp b/sycl/source/detail/sampler_impl.cpp index c2af7884a164c..4f52c2e33baad 100644 --- a/sycl/source/detail/sampler_impl.cpp +++ b/sycl/source/detail/sampler_impl.cpp @@ -22,21 +22,53 @@ sampler_impl::sampler_impl(coordinate_normalization_mode normalizationMode, MFiltMode(filteringMode), MPropList(propList) {} sampler_impl::sampler_impl(cl_sampler clSampler, const context &syclContext) { - sycl::detail::pi::PiSampler Sampler = pi::cast(clSampler); MContextToSampler[syclContext] = Sampler; const PluginPtr &Plugin = getSyclObjImpl(syclContext)->getPlugin(); - Plugin->call(Sampler); - Plugin->call( + + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(Sampler); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Sampler retain command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } + + Result = Plugin->call_nocheck( Sampler, PI_SAMPLER_INFO_NORMALIZED_COORDS, sizeof(pi_bool), &MCoordNormMode, nullptr); - Plugin->call( + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Sampler get info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } + + Result = Plugin->call_nocheck( Sampler, PI_SAMPLER_INFO_ADDRESSING_MODE, sizeof(pi_sampler_addressing_mode), &MAddrMode, nullptr); - Plugin->call( + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Sampler get info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } + + Result = Plugin->call_nocheck( Sampler, PI_SAMPLER_INFO_FILTER_MODE, sizeof(pi_sampler_filter_mode), &MFiltMode, nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Sampler get info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } sampler_impl::~sampler_impl() { @@ -44,7 +76,13 @@ sampler_impl::~sampler_impl() { for (auto &Iter : MContextToSampler) { // TODO catch an exception and add it to the list of asynchronous exceptions const PluginPtr &Plugin = getSyclObjImpl(Iter.first)->getPlugin(); - Plugin->call(Iter.second); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(Iter.second); + if (Result == PI_ERROR_INVALID_OPERATION) { + assert(!"Sampler release command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } } @@ -66,18 +104,20 @@ sampler_impl::getOrCreateSampler(const context &Context) { static_cast(MFiltMode), 0}; - sycl::detail::pi::PiResult errcode_ret = PI_SUCCESS; sycl::detail::pi::PiSampler resultSampler = nullptr; const PluginPtr &Plugin = getSyclObjImpl(Context)->getPlugin(); - errcode_ret = Plugin->call_nocheck( - getSyclObjImpl(Context)->getHandleRef(), sprops, &resultSampler); - - if (errcode_ret == PI_ERROR_UNSUPPORTED_FEATURE) - throw sycl::exception(sycl::errc::feature_not_supported, - "Images are not supported by this device."); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + getSyclObjImpl(Context)->getHandleRef(), sprops, &resultSampler); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Sampler create command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } - Plugin->checkPiResult(errcode_ret); std::lock_guard Lock(MMutex); MContextToSampler[Context] = resultSampler; diff --git a/sycl/source/detail/scheduler/commands.cpp b/sycl/source/detail/scheduler/commands.cpp index 056a4239fde1c..c3eb0f4703c49 100644 --- a/sycl/source/detail/scheduler/commands.cpp +++ b/sycl/source/detail/scheduler/commands.cpp @@ -338,8 +338,16 @@ class DispatchHostTask { std::vector RawEvents = MThisCmd->getPiEvents(PluginWithEvents.second); try { - PluginWithEvents.first->call(RawEvents.size(), - RawEvents.data()); + sycl::detail::pi::PiResult Result = + PluginWithEvents.first->call_nocheck( + RawEvents.size(), RawEvents.data()); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event wait command not supported by backend."); + } else { + PluginWithEvents.first->checkPiResult(Result); + } } catch (const sycl::exception &E) { CGHostTask &HostTask = static_cast(MThisCmd->getCG()); HostTask.MQueue->reportAsyncException(std::current_exception()); @@ -481,8 +489,17 @@ void Command::waitForEvents(QueueImplPtr Queue, for (auto &CtxWithEvents : RequiredEventsPerContext) { std::vector RawEvents = getPiEvents(CtxWithEvents.second); - CtxWithEvents.first->getPlugin()->call( - RawEvents.size(), RawEvents.data()); + sycl::detail::pi::PiResult Result = + CtxWithEvents.first->getPlugin() + ->call_nocheck(RawEvents.size(), + RawEvents.data()); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event wait command not supported by backend."); + } else { + CtxWithEvents.first->getPlugin()->checkPiResult(Result); + } } } else { #ifndef NDEBUG @@ -496,10 +513,19 @@ void Command::waitForEvents(QueueImplPtr Queue, flushCrossQueueDeps(EventImpls, getWorkerQueue()); const PluginPtr &Plugin = Queue->getPlugin(); - if (MEvent != nullptr) + if (MEvent != nullptr) { MEvent->setHostEnqueueTime(); - Plugin->call( - Queue->getHandleRef(), RawEvents.size(), &RawEvents[0], &Event); + } + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Queue->getHandleRef(), RawEvents.size(), &RawEvents[0], &Event); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue events wait command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } } } @@ -2326,8 +2352,16 @@ void SetArgBasedOnType( sampler *SamplerPtr = (sampler *)Arg.MPtr; sycl::detail::pi::PiSampler Sampler = detail::getSyclObjImpl(*SamplerPtr)->getOrCreateSampler(Context); - Plugin->call(Kernel, NextTrueIndex, - &Sampler); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Kernel, NextTrueIndex, &Sampler); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Kernel set arg sampler command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } break; } case kernel_param_kind_t::kind_pointer: { @@ -2423,6 +2457,15 @@ static pi_result SetKernelParamsAndLaunch( &NDRDesc.GlobalSize[0], LocalSize, RawEvents.size(), RawEvents.empty() ? nullptr : &RawEvents[0], OutEventImpl ? &OutEventImpl->getHandleRef() : nullptr); + + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue kernel launch handle command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } + return Error; } @@ -2534,7 +2577,7 @@ pi_int32 enqueueImpCommandBufferKernel( LocalSize = RequiredWGSize; } - pi_result Res = Plugin->call_nocheck< + pi_result Result = Plugin->call_nocheck< sycl::detail::PiApiKind::piextCommandBufferNDRangeKernel>( CommandBuffer, PiKernel, NDRDesc.Dims, &NDRDesc.GlobalOffset[0], &NDRDesc.GlobalSize[0], LocalSize, SyncPoints.size(), @@ -2546,13 +2589,17 @@ pi_int32 enqueueImpCommandBufferKernel( Plugin->call(PiProgram); } - if (Res != pi_result::PI_SUCCESS) { + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue command buffer command not supported by backend."); + } else if (Result != pi_result::PI_SUCCESS) { const device_impl &DeviceImplem = *(DeviceImpl); - detail::enqueue_kernel_launch::handleErrorOrWarning(Res, DeviceImplem, + detail::enqueue_kernel_launch::handleErrorOrWarning(Result, DeviceImplem, PiKernel, NDRDesc); } - return Res; + return Result; } pi_int32 enqueueImpKernel( @@ -2706,26 +2753,37 @@ enqueueReadWriteHostPipe(const QueueImplPtr &Queue, const std::string &PipeName, const PluginPtr &Plugin = Queue->getPlugin(); pi_queue pi_q = Queue->getHandleRef(); - pi_result Error; + pi_result Result; + std::string ResultString = + "Enqueue read host pipe command not supported by backend."; auto OutEvent = OutEventImpl ? &OutEventImpl->getHandleRef() : nullptr; if (OutEventImpl != nullptr) OutEventImpl->setHostEnqueueTime(); if (read) { - Error = + Result = Plugin->call_nocheck( pi_q, Program, PipeName.c_str(), blocking, ptr, size, RawEvents.size(), RawEvents.empty() ? nullptr : &RawEvents[0], OutEvent); } else { - Error = + Result = Plugin ->call_nocheck( pi_q, Program, PipeName.c_str(), blocking, ptr, size, RawEvents.size(), RawEvents.empty() ? nullptr : &RawEvents[0], OutEvent); + ResultString = "Enqueue write host pipe command not supported by backend."; } - return Error; + + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), ResultString); + } else { + Plugin->checkPiResult(Result); + } + + return Result; } pi_int32 ExecCGCommand::enqueueImpCommandBuffer() { @@ -2740,7 +2798,16 @@ pi_int32 ExecCGCommand::enqueueImpCommandBuffer() { std::vector RawEvents = getPiEvents(EventImpls); if (!RawEvents.empty()) { const PluginPtr &Plugin = MQueue->getPlugin(); - Plugin->call(RawEvents.size(), &RawEvents[0]); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(RawEvents.size(), + &RawEvents[0]); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event wait command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } sycl::detail::pi::PiEvent *Event = @@ -2987,7 +3054,16 @@ pi_int32 ExecCGCommand::enqueueImpQueue() { if (!RawEvents.empty()) { // Assuming that the events are for devices to the same Plugin. const PluginPtr &Plugin = EventImpls[0]->getPlugin(); - Plugin->call(RawEvents.size(), &RawEvents[0]); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(RawEvents.size(), + &RawEvents[0]); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Event wait command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } if (MQueue->is_host()) { @@ -2996,13 +3072,22 @@ pi_int32 ExecCGCommand::enqueueImpQueue() { } else { assert(MQueue->getDeviceImplPtr()->getBackend() == backend::ext_intel_esimd_emulator); - if (MEvent != nullptr) + if (MEvent != nullptr) { MEvent->setHostEnqueueTime(); - MQueue->getPlugin()->call( - nullptr, - reinterpret_cast(ExecKernel->MHostKernel->getPtr()), - NDRDesc.Dims, &NDRDesc.GlobalOffset[0], &NDRDesc.GlobalSize[0], - &NDRDesc.LocalSize[0], 0, nullptr, nullptr); + } + sycl::detail::pi::PiResult Result = + MQueue->getPlugin()->call_nocheck( + nullptr, + reinterpret_cast(ExecKernel->MHostKernel->getPtr()), + NDRDesc.Dims, &NDRDesc.GlobalOffset[0], &NDRDesc.GlobalSize[0], + &NDRDesc.LocalSize[0], 0, nullptr, nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue kernel launch command not supported by backend."); + } else { + MQueue->getPlugin()->checkPiResult(Result); + } } return PI_SUCCESS; } @@ -3159,10 +3244,19 @@ pi_int32 ExecCGCommand::enqueueImpQueue() { return PI_SUCCESS; } const PluginPtr &Plugin = MQueue->getPlugin(); - if (MEvent != nullptr) + if (MEvent != nullptr) { MEvent->setHostEnqueueTime(); - Plugin->call( - MQueue->getHandleRef(), 0, nullptr, Event); + } + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + MQueue->getHandleRef(), 0, nullptr, Event); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue events wait with barrier command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } return PI_SUCCESS; } @@ -3177,10 +3271,19 @@ pi_int32 ExecCGCommand::enqueueImpQueue() { return PI_SUCCESS; } const PluginPtr &Plugin = MQueue->getPlugin(); - if (MEvent != nullptr) + if (MEvent != nullptr) { MEvent->setHostEnqueueTime(); - Plugin->call( - MQueue->getHandleRef(), PiEvents.size(), &PiEvents[0], Event); + } + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + MQueue->getHandleRef(), PiEvents.size(), &PiEvents[0], Event); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue events wait with barrier command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } return PI_SUCCESS; } @@ -3221,13 +3324,23 @@ pi_int32 ExecCGCommand::enqueueImpQueue() { case CG::CGTYPE::ExecCommandBuffer: { CGExecCommandBuffer *CmdBufferCG = static_cast(MCommandGroup.get()); - if (MEvent != nullptr) + if (MEvent != nullptr) { MEvent->setHostEnqueueTime(); - return MQueue->getPlugin() - ->call_nocheck( - CmdBufferCG->MCommandBuffer, MQueue->getHandleRef(), - RawEvents.size(), RawEvents.empty() ? nullptr : &RawEvents[0], - Event); + } + sycl::detail::pi::PiResult Result = + MQueue->getPlugin() + ->call_nocheck( + CmdBufferCG->MCommandBuffer, MQueue->getHandleRef(), + RawEvents.size(), RawEvents.empty() ? nullptr : &RawEvents[0], + Event); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue command buffer command not supported by backend."); + } else { + MQueue->getPlugin()->checkPiResult(Result); + } + return Result; } case CG::CGTYPE::CopyImage: { CGCopyImage *Copy = (CGCopyImage *)MCommandGroup.get(); diff --git a/sycl/source/detail/sycl_mem_obj_t.cpp b/sycl/source/detail/sycl_mem_obj_t.cpp index bb4c5f4e1441d..e76e078479a5f 100644 --- a/sycl/source/detail/sycl_mem_obj_t.cpp +++ b/sycl/source/detail/sycl_mem_obj_t.cpp @@ -42,16 +42,38 @@ SYCLMemObjT::SYCLMemObjT(pi_native_handle MemObject, const context &SyclContext, sycl::detail::pi::PiContext Context = nullptr; const PluginPtr &Plugin = getPlugin(); - Plugin->call( - MemObject, MInteropContext->getHandleRef(), OwnNativeHandle, - &MInteropMemObject); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + MemObject, MInteropContext->getHandleRef(), OwnNativeHandle, + &MInteropMemObject); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem create with native handle command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } // Get the size of the buffer in bytes - Plugin->call( + Result = Plugin->call_nocheck( MInteropMemObject, PI_MEM_SIZE, sizeof(size_t), &MSizeInBytes, nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem get info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } - Plugin->call(MInteropMemObject, PI_MEM_CONTEXT, - sizeof(Context), &Context, nullptr); + Result = Plugin->call_nocheck( + MInteropMemObject, PI_MEM_CONTEXT, sizeof(Context), &Context, nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem get info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } if (MInteropContext->getHandleRef() != Context) throw sycl::invalid_parameter_error( @@ -106,12 +128,28 @@ SYCLMemObjT::SYCLMemObjT(pi_native_handle MemObject, const context &SyclContext, Desc.num_samples = 0; Desc.buffer = nullptr; - Plugin->call( + sycl::detail::pi::PiResult Result = Plugin->call_nocheck< + detail::PiApiKind::piextMemImageCreateWithNativeHandle>( MemObject, MInteropContext->getHandleRef(), OwnNativeHandle, &Format, &Desc, &MInteropMemObject); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem image create with native handle command not supported by " + "backend."); + } else { + Plugin->checkPiResult(Result); + } - Plugin->call(MInteropMemObject, PI_MEM_CONTEXT, - sizeof(Context), &Context, nullptr); + Result = Plugin->call_nocheck( + MInteropMemObject, PI_MEM_CONTEXT, sizeof(Context), &Context, nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem get info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } if (MInteropContext->getHandleRef() != Context) throw sycl::invalid_parameter_error( @@ -177,9 +215,17 @@ size_t SYCLMemObjT::getBufSizeForContext(const ContextImplPtr &Context, size_t BufSize = 0; const PluginPtr &Plugin = Context->getPlugin(); // TODO is there something required to support non-OpenCL backends? - Plugin->call( - detail::pi::cast(MemObject), PI_MEM_SIZE, - sizeof(size_t), &BufSize, nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + detail::pi::cast(MemObject), PI_MEM_SIZE, + sizeof(size_t), &BufSize, nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Mem get info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } return BufSize; } diff --git a/sycl/source/detail/usm/usm_impl.cpp b/sycl/source/detail/usm/usm_impl.cpp index ecf63bc63e427..990bc2832145e 100755 --- a/sycl/source/detail/usm/usm_impl.cpp +++ b/sycl/source/detail/usm/usm_impl.cpp @@ -587,17 +587,19 @@ alloc get_pointer_type(const void *Ptr, const context &Ctxt) { // query type using PI function const detail::PluginPtr &Plugin = CtxImpl->getPlugin(); - sycl::detail::pi::PiResult Err = + sycl::detail::pi::PiResult Result = Plugin->call_nocheck( PICtx, Ptr, PI_MEM_ALLOC_TYPE, sizeof(pi_usm_type), &AllocTy, nullptr); - - // PI_ERROR_INVALID_VALUE means USM doesn't know about this ptr - if (Err == PI_ERROR_INVALID_VALUE) + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "USM get mem alloc info command not supported by backend."); + } else if (Result == PI_ERROR_INVALID_VALUE) { return alloc::unknown; - // otherwise PI_SUCCESS is expected - if (Err != PI_SUCCESS) { - Plugin->reportPiError(Err, "get_pointer_type()"); + } else if (Result != PI_SUCCESS) { + // otherwise PI_SUCCESS is expected + Plugin->reportPiError(Result, "get_pointer_type()"); } alloc ResultAlloc; @@ -651,8 +653,17 @@ device get_pointer_device(const void *Ptr, const context &Ctxt) { // query device using PI function const detail::PluginPtr &Plugin = CtxImpl->getPlugin(); - Plugin->call( - PICtx, Ptr, PI_MEM_ALLOC_DEVICE, sizeof(pi_device), &DeviceId, nullptr); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + PICtx, Ptr, PI_MEM_ALLOC_DEVICE, sizeof(pi_device), &DeviceId, + nullptr); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "USM get mem alloc info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } // The device is not necessarily a member of the context, it could be a // member's descendant instead. Fetch the corresponding device from the cache. @@ -673,7 +684,15 @@ static void prepare_for_usm_device_copy(const void *Ptr, size_t Size, pi_context PICtx = CtxImpl->getHandleRef(); // Call the PI function const detail::PluginPtr &Plugin = CtxImpl->getPlugin(); - Plugin->call(Ptr, Size, PICtx); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(Ptr, Size, PICtx); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "USM import command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } static void release_from_usm_device_copy(const void *Ptr, const context &Ctxt) { @@ -681,7 +700,15 @@ static void release_from_usm_device_copy(const void *Ptr, const context &Ctxt) { pi_context PICtx = CtxImpl->getHandleRef(); // Call the PI function const detail::PluginPtr &Plugin = CtxImpl->getPlugin(); - Plugin->call(Ptr, PICtx); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(Ptr, PICtx); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "USM release command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } namespace ext::oneapi::experimental { diff --git a/sycl/source/device.cpp b/sycl/source/device.cpp index 70aa37aad26a2..4454c13f50d15 100644 --- a/sycl/source/device.cpp +++ b/sycl/source/device.cpp @@ -36,8 +36,18 @@ device::device(cl_device_id DeviceId) { // must retain it in order to adhere to SYCL 1.2.1 spec (Rev6, section 4.3.1.) sycl::detail::pi::PiDevice Device; auto Plugin = sycl::detail::pi::getPlugin(); - Plugin->call( - detail::pi::cast(DeviceId), nullptr, &Device); + sycl::detail::pi::PiResult Result = + Plugin + ->call_nocheck( + detail::pi::cast(DeviceId), nullptr, &Device); + 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); + } + auto Platform = detail::platform_impl::getPlatformFromPiDevice(Device, Plugin); impl = Platform->getOrMakeDeviceImpl(Device, Platform); @@ -223,7 +233,16 @@ void device::ext_oneapi_enable_peer_access(const device &peer) { const sycl::detail::pi::PiDevice Peer = peer.impl->getHandleRef(); if (Device != Peer) { auto Plugin = impl->getPlugin(); - Plugin->call(Device, Peer); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(Device, + Peer); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enable peer access command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } } @@ -232,7 +251,16 @@ void device::ext_oneapi_disable_peer_access(const device &peer) { const sycl::detail::pi::PiDevice Peer = peer.impl->getHandleRef(); if (Device != Peer) { auto Plugin = impl->getPlugin(); - Plugin->call(Device, Peer); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck(Device, + Peer); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Disable peer access command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } } } @@ -258,9 +286,18 @@ bool device::ext_oneapi_can_access_peer(const device &peer, throw sycl::exception(make_error_code(errc::invalid), "Unrecognized peer access attribute."); }(); + auto Plugin = impl->getPlugin(); - Plugin->call( - Device, Peer, PiAttr, sizeof(int), &value, &returnSize); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Device, Peer, PiAttr, sizeof(int), &value, &returnSize); + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Peer access get info command not supported by backend."); + } else { + Plugin->checkPiResult(Result); + } return value == 1; } diff --git a/sycl/source/handler.cpp b/sycl/source/handler.cpp index 17cde0994b314..b8baa350142df 100644 --- a/sycl/source/handler.cpp +++ b/sycl/source/handler.cpp @@ -279,17 +279,17 @@ event handler::finalize() { if (MQueue->getDeviceImplPtr()->getBackend() == backend::ext_intel_esimd_emulator) { // Capture the host timestamp for profiling (queue time) - if (NewEvent != nullptr) + if (NewEvent != nullptr) { NewEvent->setHostEnqueueTime(); [&](auto... Args) { if (MImpl->MKernelIsCooperative) { - MQueue->getPlugin() - ->call< + Result = MQueue->getPlugin() + ->call_nocheck< detail::PiApiKind::piextEnqueueCooperativeKernelLaunch>( Args...); } else { - MQueue->getPlugin() - ->call(Args...); + Result = MQueue->getPlugin() + ->call_nocheck(Args...); } }(/* queue */ nullptr, @@ -303,7 +303,14 @@ event handler::finalize() { /* num_events_in_wait_list */ 0, /* event_wait_list */ nullptr, /* event */ nullptr); - Result = PI_SUCCESS; + if (Result == PI_ERROR_INVALID_OPERATION) { + throw sycl::exception( + sycl::make_error_code(sycl::errc::feature_not_supported), + "Enqueue kernel launch command not supported by backend."); + } else { + MQueue->getPlugin()->checkPiResult( + (sycl::detail::pi::PiResult)Result); + } } else { Result = enqueueImpKernel( MQueue, MNDRDesc, MArgs, KernelBundleImpPtr, MKernel, @@ -1533,14 +1540,20 @@ void handler::setUserFacingNodeType(ext::oneapi::experimental::node_type Type) { std::optional> handler::getMaxWorkGroups() { auto Dev = detail::getSyclObjImpl(detail::getDeviceFromHandler(*this)); - std::array PiResult = {}; - auto Ret = Dev->getPlugin()->call_nocheck( - Dev->getHandleRef(), - PiInfoCode< - ext::oneapi::experimental::info::device::max_work_groups<3>>::value, - sizeof(PiResult), &PiResult, nullptr); - if (Ret == PI_SUCCESS) { - return PiResult; + std::array Result = {}; + sycl::detail::pi::PiResult PiResult = + Dev->getPlugin()->call_nocheck( + Dev->getHandleRef(), + PiInfoCode>::value, + sizeof(Result), &Result, 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."); + } + if (PiResult == PI_SUCCESS) { + return Result; } return {}; } diff --git a/sycl/source/interop_handle.cpp b/sycl/source/interop_handle.cpp index cd479493bbae3..df11207c4b55e 100644 --- a/sycl/source/interop_handle.cpp +++ b/sycl/source/interop_handle.cpp @@ -34,8 +34,16 @@ pi_native_handle interop_handle::getNativeMem(detail::Requirement *Req) const { auto Plugin = MQueue->getPlugin(); pi_native_handle Handle; - Plugin->call( - Iter->second, MDevice->getHandleRef(), &Handle); + sycl::detail::pi::PiResult Result = + Plugin->call_nocheck( + Iter->second, &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); + } return Handle; } diff --git a/sycl/test-e2e/Plugin/ur_unsupported_feature.cpp b/sycl/test-e2e/Plugin/ur_unsupported_feature.cpp new file mode 100644 index 0000000000000..575db230c154a --- /dev/null +++ b/sycl/test-e2e/Plugin/ur_unsupported_feature.cpp @@ -0,0 +1,41 @@ +// REQUIRES: opencl + +// RUN: %{build} -o %t.out +// RUN: %{run} %t.out + +// Tests that the Unified Runtime "UR_RESULT_ERROR_UNSUPPORTED_FEATURE" error +// code is passed up to the SYCL runtime and is handled appropriately, when an +// entry-point is not implemented in a given adapter. +// IMPORTANT: This test should be updated if the feature used for testing later +// receives support - use another unsupported feature instead +// Currently using "piextMemImageAllocate" + +#include + +using namespace sycl; + +int main() { + sycl::device Device; + sycl::queue Queue(Device); + sycl::context Context = Queue.get_context(); + + sycl::ext::oneapi::experimental::image_descriptor Descriptor( + {0}, sycl::image_channel_order::rgba, sycl::image_channel_type::fp32); + + bool Success = false; + + try { + sycl::ext::oneapi::experimental::image_mem imgMem0(Descriptor, Device, + Context); + } catch (sycl::exception &e) { + if (e.code() == sycl::errc::feature_not_supported) { + Success = true; + } + } + + // We want this test to succeed by "failing" and specifically catching a + // "sycl::errc::feature_not_supported" exception. + assert(Success); + + return 0; +}