@@ -742,12 +742,28 @@ template <typename CoordT> constexpr void assert_sampled_coords() {
742
742
" Expected float coordinates data type" );
743
743
}
744
744
}
745
+
746
+ template <typename DataT> constexpr bool is_data_size_valid () {
747
+ return (sizeof (DataT) == 1 ) || (sizeof (DataT) == 2 ) || (sizeof (DataT) == 4 ) ||
748
+ (sizeof (DataT) == 8 ) || (sizeof (DataT) == 16 );
749
+ }
750
+
751
+ template <typename DataT> constexpr bool is_recognized_standard_type () {
752
+ return is_data_size_valid<DataT>() &&
753
+ (is_vec_v<DataT> || std::is_scalar_v<DataT> ||
754
+ std::is_floating_point_v<DataT> || std::is_same_v<DataT, sycl::half>);
755
+ }
756
+
745
757
} // namespace detail
746
758
747
759
/* *
748
760
* @brief Read an unsampled image using its handle
749
761
*
750
762
* @tparam DataT The return type
763
+ * @tparam HintT A hint type that can be used to select for a specialized
764
+ * backend intrinsic when a user-defined type is passed as `DataT`.
765
+ * HintT should be a `sycl::vec` type, `sycl::half` type, or POD type.
766
+ * HintT must also have the same size as DataT.
751
767
* @tparam CoordT The input coordinate type. e.g. int, int2, or int4 for
752
768
* 1D, 2D, and 3D, respectively
753
769
* @param imageHandle The image handle
@@ -760,7 +776,7 @@ template <typename CoordT> constexpr void assert_sampled_coords() {
760
776
* The name mangling should therefore not interfere with one
761
777
* another
762
778
*/
763
- template <typename DataT, typename CoordT>
779
+ template <typename DataT, typename HintT = DataT, typename CoordT>
764
780
DataT read_image (const unsampled_image_handle &imageHandle [[maybe_unused]],
765
781
const CoordT &coords [[maybe_unused]]) {
766
782
detail::assert_unsampled_coords<CoordT>();
@@ -770,7 +786,17 @@ DataT read_image(const unsampled_image_handle &imageHandle [[maybe_unused]],
770
786
" for 1D, 2D and 3D images, respectively." );
771
787
772
788
#ifdef __SYCL_DEVICE_ONLY__
773
- return __invoke__ImageRead<DataT>(imageHandle.raw_handle , coords);
789
+ if constexpr (detail::is_recognized_standard_type<DataT>()) {
790
+ return __invoke__ImageRead<DataT>(imageHandle.raw_handle , coords);
791
+ } else {
792
+ static_assert (sizeof (HintT) == sizeof (DataT),
793
+ " When trying to read a user-defined type, HintT must be of "
794
+ " the same size as the user-defined DataT." );
795
+ static_assert (detail::is_recognized_standard_type<HintT>(),
796
+ " HintT must always be a recognized standard type" );
797
+ return sycl::bit_cast<DataT>(
798
+ __invoke__ImageRead<HintT>(imageHandle.raw_handle , coords));
799
+ }
774
800
#else
775
801
assert (false ); // Bindless images not yet implemented on host
776
802
#endif
@@ -780,6 +806,10 @@ DataT read_image(const unsampled_image_handle &imageHandle [[maybe_unused]],
780
806
* @brief Read a sampled image using its handle
781
807
*
782
808
* @tparam DataT The return type
809
+ * @tparam HintT A hint type that can be used to select for a specialized
810
+ * backend intrinsic when a user-defined type is passed as `DataT`.
811
+ * HintT should be a `sycl::vec` type, `sycl::half` type, or POD type.
812
+ * HintT must also have the same size as DataT.
783
813
* @tparam CoordT The input coordinate type. e.g. float, float2, or float4 for
784
814
* 1D, 2D, and 3D, respectively
785
815
* @param imageHandle The image handle
@@ -792,7 +822,7 @@ DataT read_image(const unsampled_image_handle &imageHandle [[maybe_unused]],
792
822
* The name mangling should therefore not interfere with one
793
823
* another
794
824
*/
795
- template <typename DataT, typename CoordT>
825
+ template <typename DataT, typename HintT = DataT, typename CoordT>
796
826
DataT read_image (const sampled_image_handle &imageHandle [[maybe_unused]],
797
827
const CoordT &coords [[maybe_unused]]) {
798
828
detail::assert_sampled_coords<CoordT>();
@@ -802,7 +832,17 @@ DataT read_image(const sampled_image_handle &imageHandle [[maybe_unused]],
802
832
" for 1D, 2D and 3D images, respectively." );
803
833
804
834
#ifdef __SYCL_DEVICE_ONLY__
805
- return __invoke__ImageRead<DataT>(imageHandle.raw_handle , coords);
835
+ if constexpr (detail::is_recognized_standard_type<DataT>()) {
836
+ return __invoke__ImageRead<DataT>(imageHandle.raw_handle , coords);
837
+ } else {
838
+ static_assert (sizeof (HintT) == sizeof (DataT),
839
+ " When trying to read a user-defined type, HintT must be of "
840
+ " the same size as the user-defined DataT." );
841
+ static_assert (detail::is_recognized_standard_type<HintT>(),
842
+ " HintT must always be a recognized standard type" );
843
+ return sycl::bit_cast<DataT>(
844
+ __invoke__ImageRead<HintT>(imageHandle.raw_handle , coords));
845
+ }
806
846
#else
807
847
assert (false ); // Bindless images not yet implemented on host.
808
848
#endif
@@ -812,14 +852,18 @@ DataT read_image(const sampled_image_handle &imageHandle [[maybe_unused]],
812
852
* @brief Read a mipmap image using its handle with LOD filtering
813
853
*
814
854
* @tparam DataT The return type
855
+ * @tparam HintT A hint type that can be used to select for a specialized
856
+ * backend intrinsic when a user-defined type is passed as `DataT`.
857
+ * HintT should be a `sycl::vec` type, `sycl::half` type, or POD type.
858
+ * HintT must also have the same size as DataT.
815
859
* @tparam CoordT The input coordinate type. e.g. float, float2, or float4 for
816
860
* 1D, 2D, and 3D, respectively
817
861
* @param imageHandle The mipmap image handle
818
862
* @param coords The coordinates at which to fetch mipmap image data
819
863
* @param level The mipmap level at which to sample
820
864
* @return Mipmap image data with LOD filtering
821
865
*/
822
- template <typename DataT, typename CoordT>
866
+ template <typename DataT, typename HintT = DataT, typename CoordT>
823
867
DataT read_mipmap (const sampled_image_handle &imageHandle [[maybe_unused]],
824
868
const CoordT &coords [[maybe_unused]],
825
869
const float level [[maybe_unused]]) {
@@ -830,7 +874,17 @@ DataT read_mipmap(const sampled_image_handle &imageHandle [[maybe_unused]],
830
874
" for 1D, 2D and 3D images, respectively." );
831
875
832
876
#ifdef __SYCL_DEVICE_ONLY__
833
- return __invoke__ImageReadLod<DataT>(imageHandle.raw_handle , coords, level);
877
+ if constexpr (detail::is_recognized_standard_type<DataT>()) {
878
+ return __invoke__ImageReadLod<DataT>(imageHandle.raw_handle , coords, level);
879
+ } else {
880
+ static_assert (sizeof (HintT) == sizeof (DataT),
881
+ " When trying to read a user-defined type, HintT must be of "
882
+ " the same size as the user-defined DataT." );
883
+ static_assert (detail::is_recognized_standard_type<HintT>(),
884
+ " HintT must always be a recognized standard type" );
885
+ return sycl::bit_cast<DataT>(
886
+ __invoke__ImageReadLod<HintT>(imageHandle.raw_handle , coords, level));
887
+ }
834
888
#else
835
889
assert (false ); // Bindless images not yet implemented on host
836
890
#endif
@@ -840,6 +894,10 @@ DataT read_mipmap(const sampled_image_handle &imageHandle [[maybe_unused]],
840
894
* @brief Read a mipmap image using its handle with anisotropic filtering
841
895
*
842
896
* @tparam DataT The return type
897
+ * @tparam HintT A hint type that can be used to select for a specialized
898
+ * backend intrinsic when a user-defined type is passed as `DataT`.
899
+ * HintT should be a `sycl::vec` type, `sycl::half` type, or POD type.
900
+ * HintT must also have the same size as DataT.
843
901
* @tparam CoordT The input coordinate type. e.g. float, float2, or float4 for
844
902
* 1D, 2D, and 3D, respectively
845
903
* @param imageHandle The mipmap image handle
@@ -848,7 +906,7 @@ DataT read_mipmap(const sampled_image_handle &imageHandle [[maybe_unused]],
848
906
* @param dY Screen space gradient in the y dimension
849
907
* @return Mipmap image data with anisotropic filtering
850
908
*/
851
- template <typename DataT, typename CoordT>
909
+ template <typename DataT, typename HintT = DataT, typename CoordT>
852
910
DataT read_mipmap (const sampled_image_handle &imageHandle [[maybe_unused]],
853
911
const CoordT &coords [[maybe_unused]],
854
912
const CoordT &dX [[maybe_unused]],
@@ -860,7 +918,18 @@ DataT read_mipmap(const sampled_image_handle &imageHandle [[maybe_unused]],
860
918
" components for 1D, 2D, and 3D images, respectively." );
861
919
862
920
#ifdef __SYCL_DEVICE_ONLY__
863
- return __invoke__ImageReadGrad<DataT>(imageHandle.raw_handle , coords, dX, dY);
921
+ if constexpr (detail::is_recognized_standard_type<DataT>()) {
922
+ return __invoke__ImageReadGrad<DataT>(imageHandle.raw_handle , coords, dX,
923
+ dY);
924
+ } else {
925
+ static_assert (sizeof (HintT) == sizeof (DataT),
926
+ " When trying to read a user-defined type, HintT must be of "
927
+ " the same size as the user-defined DataT." );
928
+ static_assert (detail::is_recognized_standard_type<HintT>(),
929
+ " HintT must always be a recognized standard type" );
930
+ return sycl::bit_cast<DataT>(
931
+ __invoke__ImageReadGrad<HintT>(imageHandle.raw_handle , coords, dX, dY));
932
+ }
864
933
#else
865
934
assert (false ); // Bindless images not yet implemented on host
866
935
#endif
@@ -871,14 +940,18 @@ DataT read_mipmap(const sampled_image_handle &imageHandle [[maybe_unused]],
871
940
* filtering
872
941
*
873
942
* @tparam DataT The return type
943
+ * @tparam HintT A hint type that can be used to select for a specialized
944
+ * backend intrinsic when a user-defined type is passed as `DataT`.
945
+ * HintT should be a `sycl::vec` type, `sycl::half` type, or POD type.
946
+ * HintT must also have the same size as DataT.
874
947
* @tparam CoordT The input coordinate type. e.g. float, float2, or float4 for
875
948
* 1D, 2D, and 3D, respectively
876
949
* @param imageHandle The mipmap image handle
877
950
* @param coords The coordinates at which to fetch mipmap image data
878
951
* @param level The mipmap level at which to sample
879
952
* @return Mipmap image data with LOD filtering
880
953
*/
881
- template <typename DataT, typename CoordT>
954
+ template <typename DataT, typename HintT = DataT, typename CoordT>
882
955
__SYCL_DEPRECATED (" read_image for mipmaps is deprecated. "
883
956
" Instead use read_mipmap." )
884
957
DataT read_image (const sampled_image_handle &imageHandle [[maybe_unused]],
@@ -891,7 +964,17 @@ DataT read_image(const sampled_image_handle &imageHandle [[maybe_unused]],
891
964
" for 1D, 2D and 3D images, respectively." );
892
965
893
966
#ifdef __SYCL_DEVICE_ONLY__
894
- return __invoke__ImageReadLod<DataT>(imageHandle.raw_handle , coords, level);
967
+ if constexpr (detail::is_recognized_standard_type<DataT>()) {
968
+ return __invoke__ImageReadLod<DataT>(imageHandle.raw_handle , coords, level);
969
+ } else {
970
+ static_assert (sizeof (HintT) == sizeof (DataT),
971
+ " When trying to read a user-defined type, HintT must be of "
972
+ " the same size as the user-defined DataT." );
973
+ static_assert (detail::is_recognized_standard_type<HintT>(),
974
+ " HintT must always be a recognized standard type" );
975
+ return sycl::bit_cast<DataT>(
976
+ __invoke__ImageReadLod<HintT>(imageHandle.raw_handle , coords, level));
977
+ }
895
978
#else
896
979
assert (false ); // Bindless images not yet implemented on host
897
980
#endif
@@ -902,6 +985,10 @@ DataT read_image(const sampled_image_handle &imageHandle [[maybe_unused]],
902
985
* filtering
903
986
*
904
987
* @tparam DataT The return type
988
+ * @tparam HintT A hint type that can be used to select for a specialized
989
+ * backend intrinsic when a user-defined type is passed as `DataT`.
990
+ * HintT should be a `sycl::vec` type, `sycl::half` type, or POD type.
991
+ * HintT must also have the same size as DataT.
905
992
* @tparam CoordT The input coordinate type. e.g. float, float2, or float4 for
906
993
* 1D, 2D, and 3D, respectively
907
994
* @param imageHandle The mipmap image handle
@@ -910,7 +997,7 @@ DataT read_image(const sampled_image_handle &imageHandle [[maybe_unused]],
910
997
* @param dY Screen space gradient in the y dimension
911
998
* @return Mipmap image data with anisotropic filtering
912
999
*/
913
- template <typename DataT, typename CoordT>
1000
+ template <typename DataT, typename HintT = DataT, typename CoordT>
914
1001
__SYCL_DEPRECATED (" read_image for mipmaps is deprecated. "
915
1002
" Instead use read_mipmap." )
916
1003
DataT read_image (const sampled_image_handle &imageHandle [[maybe_unused]],
@@ -924,7 +1011,18 @@ DataT read_image(const sampled_image_handle &imageHandle [[maybe_unused]],
924
1011
" components for 1D, 2D, and 3D images, respectively." );
925
1012
926
1013
#ifdef __SYCL_DEVICE_ONLY__
927
- return __invoke__ImageReadGrad<DataT>(imageHandle.raw_handle , coords, dX, dY);
1014
+ if constexpr (detail::is_recognized_standard_type<DataT>()) {
1015
+ return __invoke__ImageReadGrad<DataT>(imageHandle.raw_handle , coords, dX,
1016
+ dY);
1017
+ } else {
1018
+ static_assert (sizeof (HintT) == sizeof (DataT),
1019
+ " When trying to read a user-defined type, HintT must be of "
1020
+ " the same size as the user-defined DataT." );
1021
+ static_assert (detail::is_recognized_standard_type<HintT>(),
1022
+ " HintT must always be a recognized standard type" );
1023
+ return sycl::bit_cast<DataT>(
1024
+ __invoke__ImageReadGrad<HintT>(imageHandle.raw_handle , coords, dX, dY));
1025
+ }
928
1026
#else
929
1027
assert (false ); // Bindless images not yet implemented on host
930
1028
#endif
@@ -951,8 +1049,14 @@ void write_image(const unsampled_image_handle &imageHandle [[maybe_unused]],
951
1049
952
1050
#ifdef __SYCL_DEVICE_ONLY__
953
1051
#if defined(__NVPTX__)
954
- __invoke__ImageWrite ((uint64_t )imageHandle.raw_handle , coords,
955
- detail::convert_color_nvptx (color));
1052
+ if constexpr (detail::is_recognized_standard_type<DataT>()) {
1053
+ __invoke__ImageWrite ((uint64_t )imageHandle.raw_handle , coords, color);
1054
+ } else {
1055
+ // Convert DataT to a supported backend write type when user-defined type is
1056
+ // passed
1057
+ __invoke__ImageWrite ((uint64_t )imageHandle.raw_handle , coords,
1058
+ detail::convert_color_nvptx (color));
1059
+ }
956
1060
#else
957
1061
__invoke__ImageWrite ((uint64_t )imageHandle.raw_handle , coords, color);
958
1062
#endif
0 commit comments