Skip to content

Commit 7082efa

Browse files
authored
[SYCL][Bindless] Device 'image_mem_handle' to 'image_mem_handle' Sub-Region Copy (#15579)
Add support for device 'image_mem_handle' to 'image_mem_handle' sub-region copies and implement tests
1 parent cfa4af5 commit 7082efa

File tree

10 files changed

+797
-3
lines changed

10 files changed

+797
-3
lines changed

sycl/doc/extensions/experimental/sycl_ext_oneapi_bindless_images.asciidoc

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,16 @@ public:
813813
const ext::oneapi::experimental::image_mem_handle Src,
814814
ext::oneapi::experimental::image_mem_handle Dest,
815815
const ext::oneapi::experimental::image_descriptor &ImageDesc);
816+
817+
// Device to device copy with offsets and extent
818+
void ext_oneapi_copy(
819+
const ext::oneapi::experimental::image_mem_handle Src,
820+
sycl::range<3> SrcOffset,
821+
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
822+
ext::oneapi::experimental::image_mem_handle Dest,
823+
sycl::range<3> DestOffset,
824+
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
825+
sycl::range<3> CopyExtent)
816826
};
817827

818828
class queue {
@@ -954,6 +964,34 @@ public:
954964
ext::oneapi::experimental::image_mem_handle Dest,
955965
const ext::oneapi::experimental::image_descriptor &ImageDesc,
956966
const std::vector<event> &DepEvents);
967+
968+
// Device to device copy with offsets and extent
969+
void ext_oneapi_copy(
970+
const ext::oneapi::experimental::image_mem_handle Src,
971+
sycl::range<3> SrcOffset,
972+
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
973+
ext::oneapi::experimental::image_mem_handle Dest,
974+
sycl::range<3> DestOffset,
975+
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
976+
sycl::range<3> CopyExtent)
977+
void ext_oneapi_copy(
978+
const ext::oneapi::experimental::image_mem_handle Src,
979+
sycl::range<3> SrcOffset,
980+
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
981+
ext::oneapi::experimental::image_mem_handle Dest,
982+
sycl::range<3> DestOffset,
983+
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
984+
sycl::range<3> CopyExtent
985+
event DepEvent)
986+
void ext_oneapi_copy(
987+
const ext::oneapi::experimental::image_mem_handle Src,
988+
sycl::range<3> SrcOffset,
989+
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
990+
ext::oneapi::experimental::image_mem_handle Dest,
991+
sycl::range<3> DestOffset,
992+
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
993+
sycl::range<3> CopyExtent
994+
const std::vector<event> &DepEvents)
957995
};
958996
}
959997
```
@@ -2903,4 +2941,6 @@ These features still need to be handled:
29032941
|6.1|2024-09-09| - Update for image-array sub-region copy support.
29042942
|6.2|2024-09-26| - Added addressing mode `ext_oneapi_clamp_to_border` value,
29052943
equivalent to `clamp`, to match with external APIs.
2944+
|6.3|2024-10-02| - Add support for `image_mem_handle` to `image_mem_handle`
2945+
sub-region copies.
29062946
|======================

sycl/include/sycl/ext/oneapi/bindless_images.hpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1609,6 +1609,58 @@ inline event queue::ext_oneapi_copy(
16091609
TlsCodeLocCapture.query());
16101610
}
16111611

1612+
inline event queue::ext_oneapi_copy(
1613+
const ext::oneapi::experimental::image_mem_handle Src,
1614+
sycl::range<3> SrcOffset,
1615+
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
1616+
ext::oneapi::experimental::image_mem_handle Dest, sycl::range<3> DestOffset,
1617+
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
1618+
sycl::range<3> CopyExtent, const detail::code_location &CodeLoc) {
1619+
detail::tls_code_loc_t TlsCodeLocCapture(CodeLoc);
1620+
return submit(
1621+
[&](handler &CGH) {
1622+
CGH.ext_oneapi_copy(Src, SrcOffset, SrcImgDesc, Dest, DestOffset,
1623+
DestImgDesc, CopyExtent);
1624+
},
1625+
CodeLoc);
1626+
}
1627+
1628+
inline event queue::ext_oneapi_copy(
1629+
const ext::oneapi::experimental::image_mem_handle Src,
1630+
sycl::range<3> SrcOffset,
1631+
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
1632+
ext::oneapi::experimental::image_mem_handle Dest, sycl::range<3> DestOffset,
1633+
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
1634+
sycl::range<3> CopyExtent, event DepEvent,
1635+
const detail::code_location &CodeLoc) {
1636+
detail::tls_code_loc_t TlsCodeLocCapture(CodeLoc);
1637+
return submit(
1638+
[&](handler &CGH) {
1639+
CGH.depends_on(DepEvent);
1640+
CGH.ext_oneapi_copy(Src, SrcOffset, SrcImgDesc, Dest, DestOffset,
1641+
DestImgDesc, CopyExtent);
1642+
},
1643+
CodeLoc);
1644+
}
1645+
1646+
inline event queue::ext_oneapi_copy(
1647+
const ext::oneapi::experimental::image_mem_handle Src,
1648+
sycl::range<3> SrcOffset,
1649+
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
1650+
ext::oneapi::experimental::image_mem_handle Dest, sycl::range<3> DestOffset,
1651+
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
1652+
sycl::range<3> CopyExtent, const std::vector<event> &DepEvents,
1653+
const detail::code_location &CodeLoc) {
1654+
detail::tls_code_loc_t TlsCodeLocCapture(CodeLoc);
1655+
return submit(
1656+
[&](handler &CGH) {
1657+
CGH.depends_on(DepEvents);
1658+
CGH.ext_oneapi_copy(Src, SrcOffset, SrcImgDesc, Dest, DestOffset,
1659+
DestImgDesc, CopyExtent);
1660+
},
1661+
CodeLoc);
1662+
}
1663+
16121664
inline event queue::ext_oneapi_copy(
16131665
const void *Src, sycl::range<3> SrcOffset, void *Dest,
16141666
sycl::range<3> DestOffset,

sycl/include/sycl/handler.hpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3077,7 +3077,7 @@ class __SYCL_EXPORT handler {
30773077
/// incomplete.
30783078
///
30793079
/// \param Src is an opaque image memory handle to the source memory.
3080-
/// \param SrcOffset is an offset from the origin of source measured in pixels
3080+
/// \param SrcOffset is an offset from the source origin measured in pixels
30813081
/// (pixel size determined by \p SrcImgDesc )
30823082
/// \param SrcImgDesc is the source image descriptor
30833083
/// \param Dest is a USM pointer to the destination memory.
@@ -3123,6 +3123,32 @@ class __SYCL_EXPORT handler {
31233123
ext::oneapi::experimental::image_mem_handle Dest,
31243124
const ext::oneapi::experimental::image_descriptor &ImageDesc);
31253125

3126+
/// Copies data from device to device memory, where \p Src and \p Dest
3127+
/// are opaque image memory handles. Allows for a sub-region copy, where
3128+
/// \p SrcOffset, \p DestOffset and \p CopyExtent are used to determine the
3129+
/// sub-region. Pixel size is determined by \p SrcImgDesc
3130+
/// An exception is thrown if either \p Src or \p Dest is incomplete.
3131+
///
3132+
/// \param Src is an opaque image memory handle to the source memory.
3133+
/// \param SrcOffset is an offset from the source origin measured in pixels
3134+
/// (pixel size determined by \p SrcImgDesc )
3135+
/// \param SrcImgDesc is the source image descriptor
3136+
/// \param Dest is an opaque image memory handle to the destination memory.
3137+
/// \param DestOffset is an offset from the destination origin measured in
3138+
/// pixels (pixel size determined by \p DestImgDesc )
3139+
/// \param DestImgDesc is the destination image descriptor
3140+
/// \param CopyExtent is the width, height, and depth of the region to copy
3141+
/// measured in pixels (pixel size determined by
3142+
/// \p SrcImgDesc )
3143+
void ext_oneapi_copy(
3144+
const ext::oneapi::experimental::image_mem_handle Src,
3145+
sycl::range<3> SrcOffset,
3146+
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
3147+
ext::oneapi::experimental::image_mem_handle Dest,
3148+
sycl::range<3> DestOffset,
3149+
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
3150+
sycl::range<3> CopyExtent);
3151+
31263152
/// Copies data from one memory region to another, where \p Src and \p Dest
31273153
/// are USM pointers. Allows for a sub-region copy, where \p SrcOffset ,
31283154
/// \p DestOffset , and \p Extent are used to determine the sub-region.

sycl/include/sycl/queue.hpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1765,6 +1765,93 @@ class __SYCL_EXPORT queue : public detail::OwnerLessBase<queue> {
17651765
const ext::oneapi::experimental::image_descriptor &ImageDesc,
17661766
const detail::code_location &CodeLoc = detail::code_location::current());
17671767

1768+
/// Copies data from device to device memory, where \p Src and \p Dest
1769+
/// are opaque image memory handles. Allows for a sub-region copy, where
1770+
/// \p SrcOffset, \p DestOffset and \p CopyExtent are used to determine the
1771+
/// sub-region. Pixel size is determined by \p SrcImgDesc
1772+
/// An exception is thrown if either \p Src or \p Dest is incomplete.
1773+
///
1774+
/// \param Src is an opaque image memory handle to the source memory.
1775+
/// \param SrcOffset is an offset from the origin of source measured in pixels
1776+
/// (pixel size determined by \p SrcImgDesc )
1777+
/// \param SrcImgDesc is the source image descriptor
1778+
/// \param Dest is an opaque image memory handle to the destination memory.
1779+
/// \param DestOffset is an offset from the origin of destination measured in
1780+
/// pixels (pixel size determined by \p DestImgDesc )
1781+
/// \param DestImgDesc is the destination image descriptor
1782+
/// \param CopyExtent is the width, height, and depth of the region to copy
1783+
/// measured in pixels (pixel size determined by
1784+
/// \p SrcImgDesc )
1785+
/// \return an event representing the copy operation.
1786+
event ext_oneapi_copy(
1787+
const ext::oneapi::experimental::image_mem_handle Src,
1788+
sycl::range<3> SrcOffset,
1789+
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
1790+
ext::oneapi::experimental::image_mem_handle Dest,
1791+
sycl::range<3> DestOffset,
1792+
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
1793+
sycl::range<3> CopyExtent,
1794+
const detail::code_location &CodeLoc = detail::code_location::current());
1795+
1796+
/// Copies data from device to device memory, where \p Src and \p Dest
1797+
/// are opaque image memory handles. Allows for a sub-region copy, where
1798+
/// \p SrcOffset, \p DestOffset and \p CopyExtent are used to determine the
1799+
/// sub-region. Pixel size is determined by \p SrcImgDesc
1800+
/// An exception is thrown if either \p Src or \p Dest is incomplete.
1801+
///
1802+
/// \param Src is an opaque image memory handle to the source memory.
1803+
/// \param SrcOffset is an offset from the origin of source measured in pixels
1804+
/// (pixel size determined by \p SrcImgDesc )
1805+
/// \param SrcImgDesc is the source image descriptor
1806+
/// \param Dest is an opaque image memory handle to the destination memory.
1807+
/// \param DestOffset is an offset from the origin of destination measured in
1808+
/// pixels (pixel size determined by \p DestImgDesc )
1809+
/// \param DestImgDesc is the destination image descriptor
1810+
/// \param CopyExtent is the width, height, and depth of the region to copy
1811+
/// measured in pixels (pixel size determined by
1812+
/// \p SrcImgDesc )
1813+
/// \param DepEvent is an event that specifies the kernel dependencies.
1814+
/// \return an event representing the copy operation.
1815+
event ext_oneapi_copy(
1816+
const ext::oneapi::experimental::image_mem_handle Src,
1817+
sycl::range<3> SrcOffset,
1818+
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
1819+
ext::oneapi::experimental::image_mem_handle Dest,
1820+
sycl::range<3> DestOffset,
1821+
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
1822+
sycl::range<3> CopyExtent, event DepEvent,
1823+
const detail::code_location &CodeLoc = detail::code_location::current());
1824+
1825+
/// Copies data from device to device memory, where \p Src and \p Dest
1826+
/// are opaque image memory handles. Allows for a sub-region copy, where
1827+
/// \p SrcOffset, \p DestOffset and \p CopyExtent are used to determine the
1828+
/// sub-region. Pixel size is determined by \p SrcImgDesc
1829+
/// An exception is thrown if either \p Src or \p Dest is incomplete.
1830+
///
1831+
/// \param Src is an opaque image memory handle to the source memory.
1832+
/// \param SrcOffset is an offset from the origin of source measured in pixels
1833+
/// (pixel size determined by \p SrcImgDesc )
1834+
/// \param srcImgDesc is the source image descriptor
1835+
/// \param Dest is an opaque image memory handle to the destination memory.
1836+
/// \param DestOffset is an offset from the origin of destination measured in
1837+
/// pixels (pixel size determined by \p DestImgDesc )
1838+
/// \param DestImgDesc is the destination image descriptor
1839+
/// \param CopyExtent is the width, height, and depth of the region to copy
1840+
/// measured in pixels (pixel size determined by
1841+
/// \p SrcImgDesc )
1842+
/// \param DepEvents is a vector of events that specifies the kernel
1843+
/// dependencies.
1844+
/// \return an event representing the copy operation.
1845+
event ext_oneapi_copy(
1846+
const ext::oneapi::experimental::image_mem_handle Src,
1847+
sycl::range<3> SrcOffset,
1848+
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
1849+
ext::oneapi::experimental::image_mem_handle Dest,
1850+
sycl::range<3> DestOffset,
1851+
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
1852+
sycl::range<3> CopyExtent, const std::vector<event> &DepEvents,
1853+
const detail::code_location &CodeLoc = detail::code_location::current());
1854+
17681855
/// Copies data from one memory region to another, where \p Src and \p Dest
17691856
/// are USM pointers. Allows for a sub-region copy, where \p SrcOffset ,
17701857
/// \p DestOffset , and \p Extent are used to determine the sub-region.

sycl/source/handler.cpp

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,105 @@ void handler::ext_oneapi_copy(
12521252
setType(detail::CGType::CopyImage);
12531253
}
12541254

1255+
void handler::ext_oneapi_copy(
1256+
const ext::oneapi::experimental::image_mem_handle Src,
1257+
sycl::range<3> SrcOffset,
1258+
const ext::oneapi::experimental::image_descriptor &SrcImgDesc,
1259+
ext::oneapi::experimental::image_mem_handle Dest, sycl::range<3> DestOffset,
1260+
const ext::oneapi::experimental::image_descriptor &DestImgDesc,
1261+
sycl::range<3> CopyExtent) {
1262+
throwIfGraphAssociated<
1263+
ext::oneapi::experimental::detail::UnsupportedGraphFeatures::
1264+
sycl_ext_oneapi_bindless_images>();
1265+
SrcImgDesc.verify();
1266+
DestImgDesc.verify();
1267+
1268+
auto isOutOfRange = [](const sycl::range<3> &range,
1269+
const sycl::range<3> &offset,
1270+
const sycl::range<3> &copyExtent) {
1271+
sycl::range<3> result = (range > 0UL && ((offset + copyExtent) > range));
1272+
1273+
return (static_cast<bool>(result[0]) || static_cast<bool>(result[1]) ||
1274+
static_cast<bool>(result[2]));
1275+
};
1276+
1277+
sycl::range<3> SrcImageSize = {SrcImgDesc.width, SrcImgDesc.height,
1278+
SrcImgDesc.depth};
1279+
sycl::range<3> DestImageSize = {DestImgDesc.width, DestImgDesc.height,
1280+
DestImgDesc.depth};
1281+
1282+
if (isOutOfRange(SrcImageSize, SrcOffset, CopyExtent) ||
1283+
isOutOfRange(DestImageSize, DestOffset, CopyExtent)) {
1284+
throw sycl::exception(
1285+
make_error_code(errc::invalid),
1286+
"Image copy attempted to access out of bounds memory!");
1287+
}
1288+
1289+
MSrcPtr = reinterpret_cast<void *>(Src.raw_handle);
1290+
MDstPtr = reinterpret_cast<void *>(Dest.raw_handle);
1291+
1292+
ur_image_desc_t UrSrcDesc = {};
1293+
UrSrcDesc.width = SrcImgDesc.width;
1294+
UrSrcDesc.height = SrcImgDesc.height;
1295+
UrSrcDesc.depth = SrcImgDesc.depth;
1296+
UrSrcDesc.arraySize = SrcImgDesc.array_size;
1297+
1298+
ur_image_desc_t UrDestDesc = {};
1299+
UrDestDesc.width = DestImgDesc.width;
1300+
UrDestDesc.height = DestImgDesc.height;
1301+
UrDestDesc.depth = DestImgDesc.depth;
1302+
UrDestDesc.arraySize = DestImgDesc.array_size;
1303+
1304+
auto fill_image_type =
1305+
[](const ext::oneapi::experimental::image_descriptor &Desc,
1306+
ur_image_desc_t &UrDesc) {
1307+
if (Desc.array_size > 1) {
1308+
// Image Array.
1309+
UrDesc.type = Desc.height > 0 ? UR_MEM_TYPE_IMAGE2D_ARRAY
1310+
: UR_MEM_TYPE_IMAGE1D_ARRAY;
1311+
1312+
// Cubemap.
1313+
UrDesc.type =
1314+
Desc.type == sycl::ext::oneapi::experimental::image_type::cubemap
1315+
? UR_MEM_TYPE_IMAGE_CUBEMAP_EXP
1316+
: UrDesc.type;
1317+
} else {
1318+
UrDesc.type = Desc.depth > 0
1319+
? UR_MEM_TYPE_IMAGE3D
1320+
: (Desc.height > 0 ? UR_MEM_TYPE_IMAGE2D
1321+
: UR_MEM_TYPE_IMAGE1D);
1322+
}
1323+
};
1324+
1325+
fill_image_type(SrcImgDesc, UrSrcDesc);
1326+
fill_image_type(DestImgDesc, UrDestDesc);
1327+
1328+
auto fill_format = [](const ext::oneapi::experimental::image_descriptor &Desc,
1329+
ur_image_format_t &UrFormat) {
1330+
UrFormat.channelType =
1331+
sycl::_V1::detail::convertChannelType(Desc.channel_type);
1332+
UrFormat.channelOrder = sycl::detail::convertChannelOrder(
1333+
sycl::_V1::ext::oneapi::experimental::detail::
1334+
get_image_default_channel_order(Desc.num_channels));
1335+
};
1336+
1337+
ur_image_format_t UrSrcFormat;
1338+
ur_image_format_t UrDestFormat;
1339+
1340+
fill_format(SrcImgDesc, UrSrcFormat);
1341+
fill_format(DestImgDesc, UrDestFormat);
1342+
1343+
impl->MSrcOffset = {SrcOffset[0], SrcOffset[1], SrcOffset[2]};
1344+
impl->MDestOffset = {DestOffset[0], DestOffset[1], DestOffset[2]};
1345+
impl->MCopyExtent = {CopyExtent[0], CopyExtent[1], CopyExtent[2]};
1346+
impl->MSrcImageDesc = UrSrcDesc;
1347+
impl->MDstImageDesc = UrDestDesc;
1348+
impl->MSrcImageFormat = UrSrcFormat;
1349+
impl->MDstImageFormat = UrDestFormat;
1350+
impl->MImageCopyFlags = UR_EXP_IMAGE_COPY_FLAG_DEVICE_TO_DEVICE;
1351+
setType(detail::CGType::CopyImage);
1352+
}
1353+
12551354
void handler::ext_oneapi_copy(
12561355
const ext::oneapi::experimental::image_mem_handle Src,
12571356
sycl::range<3> SrcOffset,

0 commit comments

Comments
 (0)