99#pragma once
1010
1111#include < CL/sycl/access/access.hpp>
12+ #include < CL/sycl/atomic.hpp>
1213#include < CL/sycl/context.hpp>
1314#include < CL/sycl/detail/cg.hpp>
1415#include < CL/sycl/detail/export.hpp>
@@ -366,6 +367,107 @@ class __SYCL_EXPORT handler {
366367 return true ;
367368 }
368369
370+ // / Handles some special cases of the copy operation from one accessor
371+ // / to another accessor. Returns true if the copy is handled here.
372+ // /
373+ // / \param Src is a source SYCL accessor.
374+ // / \param Dst is a destination SYCL accessor.
375+ // TODO: support atomic accessor in Src or/and Dst.
376+ template <typename TSrc, int DimSrc, access::mode ModeSrc,
377+ access::target TargetSrc, typename TDst, int DimDst,
378+ access::mode ModeDst, access::target TargetDst,
379+ access::placeholder IsPHSrc, access::placeholder IsPHDst>
380+ detail::enable_if_t <(DimSrc > 0 ) && (DimDst > 0 ), bool >
381+ copyAccToAccHelper (accessor<TSrc, DimSrc, ModeSrc, TargetSrc, IsPHSrc> Src,
382+ accessor<TDst, DimDst, ModeDst, TargetDst, IsPHDst> Dst) {
383+ if (!MIsHost &&
384+ IsCopyingRectRegionAvailable (Src.get_range (), Dst.get_range ()))
385+ return false ;
386+
387+ range<1 > LinearizedRange (Src.get_count ());
388+ parallel_for<class __copyAcc2Acc <TSrc, DimSrc, ModeSrc, TargetSrc,
389+ TDst, DimDst, ModeDst, TargetDst,
390+ IsPHSrc, IsPHDst>>
391+ (LinearizedRange, [=](id<1 > Id) {
392+ size_t Index = Id[0 ];
393+ id<DimSrc> SrcIndex = getDelinearizedIndex (Src.get_range (), Index);
394+ id<DimDst> DstIndex = getDelinearizedIndex (Dst.get_range (), Index);
395+ Dst[DstIndex] = Src[SrcIndex];
396+ });
397+ return true ;
398+ }
399+
400+ template <typename T, int Dim, access::mode Mode, access::target Target,
401+ access::placeholder IsPH>
402+ detail::enable_if_t <Dim == 0 && Mode == access::mode::atomic, T>
403+ readFromFirstAccElement (accessor<T, Dim, Mode, Target, IsPH> Src) const {
404+ atomic<T, access::address_space::global_space> AtomicSrc = Src;
405+ return AtomicSrc.load ();
406+ }
407+
408+ template <typename T, int Dim, access::mode Mode, access::target Target,
409+ access::placeholder IsPH>
410+ detail::enable_if_t <(Dim > 0 ) && Mode == access::mode::atomic, T>
411+ readFromFirstAccElement (accessor<T, Dim, Mode, Target, IsPH> Src) const {
412+ id<Dim> Id = getDelinearizedIndex (Src.get_range (), 0 );
413+ return Src[Id].load ();
414+ }
415+
416+ template <typename T, int Dim, access::mode Mode, access::target Target,
417+ access::placeholder IsPH>
418+ detail::enable_if_t <Mode != access::mode::atomic, T>
419+ readFromFirstAccElement (accessor<T, Dim, Mode, Target, IsPH> Src) const {
420+ return *(Src.get_pointer ());
421+ }
422+
423+ template <typename T, int Dim, access::mode Mode, access::target Target,
424+ access::placeholder IsPH>
425+ detail::enable_if_t <Dim == 0 && Mode == access::mode::atomic, void >
426+ writeToFirstAccElement (accessor<T, Dim, Mode, Target, IsPH> Dst, T V) const {
427+ atomic<T, access::address_space::global_space> AtomicDst = Dst;
428+ AtomicDst.store (V);
429+ }
430+
431+ template <typename T, int Dim, access::mode Mode, access::target Target,
432+ access::placeholder IsPH>
433+ detail::enable_if_t <(Dim > 0 ) && Mode == access::mode::atomic, void >
434+ writeToFirstAccElement (accessor<T, Dim, Mode, Target, IsPH> Dst, T V) const {
435+ id<Dim> Id = getDelinearizedIndex (Dst.get_range (), 0 );
436+ Dst[Id].store (V);
437+ }
438+
439+ template <typename T, int Dim, access::mode Mode, access::target Target,
440+ access::placeholder IsPH>
441+ detail::enable_if_t <Mode != access::mode::atomic, void >
442+ writeToFirstAccElement (accessor<T, Dim, Mode, Target, IsPH> Dst, T V) const {
443+ *(Dst.get_pointer ()) = V;
444+ }
445+
446+ // / Handles some special cases of the copy operation from one accessor
447+ // / to another accessor. Returns true if the copy is handled here.
448+ // /
449+ // / Source must have at least as many bytes as the range accessed by Dst.
450+ // /
451+ // / \param Src is a source SYCL accessor.
452+ // / \param Dst is a destination SYCL accessor.
453+ template <typename TSrc, int DimSrc, access::mode ModeSrc,
454+ access::target TargetSrc, typename TDst, int DimDst,
455+ access::mode ModeDst, access::target TargetDst,
456+ access::placeholder IsPHSrc, access::placeholder IsPHDst>
457+ detail::enable_if_t <DimSrc == 0 || DimDst == 0 , bool >
458+ copyAccToAccHelper (accessor<TSrc, DimSrc, ModeSrc, TargetSrc, IsPHSrc> Src,
459+ accessor<TDst, DimDst, ModeDst, TargetDst, IsPHDst> Dst) {
460+ if (!MIsHost)
461+ return false ;
462+
463+ single_task<class __copyAcc2Acc <TSrc, DimSrc, ModeSrc, TargetSrc,
464+ TDst, DimDst, ModeDst, TargetDst,
465+ IsPHSrc, IsPHDst>> ([=]() {
466+ writeToFirstAccElement (Dst, readFromFirstAccElement (Src));
467+ });
468+ return true ;
469+ }
470+
369471 constexpr static bool isConstOrGlobal (access::target AccessTarget) {
370472 return AccessTarget == access::target::global_buffer ||
371473 AccessTarget == access::target::constant_buffer;
@@ -985,6 +1087,7 @@ class __SYCL_EXPORT handler {
9851087 // /
9861088 // / \param Src is a source SYCL accessor.
9871089 // / \param Dst is a pointer to destination memory.
1090+ // TODO: support 0-dimensional and atomic accessors.
9881091 template <typename T_Src, typename T_Dst, int Dims, access::mode AccessMode,
9891092 access::target AccessTarget,
9901093 access::placeholder IsPlaceholder = access::placeholder::false_t >
@@ -1030,6 +1133,7 @@ class __SYCL_EXPORT handler {
10301133 // /
10311134 // / \param Src is a pointer to source memory.
10321135 // / \param Dst is a destination SYCL accessor.
1136+ // TODO: support 0-dimensional and atomic accessors.
10331137 template <typename T_Src, typename T_Dst, int Dims, access::mode AccessMode,
10341138 access::target AccessTarget,
10351139 access::placeholder IsPlaceholder = access::placeholder::false_t >
@@ -1072,7 +1176,7 @@ class __SYCL_EXPORT handler {
10721176 // / Copies the contents of memory object accessed by Src to the memory
10731177 // / object accessed by Dst.
10741178 // /
1075- // / Source must have at least as many bytes as the range accessed by Dst .
1179+ // / Dst must have at least as many bytes as the range accessed by Src .
10761180 // /
10771181 // / \param Src is a source SYCL accessor.
10781182 // / \param Dst is a destination SYCL accessor.
@@ -1093,32 +1197,10 @@ class __SYCL_EXPORT handler {
10931197 " Invalid source accessor target for the copy method." );
10941198 static_assert (isValidTargetForExplicitOp (AccessTarget_Dst),
10951199 " Invalid destination accessor target for the copy method." );
1096- // TODO replace to get_size() when it will provide correct values.
1097- assert (
1098- (Dst.get_range ().size () * sizeof (T_Dst) >=
1099- Src.get_range ().size () * sizeof (T_Src)) &&
1100- " dest must have at least as many bytes as the range accessed by src." );
1101- if (MIsHost ||
1102- !IsCopyingRectRegionAvailable (Src.get_range (), Dst.get_range ())) {
1103- range<Dims_Src> CopyRange = Src.get_range ();
1104- size_t Range = 1 ;
1105- for (size_t I = 0 ; I < Dims_Src; ++I)
1106- Range *= CopyRange[I];
1107- range<1 > LinearizedRange (Range);
1108- parallel_for< class __copyAcc2Acc < T_Src, Dims_Src, AccessMode_Src,
1109- AccessTarget_Src, T_Dst, Dims_Dst,
1110- AccessMode_Dst, AccessTarget_Dst,
1111- IsPlaceholder_Src,
1112- IsPlaceholder_Dst>>
1113- (LinearizedRange, [=](id<1 > Id) {
1114- size_t Index = Id[0 ];
1115- id<Dims_Src> SrcIndex = getDelinearizedIndex (Src.get_range (), Index);
1116- id<Dims_Dst> DstIndex = getDelinearizedIndex (Dst.get_range (), Index);
1117- Dst[DstIndex] = Src[SrcIndex];
1118- });
1119-
1200+ assert (Dst.get_size () >= Src.get_size () &&
1201+ " The destination accessor does not fit the copied memory." );
1202+ if (copyAccToAccHelper (Src, Dst))
11201203 return ;
1121- }
11221204 MCGType = detail::CG::COPY_ACC_TO_ACC;
11231205
11241206 detail::AccessorBaseHost *AccBaseSrc = (detail::AccessorBaseHost *)&Src;
0 commit comments