diff --git a/include/ur.py b/include/ur.py index 810d8c2cba..fcee6474e2 100644 --- a/include/ur.py +++ b/include/ur.py @@ -1978,6 +1978,9 @@ class ur_function_v(IntEnum): PHYSICAL_MEM_RELEASE = 162 ## Enumerator for ::urPhysicalMemRelease USM_IMPORT_EXP = 163 ## Enumerator for ::urUSMImportExp USM_RELEASE_EXP = 164 ## Enumerator for ::urUSMReleaseExp + USM_P2P_ENABLE_PEER_ACCESS_EXP = 165 ## Enumerator for ::urUsmP2PEnablePeerAccessExp + USM_P2P_DISABLE_PEER_ACCESS_EXP = 166 ## Enumerator for ::urUsmP2PDisablePeerAccessExp + USM_P2P_PEER_ACCESS_GET_INFO_EXP = 167 ## Enumerator for ::urUsmP2PPeerAccessGetInfoExp class ur_function_t(c_int): def __str__(self): @@ -2082,6 +2085,19 @@ class ur_exp_command_buffer_sync_point_t(c_ulong): class ur_exp_command_buffer_handle_t(c_void_p): pass +############################################################################### +## @brief Supported peer info +class ur_exp_peer_info_v(IntEnum): + UR_PEER_ACCESS_SUPPORTED = 0 ## [uint32_t] 1 if P2P access is supported otherwise P2P access is not + ## supported. + UR_PEER_ATOMICS_SUPPORTED = 1 ## [uint32_t] 1 if atomic operations are supported over the P2P link, + ## otherwise such operations are not supported. + +class ur_exp_peer_info_t(c_int): + def __str__(self): + return str(ur_exp_peer_info_v(self.value)) + + ############################################################################### __use_win_types = "Windows" == platform.uname()[0] @@ -3303,6 +3319,37 @@ class ur_command_buffer_exp_dditable_t(Structure): ("pfnEnqueueExp", c_void_p) ## _urCommandBufferEnqueueExp_t ] +############################################################################### +## @brief Function-pointer for urUsmP2PEnablePeerAccessExp +if __use_win_types: + _urUsmP2PEnablePeerAccessExp_t = WINFUNCTYPE( ur_result_t, ur_device_handle_t, ur_device_handle_t ) +else: + _urUsmP2PEnablePeerAccessExp_t = CFUNCTYPE( ur_result_t, ur_device_handle_t, ur_device_handle_t ) + +############################################################################### +## @brief Function-pointer for urUsmP2PDisablePeerAccessExp +if __use_win_types: + _urUsmP2PDisablePeerAccessExp_t = WINFUNCTYPE( ur_result_t, ur_device_handle_t, ur_device_handle_t ) +else: + _urUsmP2PDisablePeerAccessExp_t = CFUNCTYPE( ur_result_t, ur_device_handle_t, ur_device_handle_t ) + +############################################################################### +## @brief Function-pointer for urUsmP2PPeerAccessGetInfoExp +if __use_win_types: + _urUsmP2PPeerAccessGetInfoExp_t = WINFUNCTYPE( ur_result_t, ur_device_handle_t, ur_device_handle_t, ur_exp_peer_info_t, c_size_t, c_void_p, POINTER(c_size_t) ) +else: + _urUsmP2PPeerAccessGetInfoExp_t = CFUNCTYPE( ur_result_t, ur_device_handle_t, ur_device_handle_t, ur_exp_peer_info_t, c_size_t, c_void_p, POINTER(c_size_t) ) + + +############################################################################### +## @brief Table of UsmP2PExp functions pointers +class ur_usm_p2p_exp_dditable_t(Structure): + _fields_ = [ + ("pfnEnablePeerAccessExp", c_void_p), ## _urUsmP2PEnablePeerAccessExp_t + ("pfnDisablePeerAccessExp", c_void_p), ## _urUsmP2PDisablePeerAccessExp_t + ("pfnPeerAccessGetInfoExp", c_void_p) ## _urUsmP2PPeerAccessGetInfoExp_t + ] + ############################################################################### ## @brief Function-pointer for urInit if __use_win_types: @@ -3485,6 +3532,7 @@ class ur_dditable_t(Structure): ("USM", ur_usm_dditable_t), ("USMExp", ur_usm_exp_dditable_t), ("CommandBufferExp", ur_command_buffer_exp_dditable_t), + ("UsmP2PExp", ur_usm_p2p_exp_dditable_t), ("Global", ur_global_dditable_t), ("VirtualMem", ur_virtual_mem_dditable_t), ("Device", ur_device_dditable_t) @@ -3772,6 +3820,18 @@ def __init__(self, version : ur_api_version_t): self.urCommandBufferAppendMembufferCopyRectExp = _urCommandBufferAppendMembufferCopyRectExp_t(self.__dditable.CommandBufferExp.pfnAppendMembufferCopyRectExp) self.urCommandBufferEnqueueExp = _urCommandBufferEnqueueExp_t(self.__dditable.CommandBufferExp.pfnEnqueueExp) + # call driver to get function pointers + UsmP2PExp = ur_usm_p2p_exp_dditable_t() + r = ur_result_v(self.__dll.urGetUsmP2PExpProcAddrTable(version, byref(UsmP2PExp))) + if r != ur_result_v.SUCCESS: + raise Exception(r) + self.__dditable.UsmP2PExp = UsmP2PExp + + # attach function interface to function address + self.urUsmP2PEnablePeerAccessExp = _urUsmP2PEnablePeerAccessExp_t(self.__dditable.UsmP2PExp.pfnEnablePeerAccessExp) + self.urUsmP2PDisablePeerAccessExp = _urUsmP2PDisablePeerAccessExp_t(self.__dditable.UsmP2PExp.pfnDisablePeerAccessExp) + self.urUsmP2PPeerAccessGetInfoExp = _urUsmP2PPeerAccessGetInfoExp_t(self.__dditable.UsmP2PExp.pfnPeerAccessGetInfoExp) + # call driver to get function pointers Global = ur_global_dditable_t() r = ur_result_v(self.__dll.urGetGlobalProcAddrTable(version, byref(Global))) diff --git a/include/ur_api.h b/include/ur_api.h index b976039ef9..309a309627 100644 --- a/include/ur_api.h +++ b/include/ur_api.h @@ -5274,6 +5274,9 @@ typedef enum ur_function_t { UR_FUNCTION_PHYSICAL_MEM_RELEASE = 162, ///< Enumerator for ::urPhysicalMemRelease UR_FUNCTION_USM_IMPORT_EXP = 163, ///< Enumerator for ::urUSMImportExp UR_FUNCTION_USM_RELEASE_EXP = 164, ///< Enumerator for ::urUSMReleaseExp + UR_FUNCTION_USM_P2P_ENABLE_PEER_ACCESS_EXP = 165, ///< Enumerator for ::urUsmP2PEnablePeerAccessExp + UR_FUNCTION_USM_P2P_DISABLE_PEER_ACCESS_EXP = 166, ///< Enumerator for ::urUsmP2PDisablePeerAccessExp + UR_FUNCTION_USM_P2P_PEER_ACCESS_GET_INFO_EXP = 167, ///< Enumerator for ::urUsmP2PPeerAccessGetInfoExp /// @cond UR_FUNCTION_FORCE_UINT32 = 0x7fffffff /// @endcond @@ -7442,6 +7445,152 @@ urUSMReleaseExp( void *pMem ///< [in] pointer to host memory object ); +#if !defined(__GNUC__) +#pragma endregion +#endif +// Intel 'oneAPI' Unified Runtime Experimental APIs for USM P2P +#if !defined(__GNUC__) +#pragma region usm p2p(experimental) +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief Supported peer info +typedef enum ur_exp_peer_info_t { + UR_EXP_PEER_INFO_UR_PEER_ACCESS_SUPPORTED = 0, ///< [uint32_t] 1 if P2P access is supported otherwise P2P access is not + ///< supported. + UR_EXP_PEER_INFO_UR_PEER_ATOMICS_SUPPORTED = 1, ///< [uint32_t] 1 if atomic operations are supported over the P2P link, + ///< otherwise such operations are not supported. + /// @cond + UR_EXP_PEER_INFO_FORCE_UINT32 = 0x7fffffff + /// @endcond + +} ur_exp_peer_info_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enable access to peer device memory +/// +/// @details +/// - Enables the command device to access and write device memory +/// allocations located on the peer device, provided that a P2P link +/// between the two devices is available. +/// - When Peer Access is successfully enabled, P2P memory accesses are +/// guaranteed to be allowed on the peer device until +/// ::urUsmP2PDisablePeerAccessExp is called. +/// - Note that the function operands may, but aren't guaranteed to, commute +/// for a given adapter: the peer device is not guaranteed to have access +/// to device memory allocations located on the command device. +/// - It is not guaranteed that the commutation relations of the function +/// arguments are identical for peer access and peer copies: For example, +/// for a given adapter the peer device may be able to copy data from the +/// command device, but not access and write the same data on the command +/// device. +/// - Consult the appropriate adapter driver documentation for details of +/// adapter specific behavior and native error codes that may be returned. +/// +/// @remarks +/// _Analogues_ +/// - **cuCtxEnablePeerAccess** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == commandDevice` +/// + `NULL == peerDevice` +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +UR_APIEXPORT ur_result_t UR_APICALL +urUsmP2PEnablePeerAccessExp( + ur_device_handle_t commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object +); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Disable access to peer device memory +/// +/// @details +/// - Disables the ability of the command device to access and write device +/// memory allocations located on the peer device, provided that a P2P +/// link between the two devices was enabled prior to the call. +/// - Note that the function operands may, but aren't guaranteed to, commute +/// for a given adapter. If, prior to the function call, the peer device +/// had access to device memory allocations on the command device, it is +/// not guaranteed to still have such access following the function +/// return. +/// - It is not guaranteed that the commutation relations of the function +/// arguments are identical for peer access and peer copies: For example +/// for a given adapter, if, prior to the call, the peer device had access +/// to device memory allocations on the command device, the peer device +/// may still, following the function call, be able to copy data from the +/// command device, but not access and write the same data on the command +/// device. +/// - Consult the appropriate adapter driver documentation for details of +/// adapter specific behavior and native error codes that may be returned. +/// +/// @remarks +/// _Analogues_ +/// - **cuCtxDisablePeerAccess** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == commandDevice` +/// + `NULL == peerDevice` +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +UR_APIEXPORT ur_result_t UR_APICALL +urUsmP2PDisablePeerAccessExp( + ur_device_handle_t commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object +); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Disable access to peer device memory +/// +/// @details +/// - Queries the peer access capabilities from the command device to the +/// peer device according to the query `propName`. +/// +/// @remarks +/// _Analogues_ +/// - **cuDeviceGetP2PAttribute** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == commandDevice` +/// + `NULL == peerDevice` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_EXP_PEER_INFO_UR_PEER_ATOMICS_SUPPORTED < propName` +/// - ::UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION +/// + If `propName` is not supported by the adapter. +/// - ::UR_RESULT_ERROR_INVALID_SIZE +/// + `propSize == 0 && pPropValue != NULL` +/// + If `propSize` is less than the real number of bytes needed to return the info. +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `propSize != 0 && pPropValue == NULL` +/// + `pPropValue == NULL && pPropSizeRet == NULL` +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +UR_APIEXPORT ur_result_t UR_APICALL +urUsmP2PPeerAccessGetInfoExp( + ur_device_handle_t commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice, ///< [in] handle of the peer device object + ur_exp_peer_info_t propName, ///< [in] type of the info to retrieve + size_t propSize, ///< [in] the number of bytes pointed to by pPropValue. + void *pPropValue, ///< [out][optional][typename(propName, propSize)] array of bytes holding + ///< the info. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return the info + ///< then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pPropValue is not used. + size_t *pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of the queried propName. +); + #if !defined(__GNUC__) #pragma endregion #endif @@ -9075,6 +9224,37 @@ typedef struct ur_command_buffer_enqueue_exp_params_t { ur_event_handle_t **pphEvent; } ur_command_buffer_enqueue_exp_params_t; +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function parameters for urUsmP2PEnablePeerAccessExp +/// @details Each entry is a pointer to the parameter passed to the function; +/// allowing the callback the ability to modify the parameter's value +typedef struct ur_usm_p2p_enable_peer_access_exp_params_t { + ur_device_handle_t *pcommandDevice; + ur_device_handle_t *ppeerDevice; +} ur_usm_p2p_enable_peer_access_exp_params_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function parameters for urUsmP2PDisablePeerAccessExp +/// @details Each entry is a pointer to the parameter passed to the function; +/// allowing the callback the ability to modify the parameter's value +typedef struct ur_usm_p2p_disable_peer_access_exp_params_t { + ur_device_handle_t *pcommandDevice; + ur_device_handle_t *ppeerDevice; +} ur_usm_p2p_disable_peer_access_exp_params_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function parameters for urUsmP2PPeerAccessGetInfoExp +/// @details Each entry is a pointer to the parameter passed to the function; +/// allowing the callback the ability to modify the parameter's value +typedef struct ur_usm_p2p_peer_access_get_info_exp_params_t { + ur_device_handle_t *pcommandDevice; + ur_device_handle_t *ppeerDevice; + ur_exp_peer_info_t *ppropName; + size_t *ppropSize; + void **ppPropValue; + size_t **ppPropSizeRet; +} ur_usm_p2p_peer_access_get_info_exp_params_t; + /////////////////////////////////////////////////////////////////////////////// /// @brief Function parameters for urInit /// @details Each entry is a pointer to the parameter passed to the function; diff --git a/include/ur_ddi.h b/include/ur_ddi.h index 25e775fef1..795edc605b 100644 --- a/include/ur_ddi.h +++ b/include/ur_ddi.h @@ -1731,6 +1731,57 @@ typedef ur_result_t(UR_APICALL *ur_pfnGetCommandBufferExpProcAddrTable_t)( ur_api_version_t, ur_command_buffer_exp_dditable_t *); +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for urUsmP2PEnablePeerAccessExp +typedef ur_result_t(UR_APICALL *ur_pfnUsmP2PEnablePeerAccessExp_t)( + ur_device_handle_t, + ur_device_handle_t); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for urUsmP2PDisablePeerAccessExp +typedef ur_result_t(UR_APICALL *ur_pfnUsmP2PDisablePeerAccessExp_t)( + ur_device_handle_t, + ur_device_handle_t); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for urUsmP2PPeerAccessGetInfoExp +typedef ur_result_t(UR_APICALL *ur_pfnUsmP2PPeerAccessGetInfoExp_t)( + ur_device_handle_t, + ur_device_handle_t, + ur_exp_peer_info_t, + size_t, + void *, + size_t *); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Table of UsmP2PExp functions pointers +typedef struct ur_usm_p2p_exp_dditable_t { + ur_pfnUsmP2PEnablePeerAccessExp_t pfnEnablePeerAccessExp; + ur_pfnUsmP2PDisablePeerAccessExp_t pfnDisablePeerAccessExp; + ur_pfnUsmP2PPeerAccessGetInfoExp_t pfnPeerAccessGetInfoExp; +} ur_usm_p2p_exp_dditable_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's UsmP2PExp table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL +urGetUsmP2PExpProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_usm_p2p_exp_dditable_t *pDdiTable ///< [in,out] pointer to table of DDI function pointers +); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for urGetUsmP2PExpProcAddrTable +typedef ur_result_t(UR_APICALL *ur_pfnGetUsmP2PExpProcAddrTable_t)( + ur_api_version_t, + ur_usm_p2p_exp_dditable_t *); + /////////////////////////////////////////////////////////////////////////////// /// @brief Function-pointer for urInit typedef ur_result_t(UR_APICALL *ur_pfnInit_t)( @@ -1981,6 +2032,7 @@ typedef struct ur_dditable_t { ur_usm_dditable_t USM; ur_usm_exp_dditable_t USMExp; ur_command_buffer_exp_dditable_t CommandBufferExp; + ur_usm_p2p_exp_dditable_t UsmP2PExp; ur_global_dditable_t Global; ur_virtual_mem_dditable_t VirtualMem; ur_device_dditable_t Device; diff --git a/scripts/core/EXP-USM-P2P.rst b/scripts/core/EXP-USM-P2P.rst new file mode 100644 index 0000000000..586dd46356 --- /dev/null +++ b/scripts/core/EXP-USM-P2P.rst @@ -0,0 +1,63 @@ +<% + OneApi=tags['$OneApi'] + x=tags['$x'] + X=x.upper() +%> + +.. _experimental-usm-p2p: + +================================================================================ +USM P2P +================================================================================ + +.. warning:: + + Experimental features: + + * May be replaced, updated, or removed at any time. + * Do not require maintaining API/ABI stability of their own additions over + time. + * Do not require conformance testing of their own additions. + + +Terminology +-------------------------------------------------------------------------------- +"Peer to peer" ("P2P") is used to indicate a "command" device either accessing +or copying the memory located on a separate "peer" device. + +Motivation +-------------------------------------------------------------------------------- +Several important projects that the SYCL programming model aims to support use +fine-grained peer to peer memory access controls. +Two such examples that SYCL supports are Pytorch and Gromacs. +This experimental extension to UR aims to provide a portable interface that can +call appropriate driver functions to query and control peer memory access +across the CUDA, HIP and L0 adapters. + +API +-------------------------------------------------------------------------------- + +Enums +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* ${x}_exp_peer_info_t + +Functions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* ${x}UsmP2PEnablePeerAccessExp +* ${x}UsmP2PDisablePeerAccessExp +* ${x}UsmP2PPeerAccessGetInfoExp + +Changelog +-------------------------------------------------------------------------------- + ++-----------+------------------------+ +| Revision | Changes | ++===========+========================+ +| 1.0 | Initial Draft | ++-----------+------------------------+ + +Contributors +-------------------------------------------------------------------------------- + +* JackAKirk `jack.kirk@codeplay.com `_ diff --git a/scripts/core/exp-usm-p2p.yml b/scripts/core/exp-usm-p2p.yml new file mode 100644 index 0000000000..21010792f4 --- /dev/null +++ b/scripts/core/exp-usm-p2p.yml @@ -0,0 +1,116 @@ +# +# Copyright (C) 2023 Intel Corporation +# +# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +# See LICENSE.TXT +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# See YaML.md for syntax definition +# +--- #-------------------------------------------------------------------------- +type: header +desc: "Intel $OneApi Unified Runtime Experimental APIs for USM P2P" +ordinal: "99" +--- #-------------------------------------------------------------------------- +type: enum +desc: "Supported peer info" +class: $xUsmP2P +name: $x_exp_peer_info_t +typed_etors: True +etors: + - name: UR_PEER_ACCESS_SUPPORTED + desc: "[uint32_t] 1 if P2P access is supported otherwise P2P access is not supported." + - name: UR_PEER_ATOMICS_SUPPORTED + desc: "[uint32_t] 1 if atomic operations are supported over the P2P link, otherwise such operations are not supported." +--- #-------------------------------------------------------------------------- +type: function +desc: "Enable access to peer device memory" +class: $xUsmP2P +name: EnablePeerAccessExp +ordinal: "0" +analogue: + - "**cuCtxEnablePeerAccess**" +details: + - "Enables the command device to access and write device memory allocations located on the peer device, provided that a P2P link between the two devices is available." + - "When Peer Access is successfully enabled, P2P memory accesses are guaranteed to be allowed on the peer device until $xUsmP2PDisablePeerAccessExp is called." + - "Note that the function operands may, but aren't guaranteed to, commute for a given adapter: the peer device is not guaranteed to have access to device memory allocations located on the command device." + - "It is not guaranteed that the commutation relations of the function arguments are identical for peer access and peer copies: For example, for a given adapter the peer device may be able to copy data from the command device, but not access and write the same data on the command device." + - "Consult the appropriate adapter driver documentation for details of adapter specific behavior and native error codes that may be returned." +params: + - type: $x_device_handle_t + name: commandDevice + desc: "[in] handle of the command device object" + - type: $x_device_handle_t + name: peerDevice + desc: "[in] handle of the peer device object" +returns: + - $X_RESULT_SUCCESS + - $X_RESULT_ERROR_ADAPTER_SPECIFIC +--- #-------------------------------------------------------------------------- +type: function +desc: "Disable access to peer device memory" +class: $xUsmP2P +name: DisablePeerAccessExp +ordinal: "0" +analogue: + - "**cuCtxDisablePeerAccess**" +details: + - "Disables the ability of the command device to access and write device memory allocations located on the peer device, provided that a P2P link between the two devices was enabled prior to the call." + - "Note that the function operands may, but aren't guaranteed to, commute for a given adapter. If, prior to the function call, the peer device had access to device memory allocations on the command device, it is not guaranteed to still have such access following the function return." + - "It is not guaranteed that the commutation relations of the function arguments are identical for peer access and peer copies: For example for a given adapter, if, prior to the call, the peer device had access to device memory allocations on the command device, the peer device may still, following the function call, be able to copy data from the command device, but not access and write the same data on the command device." + - "Consult the appropriate adapter driver documentation for details of adapter specific behavior and native error codes that may be returned." +params: + - type: $x_device_handle_t + name: commandDevice + desc: "[in] handle of the command device object" + - type: $x_device_handle_t + name: peerDevice + desc: "[in] handle of the peer device object" +returns: + - $X_RESULT_SUCCESS + - $X_RESULT_ERROR_ADAPTER_SPECIFIC +--- #-------------------------------------------------------------------------- +type: function +desc: "Disable access to peer device memory" +class: $xUsmP2P +name: PeerAccessGetInfoExp +ordinal: "0" +analogue: + - "**cuDeviceGetP2PAttribute**" +details: + - "Queries the peer access capabilities from the command device to the peer device according to the query `propName`." +params: + - type: $x_device_handle_t + name: commandDevice + desc: "[in] handle of the command device object" + - type: $x_device_handle_t + name: peerDevice + desc: "[in] handle of the peer device object" + - type: $x_exp_peer_info_t + name: propName + desc: "[in] type of the info to retrieve" + - type: "size_t" + name: propSize + desc: | + [in] the number of bytes pointed to by pPropValue. + - type: "void*" + name: pPropValue + desc: | + [out][optional][typename(propName, propSize)] array of bytes holding the info. + If propSize is not equal to or greater than the real number of bytes needed to return the info + then the $X_RESULT_ERROR_INVALID_SIZE error is returned and pPropValue is not used. + - type: "size_t*" + name: pPropSizeRet + desc: | + [out][optional] pointer to the actual size in bytes of the queried propName. +returns: + - $X_RESULT_ERROR_UNSUPPORTED_ENUMERATION: + - "If `propName` is not supported by the adapter." + - $X_RESULT_ERROR_INVALID_SIZE: + - "`propSize == 0 && pPropValue != NULL`" + - "If `propSize` is less than the real number of bytes needed to return the info." + - $X_RESULT_ERROR_INVALID_NULL_POINTER: + - "`propSize != 0 && pPropValue == NULL`" + - "`pPropValue == NULL && pPropSizeRet == NULL`" + - $X_RESULT_SUCCESS + - $X_RESULT_ERROR_ADAPTER_SPECIFIC diff --git a/scripts/core/registry.yml b/scripts/core/registry.yml index 42ef2a322a..0aa2703187 100644 --- a/scripts/core/registry.yml +++ b/scripts/core/registry.yml @@ -481,3 +481,12 @@ etors: - name: USM_RELEASE_EXP desc: Enumerator for $xUSMReleaseExp value: '164' +- name: USM_P2P_ENABLE_PEER_ACCESS_EXP + desc: Enumerator for $xUsmP2PEnablePeerAccessExp + value: '165' +- name: USM_P2P_DISABLE_PEER_ACCESS_EXP + desc: Enumerator for $xUsmP2PDisablePeerAccessExp + value: '166' +- name: USM_P2P_PEER_ACCESS_GET_INFO_EXP + desc: Enumerator for $xUsmP2PPeerAccessGetInfoExp + value: '167' diff --git a/source/adapters/null/ur_nullddi.cpp b/source/adapters/null/ur_nullddi.cpp index e7ba9338a5..a029e4ff1e 100644 --- a/source/adapters/null/ur_nullddi.cpp +++ b/source/adapters/null/ur_nullddi.cpp @@ -4615,6 +4615,87 @@ __urdlllocal ur_result_t UR_APICALL urUSMReleaseExp( return exceptionToResult(std::current_exception()); } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUsmP2PEnablePeerAccessExp +__urdlllocal ur_result_t UR_APICALL urUsmP2PEnablePeerAccessExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object + ) try { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnEnablePeerAccessExp = + d_context.urDdiTable.UsmP2PExp.pfnEnablePeerAccessExp; + if (nullptr != pfnEnablePeerAccessExp) { + result = pfnEnablePeerAccessExp(commandDevice, peerDevice); + } else { + // generic implementation + } + + return result; +} catch (...) { + return exceptionToResult(std::current_exception()); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUsmP2PDisablePeerAccessExp +__urdlllocal ur_result_t UR_APICALL urUsmP2PDisablePeerAccessExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object + ) try { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnDisablePeerAccessExp = + d_context.urDdiTable.UsmP2PExp.pfnDisablePeerAccessExp; + if (nullptr != pfnDisablePeerAccessExp) { + result = pfnDisablePeerAccessExp(commandDevice, peerDevice); + } else { + // generic implementation + } + + return result; +} catch (...) { + return exceptionToResult(std::current_exception()); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUsmP2PPeerAccessGetInfoExp +__urdlllocal ur_result_t UR_APICALL urUsmP2PPeerAccessGetInfoExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice, ///< [in] handle of the peer device object + ur_exp_peer_info_t propName, ///< [in] type of the info to retrieve + size_t propSize, ///< [in] the number of bytes pointed to by pPropValue. + void * + pPropValue, ///< [out][optional][typename(propName, propSize)] array of bytes holding + ///< the info. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return the info + ///< then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pPropValue is not used. + size_t * + pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of the queried propName. + ) try { + ur_result_t result = UR_RESULT_SUCCESS; + + // if the driver has created a custom function, then call it instead of using the generic path + auto pfnPeerAccessGetInfoExp = + d_context.urDdiTable.UsmP2PExp.pfnPeerAccessGetInfoExp; + if (nullptr != pfnPeerAccessGetInfoExp) { + result = pfnPeerAccessGetInfoExp(commandDevice, peerDevice, propName, + propSize, pPropValue, pPropSizeRet); + } else { + // generic implementation + } + + return result; +} catch (...) { + return exceptionToResult(std::current_exception()); +} + } // namespace driver #if defined(__cplusplus) @@ -5352,6 +5433,40 @@ UR_DLLEXPORT ur_result_t UR_APICALL urGetUSMExpProcAddrTable( return exceptionToResult(std::current_exception()); } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's UsmP2PExp table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL urGetUsmP2PExpProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_usm_p2p_exp_dditable_t + *pDdiTable ///< [in,out] pointer to table of DDI function pointers + ) try { + if (nullptr == pDdiTable) { + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + } + + if (driver::d_context.version < version) { + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + } + + ur_result_t result = UR_RESULT_SUCCESS; + + pDdiTable->pfnEnablePeerAccessExp = driver::urUsmP2PEnablePeerAccessExp; + + pDdiTable->pfnDisablePeerAccessExp = driver::urUsmP2PDisablePeerAccessExp; + + pDdiTable->pfnPeerAccessGetInfoExp = driver::urUsmP2PPeerAccessGetInfoExp; + + return result; +} catch (...) { + return exceptionToResult(std::current_exception()); +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Exported function for filling application's VirtualMem table /// with current process' addresses diff --git a/source/common/ur_params.hpp b/source/common/ur_params.hpp index a4877f8ac6..27ecf34a62 100644 --- a/source/common/ur_params.hpp +++ b/source/common/ur_params.hpp @@ -175,6 +175,10 @@ template <> inline void serializeFlag(std::ostream &os, uint32_t flag); +template <> +inline void serializeTagged(std::ostream &os, const void *ptr, + ur_exp_peer_info_t value, size_t size); + } // namespace ur_params inline std::ostream &operator<<(std::ostream &os, enum ur_result_t value); @@ -371,6 +375,8 @@ operator<<(std::ostream &os, const struct ur_exp_sampler_mip_properties_t params); inline std::ostream & operator<<(std::ostream &os, const struct ur_exp_command_buffer_desc_t params); +inline std::ostream &operator<<(std::ostream &os, + enum ur_exp_peer_info_t value); inline std::ostream &operator<<(std::ostream &os, enum ur_result_t value) { switch (value) { @@ -9054,6 +9060,18 @@ inline std::ostream &operator<<(std::ostream &os, enum ur_function_t value) { case UR_FUNCTION_USM_RELEASE_EXP: os << "UR_FUNCTION_USM_RELEASE_EXP"; break; + + case UR_FUNCTION_USM_P2P_ENABLE_PEER_ACCESS_EXP: + os << "UR_FUNCTION_USM_P2P_ENABLE_PEER_ACCESS_EXP"; + break; + + case UR_FUNCTION_USM_P2P_DISABLE_PEER_ACCESS_EXP: + os << "UR_FUNCTION_USM_P2P_DISABLE_PEER_ACCESS_EXP"; + break; + + case UR_FUNCTION_USM_P2P_PEER_ACCESS_GET_INFO_EXP: + os << "UR_FUNCTION_USM_P2P_PEER_ACCESS_GET_INFO_EXP"; + break; default: os << "unknown enumerator"; break; @@ -9290,6 +9308,67 @@ operator<<(std::ostream &os, const struct ur_exp_command_buffer_desc_t params) { os << "}"; return os; } +inline std::ostream &operator<<(std::ostream &os, + enum ur_exp_peer_info_t value) { + switch (value) { + + case UR_EXP_PEER_INFO_UR_PEER_ACCESS_SUPPORTED: + os << "UR_EXP_PEER_INFO_UR_PEER_ACCESS_SUPPORTED"; + break; + + case UR_EXP_PEER_INFO_UR_PEER_ATOMICS_SUPPORTED: + os << "UR_EXP_PEER_INFO_UR_PEER_ATOMICS_SUPPORTED"; + break; + default: + os << "unknown enumerator"; + break; + } + return os; +} +namespace ur_params { +template <> +inline void serializeTagged(std::ostream &os, const void *ptr, + ur_exp_peer_info_t value, size_t size) { + if (ptr == NULL) { + serializePtr(os, ptr); + return; + } + + switch (value) { + + case UR_EXP_PEER_INFO_UR_PEER_ACCESS_SUPPORTED: { + const uint32_t *tptr = (const uint32_t *)ptr; + if (sizeof(uint32_t) > size) { + os << "invalid size (is: " << size + << ", expected: >=" << sizeof(uint32_t) << ")"; + return; + } + os << (void *)(tptr) << " ("; + + os << *tptr; + + os << ")"; + } break; + + case UR_EXP_PEER_INFO_UR_PEER_ATOMICS_SUPPORTED: { + const uint32_t *tptr = (const uint32_t *)ptr; + if (sizeof(uint32_t) > size) { + os << "invalid size (is: " << size + << ", expected: >=" << sizeof(uint32_t) << ")"; + return; + } + os << (void *)(tptr) << " ("; + + os << *tptr; + + os << ")"; + } break; + default: + os << "unknown enumerator"; + break; + } +} +} // namespace ur_params inline std::ostream &operator<<(std::ostream &os, const struct ur_init_params_t *params) { @@ -13622,6 +13701,74 @@ operator<<(std::ostream &os, const struct ur_usm_release_exp_params_t *params) { return os; } +inline std::ostream & +operator<<(std::ostream &os, + const struct ur_usm_p2p_enable_peer_access_exp_params_t *params) { + + os << ".commandDevice = "; + + ur_params::serializePtr(os, *(params->pcommandDevice)); + + os << ", "; + os << ".peerDevice = "; + + ur_params::serializePtr(os, *(params->ppeerDevice)); + + return os; +} + +inline std::ostream & +operator<<(std::ostream &os, + const struct ur_usm_p2p_disable_peer_access_exp_params_t *params) { + + os << ".commandDevice = "; + + ur_params::serializePtr(os, *(params->pcommandDevice)); + + os << ", "; + os << ".peerDevice = "; + + ur_params::serializePtr(os, *(params->ppeerDevice)); + + return os; +} + +inline std::ostream & +operator<<(std::ostream &os, + const struct ur_usm_p2p_peer_access_get_info_exp_params_t *params) { + + os << ".commandDevice = "; + + ur_params::serializePtr(os, *(params->pcommandDevice)); + + os << ", "; + os << ".peerDevice = "; + + ur_params::serializePtr(os, *(params->ppeerDevice)); + + os << ", "; + os << ".propName = "; + + os << *(params->ppropName); + + os << ", "; + os << ".propSize = "; + + os << *(params->ppropSize); + + os << ", "; + os << ".pPropValue = "; + ur_params::serializeTagged(os, *(params->ppPropValue), *(params->ppropName), + *(params->ppropSize)); + + os << ", "; + os << ".pPropSizeRet = "; + + ur_params::serializePtr(os, *(params->ppPropSizeRet)); + + return os; +} + inline std::ostream & operator<<(std::ostream &os, const struct ur_virtual_mem_granularity_get_info_params_t *params) { @@ -14538,6 +14685,17 @@ inline int serializeFunctionParams(std::ostream &os, uint32_t function, case UR_FUNCTION_USM_RELEASE_EXP: { os << (const struct ur_usm_release_exp_params_t *)params; } break; + case UR_FUNCTION_USM_P2P_ENABLE_PEER_ACCESS_EXP: { + os << (const struct ur_usm_p2p_enable_peer_access_exp_params_t *)params; + } break; + case UR_FUNCTION_USM_P2P_DISABLE_PEER_ACCESS_EXP: { + os << (const struct ur_usm_p2p_disable_peer_access_exp_params_t *) + params; + } break; + case UR_FUNCTION_USM_P2P_PEER_ACCESS_GET_INFO_EXP: { + os << (const struct ur_usm_p2p_peer_access_get_info_exp_params_t *) + params; + } break; case UR_FUNCTION_VIRTUAL_MEM_GRANULARITY_GET_INFO: { os << (const struct ur_virtual_mem_granularity_get_info_params_t *) params; diff --git a/source/loader/layers/tracing/ur_trcddi.cpp b/source/loader/layers/tracing/ur_trcddi.cpp index 935938b37e..a7d43afe5e 100644 --- a/source/loader/layers/tracing/ur_trcddi.cpp +++ b/source/loader/layers/tracing/ur_trcddi.cpp @@ -5290,6 +5290,107 @@ __urdlllocal ur_result_t UR_APICALL urUSMReleaseExp( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUsmP2PEnablePeerAccessExp +__urdlllocal ur_result_t UR_APICALL urUsmP2PEnablePeerAccessExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object +) { + auto pfnEnablePeerAccessExp = + context.urDdiTable.UsmP2PExp.pfnEnablePeerAccessExp; + + if (nullptr == pfnEnablePeerAccessExp) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + ur_usm_p2p_enable_peer_access_exp_params_t params = {&commandDevice, + &peerDevice}; + uint64_t instance = + context.notify_begin(UR_FUNCTION_USM_P2P_ENABLE_PEER_ACCESS_EXP, + "urUsmP2PEnablePeerAccessExp", ¶ms); + + ur_result_t result = pfnEnablePeerAccessExp(commandDevice, peerDevice); + + context.notify_end(UR_FUNCTION_USM_P2P_ENABLE_PEER_ACCESS_EXP, + "urUsmP2PEnablePeerAccessExp", ¶ms, &result, + instance); + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUsmP2PDisablePeerAccessExp +__urdlllocal ur_result_t UR_APICALL urUsmP2PDisablePeerAccessExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object +) { + auto pfnDisablePeerAccessExp = + context.urDdiTable.UsmP2PExp.pfnDisablePeerAccessExp; + + if (nullptr == pfnDisablePeerAccessExp) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + ur_usm_p2p_disable_peer_access_exp_params_t params = {&commandDevice, + &peerDevice}; + uint64_t instance = + context.notify_begin(UR_FUNCTION_USM_P2P_DISABLE_PEER_ACCESS_EXP, + "urUsmP2PDisablePeerAccessExp", ¶ms); + + ur_result_t result = pfnDisablePeerAccessExp(commandDevice, peerDevice); + + context.notify_end(UR_FUNCTION_USM_P2P_DISABLE_PEER_ACCESS_EXP, + "urUsmP2PDisablePeerAccessExp", ¶ms, &result, + instance); + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUsmP2PPeerAccessGetInfoExp +__urdlllocal ur_result_t UR_APICALL urUsmP2PPeerAccessGetInfoExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice, ///< [in] handle of the peer device object + ur_exp_peer_info_t propName, ///< [in] type of the info to retrieve + size_t propSize, ///< [in] the number of bytes pointed to by pPropValue. + void * + pPropValue, ///< [out][optional][typename(propName, propSize)] array of bytes holding + ///< the info. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return the info + ///< then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pPropValue is not used. + size_t * + pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of the queried propName. +) { + auto pfnPeerAccessGetInfoExp = + context.urDdiTable.UsmP2PExp.pfnPeerAccessGetInfoExp; + + if (nullptr == pfnPeerAccessGetInfoExp) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + ur_usm_p2p_peer_access_get_info_exp_params_t params = { + &commandDevice, &peerDevice, &propName, + &propSize, &pPropValue, &pPropSizeRet}; + uint64_t instance = + context.notify_begin(UR_FUNCTION_USM_P2P_PEER_ACCESS_GET_INFO_EXP, + "urUsmP2PPeerAccessGetInfoExp", ¶ms); + + ur_result_t result = + pfnPeerAccessGetInfoExp(commandDevice, peerDevice, propName, propSize, + pPropValue, pPropSizeRet); + + context.notify_end(UR_FUNCTION_USM_P2P_PEER_ACCESS_GET_INFO_EXP, + "urUsmP2PPeerAccessGetInfoExp", ¶ms, &result, + instance); + + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Exported function for filling application's Global table /// with current process' addresses @@ -6220,6 +6321,48 @@ __urdlllocal ur_result_t UR_APICALL urGetUSMExpProcAddrTable( return result; } /////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's UsmP2PExp table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +__urdlllocal ur_result_t UR_APICALL urGetUsmP2PExpProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_usm_p2p_exp_dditable_t + *pDdiTable ///< [in,out] pointer to table of DDI function pointers +) { + auto &dditable = ur_tracing_layer::context.urDdiTable.UsmP2PExp; + + if (nullptr == pDdiTable) { + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + } + + if (UR_MAJOR_VERSION(ur_tracing_layer::context.version) != + UR_MAJOR_VERSION(version) || + UR_MINOR_VERSION(ur_tracing_layer::context.version) > + UR_MINOR_VERSION(version)) { + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + } + + ur_result_t result = UR_RESULT_SUCCESS; + + dditable.pfnEnablePeerAccessExp = pDdiTable->pfnEnablePeerAccessExp; + pDdiTable->pfnEnablePeerAccessExp = + ur_tracing_layer::urUsmP2PEnablePeerAccessExp; + + dditable.pfnDisablePeerAccessExp = pDdiTable->pfnDisablePeerAccessExp; + pDdiTable->pfnDisablePeerAccessExp = + ur_tracing_layer::urUsmP2PDisablePeerAccessExp; + + dditable.pfnPeerAccessGetInfoExp = pDdiTable->pfnPeerAccessGetInfoExp; + pDdiTable->pfnPeerAccessGetInfoExp = + ur_tracing_layer::urUsmP2PPeerAccessGetInfoExp; + + return result; +} +/////////////////////////////////////////////////////////////////////////////// /// @brief Exported function for filling application's VirtualMem table /// with current process' addresses /// @@ -6409,6 +6552,11 @@ ur_result_t context_t::init(ur_dditable_t *dditable) { UR_API_VERSION_CURRENT, &dditable->USMExp); } + if (UR_RESULT_SUCCESS == result) { + result = ur_tracing_layer::urGetUsmP2PExpProcAddrTable( + UR_API_VERSION_CURRENT, &dditable->UsmP2PExp); + } + if (UR_RESULT_SUCCESS == result) { result = ur_tracing_layer::urGetVirtualMemProcAddrTable( UR_API_VERSION_CURRENT, &dditable->VirtualMem); diff --git a/source/loader/layers/validation/ur_valddi.cpp b/source/loader/layers/validation/ur_valddi.cpp index 593e5418b2..6084954b58 100644 --- a/source/loader/layers/validation/ur_valddi.cpp +++ b/source/loader/layers/validation/ur_valddi.cpp @@ -6568,6 +6568,122 @@ __urdlllocal ur_result_t UR_APICALL urUSMReleaseExp( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUsmP2PEnablePeerAccessExp +__urdlllocal ur_result_t UR_APICALL urUsmP2PEnablePeerAccessExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object +) { + auto pfnEnablePeerAccessExp = + context.urDdiTable.UsmP2PExp.pfnEnablePeerAccessExp; + + if (nullptr == pfnEnablePeerAccessExp) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + if (context.enableParameterValidation) { + if (NULL == commandDevice) { + return UR_RESULT_ERROR_INVALID_NULL_HANDLE; + } + + if (NULL == peerDevice) { + return UR_RESULT_ERROR_INVALID_NULL_HANDLE; + } + } + + ur_result_t result = pfnEnablePeerAccessExp(commandDevice, peerDevice); + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUsmP2PDisablePeerAccessExp +__urdlllocal ur_result_t UR_APICALL urUsmP2PDisablePeerAccessExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object +) { + auto pfnDisablePeerAccessExp = + context.urDdiTable.UsmP2PExp.pfnDisablePeerAccessExp; + + if (nullptr == pfnDisablePeerAccessExp) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + if (context.enableParameterValidation) { + if (NULL == commandDevice) { + return UR_RESULT_ERROR_INVALID_NULL_HANDLE; + } + + if (NULL == peerDevice) { + return UR_RESULT_ERROR_INVALID_NULL_HANDLE; + } + } + + ur_result_t result = pfnDisablePeerAccessExp(commandDevice, peerDevice); + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUsmP2PPeerAccessGetInfoExp +__urdlllocal ur_result_t UR_APICALL urUsmP2PPeerAccessGetInfoExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice, ///< [in] handle of the peer device object + ur_exp_peer_info_t propName, ///< [in] type of the info to retrieve + size_t propSize, ///< [in] the number of bytes pointed to by pPropValue. + void * + pPropValue, ///< [out][optional][typename(propName, propSize)] array of bytes holding + ///< the info. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return the info + ///< then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pPropValue is not used. + size_t * + pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of the queried propName. +) { + auto pfnPeerAccessGetInfoExp = + context.urDdiTable.UsmP2PExp.pfnPeerAccessGetInfoExp; + + if (nullptr == pfnPeerAccessGetInfoExp) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + } + + if (context.enableParameterValidation) { + if (NULL == commandDevice) { + return UR_RESULT_ERROR_INVALID_NULL_HANDLE; + } + + if (NULL == peerDevice) { + return UR_RESULT_ERROR_INVALID_NULL_HANDLE; + } + + if (propSize != 0 && pPropValue == NULL) { + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + } + + if (pPropValue == NULL && pPropSizeRet == NULL) { + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + } + + if (UR_EXP_PEER_INFO_UR_PEER_ATOMICS_SUPPORTED < propName) { + return UR_RESULT_ERROR_INVALID_ENUMERATION; + } + + if (propSize == 0 && pPropValue != NULL) { + return UR_RESULT_ERROR_INVALID_SIZE; + } + } + + ur_result_t result = + pfnPeerAccessGetInfoExp(commandDevice, peerDevice, propName, propSize, + pPropValue, pPropSizeRet); + + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Exported function for filling application's Global table /// with current process' addresses @@ -7521,6 +7637,49 @@ UR_DLLEXPORT ur_result_t UR_APICALL urGetUSMExpProcAddrTable( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's UsmP2PExp table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL urGetUsmP2PExpProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_usm_p2p_exp_dditable_t + *pDdiTable ///< [in,out] pointer to table of DDI function pointers +) { + auto &dditable = ur_validation_layer::context.urDdiTable.UsmP2PExp; + + if (nullptr == pDdiTable) { + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + } + + if (UR_MAJOR_VERSION(ur_validation_layer::context.version) != + UR_MAJOR_VERSION(version) || + UR_MINOR_VERSION(ur_validation_layer::context.version) > + UR_MINOR_VERSION(version)) { + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + } + + ur_result_t result = UR_RESULT_SUCCESS; + + dditable.pfnEnablePeerAccessExp = pDdiTable->pfnEnablePeerAccessExp; + pDdiTable->pfnEnablePeerAccessExp = + ur_validation_layer::urUsmP2PEnablePeerAccessExp; + + dditable.pfnDisablePeerAccessExp = pDdiTable->pfnDisablePeerAccessExp; + pDdiTable->pfnDisablePeerAccessExp = + ur_validation_layer::urUsmP2PDisablePeerAccessExp; + + dditable.pfnPeerAccessGetInfoExp = pDdiTable->pfnPeerAccessGetInfoExp; + pDdiTable->pfnPeerAccessGetInfoExp = + ur_validation_layer::urUsmP2PPeerAccessGetInfoExp; + + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Exported function for filling application's VirtualMem table /// with current process' addresses @@ -7713,6 +7872,11 @@ ur_result_t context_t::init(ur_dditable_t *dditable) { UR_API_VERSION_CURRENT, &dditable->USMExp); } + if (UR_RESULT_SUCCESS == result) { + result = ur_validation_layer::urGetUsmP2PExpProcAddrTable( + UR_API_VERSION_CURRENT, &dditable->UsmP2PExp); + } + if (UR_RESULT_SUCCESS == result) { result = ur_validation_layer::urGetVirtualMemProcAddrTable( UR_API_VERSION_CURRENT, &dditable->VirtualMem); diff --git a/source/loader/ur_ldrddi.cpp b/source/loader/ur_ldrddi.cpp index 8a2a7f4f85..144d812382 100644 --- a/source/loader/ur_ldrddi.cpp +++ b/source/loader/ur_ldrddi.cpp @@ -6419,6 +6419,110 @@ __urdlllocal ur_result_t UR_APICALL urUSMReleaseExp( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUsmP2PEnablePeerAccessExp +__urdlllocal ur_result_t UR_APICALL urUsmP2PEnablePeerAccessExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object +) { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = + reinterpret_cast(commandDevice)->dditable; + auto pfnEnablePeerAccessExp = dditable->ur.UsmP2PExp.pfnEnablePeerAccessExp; + if (nullptr == pfnEnablePeerAccessExp) { + return UR_RESULT_ERROR_UNINITIALIZED; + } + + // convert loader handle to platform handle + commandDevice = + reinterpret_cast(commandDevice)->handle; + + // convert loader handle to platform handle + peerDevice = reinterpret_cast(peerDevice)->handle; + + // forward to device-platform + result = pfnEnablePeerAccessExp(commandDevice, peerDevice); + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUsmP2PDisablePeerAccessExp +__urdlllocal ur_result_t UR_APICALL urUsmP2PDisablePeerAccessExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object +) { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = + reinterpret_cast(commandDevice)->dditable; + auto pfnDisablePeerAccessExp = + dditable->ur.UsmP2PExp.pfnDisablePeerAccessExp; + if (nullptr == pfnDisablePeerAccessExp) { + return UR_RESULT_ERROR_UNINITIALIZED; + } + + // convert loader handle to platform handle + commandDevice = + reinterpret_cast(commandDevice)->handle; + + // convert loader handle to platform handle + peerDevice = reinterpret_cast(peerDevice)->handle; + + // forward to device-platform + result = pfnDisablePeerAccessExp(commandDevice, peerDevice); + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUsmP2PPeerAccessGetInfoExp +__urdlllocal ur_result_t UR_APICALL urUsmP2PPeerAccessGetInfoExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice, ///< [in] handle of the peer device object + ur_exp_peer_info_t propName, ///< [in] type of the info to retrieve + size_t propSize, ///< [in] the number of bytes pointed to by pPropValue. + void * + pPropValue, ///< [out][optional][typename(propName, propSize)] array of bytes holding + ///< the info. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return the info + ///< then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pPropValue is not used. + size_t * + pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of the queried propName. +) { + ur_result_t result = UR_RESULT_SUCCESS; + + // extract platform's function pointer table + auto dditable = + reinterpret_cast(commandDevice)->dditable; + auto pfnPeerAccessGetInfoExp = + dditable->ur.UsmP2PExp.pfnPeerAccessGetInfoExp; + if (nullptr == pfnPeerAccessGetInfoExp) { + return UR_RESULT_ERROR_UNINITIALIZED; + } + + // convert loader handle to platform handle + commandDevice = + reinterpret_cast(commandDevice)->handle; + + // convert loader handle to platform handle + peerDevice = reinterpret_cast(peerDevice)->handle; + + // forward to device-platform + result = pfnPeerAccessGetInfoExp(commandDevice, peerDevice, propName, + propSize, pPropValue, pPropSizeRet); + + return result; +} + } // namespace ur_loader #if defined(__cplusplus) @@ -7395,6 +7499,65 @@ UR_DLLEXPORT ur_result_t UR_APICALL urGetUSMExpProcAddrTable( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Exported function for filling application's UsmP2PExp table +/// with current process' addresses +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// - ::UR_RESULT_ERROR_UNSUPPORTED_VERSION +UR_DLLEXPORT ur_result_t UR_APICALL urGetUsmP2PExpProcAddrTable( + ur_api_version_t version, ///< [in] API version requested + ur_usm_p2p_exp_dditable_t + *pDdiTable ///< [in,out] pointer to table of DDI function pointers +) { + if (nullptr == pDdiTable) { + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + } + + if (ur_loader::context->version < version) { + return UR_RESULT_ERROR_UNSUPPORTED_VERSION; + } + + ur_result_t result = UR_RESULT_SUCCESS; + + // Load the device-platform DDI tables + for (auto &platform : ur_loader::context->platforms) { + if (platform.initStatus != UR_RESULT_SUCCESS) { + continue; + } + auto getTable = reinterpret_cast( + ur_loader::LibLoader::getFunctionPtr( + platform.handle.get(), "urGetUsmP2PExpProcAddrTable")); + if (!getTable) { + continue; + } + platform.initStatus = + getTable(version, &platform.dditable.ur.UsmP2PExp); + } + + if (UR_RESULT_SUCCESS == result) { + if (ur_loader::context->platforms.size() != 1 || + ur_loader::context->forceIntercept) { + // return pointers to loader's DDIs + pDdiTable->pfnEnablePeerAccessExp = + ur_loader::urUsmP2PEnablePeerAccessExp; + pDdiTable->pfnDisablePeerAccessExp = + ur_loader::urUsmP2PDisablePeerAccessExp; + pDdiTable->pfnPeerAccessGetInfoExp = + ur_loader::urUsmP2PPeerAccessGetInfoExp; + } else { + // return pointers directly to platform's DDIs + *pDdiTable = + ur_loader::context->platforms.front().dditable.ur.UsmP2PExp; + } + } + + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Exported function for filling application's VirtualMem table /// with current process' addresses diff --git a/source/loader/ur_libapi.cpp b/source/loader/ur_libapi.cpp index efbe972fba..664e7e3d1a 100644 --- a/source/loader/ur_libapi.cpp +++ b/source/loader/ur_libapi.cpp @@ -6945,4 +6945,163 @@ ur_result_t UR_APICALL urUSMReleaseExp( return exceptionToResult(std::current_exception()); } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enable access to peer device memory +/// +/// @details +/// - Enables the command device to access and write device memory +/// allocations located on the peer device, provided that a P2P link +/// between the two devices is available. +/// - When Peer Access is successfully enabled, P2P memory accesses are +/// guaranteed to be allowed on the peer device until +/// ::urUsmP2PDisablePeerAccessExp is called. +/// - Note that the function operands may, but aren't guaranteed to, commute +/// for a given adapter: the peer device is not guaranteed to have access +/// to device memory allocations located on the command device. +/// - It is not guaranteed that the commutation relations of the function +/// arguments are identical for peer access and peer copies: For example, +/// for a given adapter the peer device may be able to copy data from the +/// command device, but not access and write the same data on the command +/// device. +/// - Consult the appropriate adapter driver documentation for details of +/// adapter specific behavior and native error codes that may be returned. +/// +/// @remarks +/// _Analogues_ +/// - **cuCtxEnablePeerAccess** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == commandDevice` +/// + `NULL == peerDevice` +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +ur_result_t UR_APICALL urUsmP2PEnablePeerAccessExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object + ) try { + auto pfnEnablePeerAccessExp = + ur_lib::context->urDdiTable.UsmP2PExp.pfnEnablePeerAccessExp; + if (nullptr == pfnEnablePeerAccessExp) { + return UR_RESULT_ERROR_UNINITIALIZED; + } + + return pfnEnablePeerAccessExp(commandDevice, peerDevice); +} catch (...) { + return exceptionToResult(std::current_exception()); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Disable access to peer device memory +/// +/// @details +/// - Disables the ability of the command device to access and write device +/// memory allocations located on the peer device, provided that a P2P +/// link between the two devices was enabled prior to the call. +/// - Note that the function operands may, but aren't guaranteed to, commute +/// for a given adapter. If, prior to the function call, the peer device +/// had access to device memory allocations on the command device, it is +/// not guaranteed to still have such access following the function +/// return. +/// - It is not guaranteed that the commutation relations of the function +/// arguments are identical for peer access and peer copies: For example +/// for a given adapter, if, prior to the call, the peer device had access +/// to device memory allocations on the command device, the peer device +/// may still, following the function call, be able to copy data from the +/// command device, but not access and write the same data on the command +/// device. +/// - Consult the appropriate adapter driver documentation for details of +/// adapter specific behavior and native error codes that may be returned. +/// +/// @remarks +/// _Analogues_ +/// - **cuCtxDisablePeerAccess** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == commandDevice` +/// + `NULL == peerDevice` +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +ur_result_t UR_APICALL urUsmP2PDisablePeerAccessExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object + ) try { + auto pfnDisablePeerAccessExp = + ur_lib::context->urDdiTable.UsmP2PExp.pfnDisablePeerAccessExp; + if (nullptr == pfnDisablePeerAccessExp) { + return UR_RESULT_ERROR_UNINITIALIZED; + } + + return pfnDisablePeerAccessExp(commandDevice, peerDevice); +} catch (...) { + return exceptionToResult(std::current_exception()); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Disable access to peer device memory +/// +/// @details +/// - Queries the peer access capabilities from the command device to the +/// peer device according to the query `propName`. +/// +/// @remarks +/// _Analogues_ +/// - **cuDeviceGetP2PAttribute** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == commandDevice` +/// + `NULL == peerDevice` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_EXP_PEER_INFO_UR_PEER_ATOMICS_SUPPORTED < propName` +/// - ::UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION +/// + If `propName` is not supported by the adapter. +/// - ::UR_RESULT_ERROR_INVALID_SIZE +/// + `propSize == 0 && pPropValue != NULL` +/// + If `propSize` is less than the real number of bytes needed to return the info. +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `propSize != 0 && pPropValue == NULL` +/// + `pPropValue == NULL && pPropSizeRet == NULL` +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +ur_result_t UR_APICALL urUsmP2PPeerAccessGetInfoExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice, ///< [in] handle of the peer device object + ur_exp_peer_info_t propName, ///< [in] type of the info to retrieve + size_t propSize, ///< [in] the number of bytes pointed to by pPropValue. + void * + pPropValue, ///< [out][optional][typename(propName, propSize)] array of bytes holding + ///< the info. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return the info + ///< then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pPropValue is not used. + size_t * + pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of the queried propName. + ) try { + auto pfnPeerAccessGetInfoExp = + ur_lib::context->urDdiTable.UsmP2PExp.pfnPeerAccessGetInfoExp; + if (nullptr == pfnPeerAccessGetInfoExp) { + return UR_RESULT_ERROR_UNINITIALIZED; + } + + return pfnPeerAccessGetInfoExp(commandDevice, peerDevice, propName, + propSize, pPropValue, pPropSizeRet); +} catch (...) { + return exceptionToResult(std::current_exception()); +} + } // extern "C" diff --git a/source/loader/ur_libddi.cpp b/source/loader/ur_libddi.cpp index 1c8ccd5593..1328a2b071 100644 --- a/source/loader/ur_libddi.cpp +++ b/source/loader/ur_libddi.cpp @@ -93,6 +93,11 @@ __urdlllocal ur_result_t context_t::urInit() { &urDdiTable.USMExp); } + if (UR_RESULT_SUCCESS == result) { + result = urGetUsmP2PExpProcAddrTable(UR_API_VERSION_CURRENT, + &urDdiTable.UsmP2PExp); + } + if (UR_RESULT_SUCCESS == result) { result = urGetVirtualMemProcAddrTable(UR_API_VERSION_CURRENT, &urDdiTable.VirtualMem); diff --git a/source/ur_api.cpp b/source/ur_api.cpp index 4c72aee9c1..b44a830b3c 100644 --- a/source/ur_api.cpp +++ b/source/ur_api.cpp @@ -5825,3 +5825,140 @@ ur_result_t UR_APICALL urUSMReleaseExp( ur_result_t result = UR_RESULT_SUCCESS; return result; } + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Enable access to peer device memory +/// +/// @details +/// - Enables the command device to access and write device memory +/// allocations located on the peer device, provided that a P2P link +/// between the two devices is available. +/// - When Peer Access is successfully enabled, P2P memory accesses are +/// guaranteed to be allowed on the peer device until +/// ::urUsmP2PDisablePeerAccessExp is called. +/// - Note that the function operands may, but aren't guaranteed to, commute +/// for a given adapter: the peer device is not guaranteed to have access +/// to device memory allocations located on the command device. +/// - It is not guaranteed that the commutation relations of the function +/// arguments are identical for peer access and peer copies: For example, +/// for a given adapter the peer device may be able to copy data from the +/// command device, but not access and write the same data on the command +/// device. +/// - Consult the appropriate adapter driver documentation for details of +/// adapter specific behavior and native error codes that may be returned. +/// +/// @remarks +/// _Analogues_ +/// - **cuCtxEnablePeerAccess** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == commandDevice` +/// + `NULL == peerDevice` +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +ur_result_t UR_APICALL urUsmP2PEnablePeerAccessExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object +) { + ur_result_t result = UR_RESULT_SUCCESS; + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Disable access to peer device memory +/// +/// @details +/// - Disables the ability of the command device to access and write device +/// memory allocations located on the peer device, provided that a P2P +/// link between the two devices was enabled prior to the call. +/// - Note that the function operands may, but aren't guaranteed to, commute +/// for a given adapter. If, prior to the function call, the peer device +/// had access to device memory allocations on the command device, it is +/// not guaranteed to still have such access following the function +/// return. +/// - It is not guaranteed that the commutation relations of the function +/// arguments are identical for peer access and peer copies: For example +/// for a given adapter, if, prior to the call, the peer device had access +/// to device memory allocations on the command device, the peer device +/// may still, following the function call, be able to copy data from the +/// command device, but not access and write the same data on the command +/// device. +/// - Consult the appropriate adapter driver documentation for details of +/// adapter specific behavior and native error codes that may be returned. +/// +/// @remarks +/// _Analogues_ +/// - **cuCtxDisablePeerAccess** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == commandDevice` +/// + `NULL == peerDevice` +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +ur_result_t UR_APICALL urUsmP2PDisablePeerAccessExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice ///< [in] handle of the peer device object +) { + ur_result_t result = UR_RESULT_SUCCESS; + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Disable access to peer device memory +/// +/// @details +/// - Queries the peer access capabilities from the command device to the +/// peer device according to the query `propName`. +/// +/// @remarks +/// _Analogues_ +/// - **cuDeviceGetP2PAttribute** +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == commandDevice` +/// + `NULL == peerDevice` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `::UR_EXP_PEER_INFO_UR_PEER_ATOMICS_SUPPORTED < propName` +/// - ::UR_RESULT_ERROR_UNSUPPORTED_ENUMERATION +/// + If `propName` is not supported by the adapter. +/// - ::UR_RESULT_ERROR_INVALID_SIZE +/// + `propSize == 0 && pPropValue != NULL` +/// + If `propSize` is less than the real number of bytes needed to return the info. +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `propSize != 0 && pPropValue == NULL` +/// + `pPropValue == NULL && pPropSizeRet == NULL` +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +ur_result_t UR_APICALL urUsmP2PPeerAccessGetInfoExp( + ur_device_handle_t + commandDevice, ///< [in] handle of the command device object + ur_device_handle_t peerDevice, ///< [in] handle of the peer device object + ur_exp_peer_info_t propName, ///< [in] type of the info to retrieve + size_t propSize, ///< [in] the number of bytes pointed to by pPropValue. + void * + pPropValue, ///< [out][optional][typename(propName, propSize)] array of bytes holding + ///< the info. + ///< If propSize is not equal to or greater than the real number of bytes + ///< needed to return the info + ///< then the ::UR_RESULT_ERROR_INVALID_SIZE error is returned and + ///< pPropValue is not used. + size_t * + pPropSizeRet ///< [out][optional] pointer to the actual size in bytes of the queried propName. +) { + ur_result_t result = UR_RESULT_SUCCESS; + return result; +}