From a994da8af6a1df8106d68c099bdb0d71438ca67d Mon Sep 17 00:00:00 2001 From: Vladislav Sytchenko Date: Tue, 17 Mar 2020 12:52:20 -0400 Subject: [PATCH] Add constraints to texture fetch functions When sampling a pixel the hw always returns a float4. The type in the texture reference controls the bitcast that we perform before returning the sampled pixel. Creating a texture with an unsupported will lead to potential UB. This change makes it so that it's only possible to use textures with a type that makes sense. Using something like texture will now lead to a compilation error with a message "Invalid channel type!". Change-Id: I7fde44cb1d4b9737e0c48c28cb59c018c59ccaa2 --- .../hip/hcc_detail/texture_fetch_functions.h | 150 +++++++++++++++--- 1 file changed, 132 insertions(+), 18 deletions(-) diff --git a/hipamd/include/hip/hcc_detail/texture_fetch_functions.h b/hipamd/include/hip/hcc_detail/texture_fetch_functions.h index ad8deda400..39ac3ecd89 100644 --- a/hipamd/include/hip/hcc_detail/texture_fetch_functions.h +++ b/hipamd/include/hip/hcc_detail/texture_fetch_functions.h @@ -34,20 +34,106 @@ THE SOFTWARE. unsigned int ADDRESS_SPACE_CONSTANT* i = (unsigned int ADDRESS_SPACE_CONSTANT*)t.textureObject; \ unsigned int ADDRESS_SPACE_CONSTANT* s = i + HIP_SAMPLER_OBJECT_OFFSET_DWORD; -template -struct __hip_tex_ret {}; +template +struct __hip_is_channel_type +{ + static constexpr bool value = + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value; +}; -template -using __hip_tex_ret_t = typename __hip_tex_ret::type; - -template -struct __hip_tex_ret { using type = T; }; +template< + typename T, + unsigned int rank> +struct __hip_is_channel_type> +{ + static constexpr bool value = + __hip_is_channel_type::value && + ((rank == 1) || + (rank == 2) || + (rank == 4)); +}; template -struct __hip_tex_ret { using type = float; }; +struct __hip_is_normalized_channel_type +{ + static constexpr bool value = + std::is_same::value || + std::is_same::value || + std::is_same::value || + std::is_same::value; +}; -template -struct __hip_tex_ret, hipReadModeNormalizedFloat> { using type = HIP_vector_type; }; +template< + typename T, + unsigned int rank> +struct __hip_is_normalized_channel_type> +{ + static constexpr bool value = + __hip_is_normalized_channel_type::value && + ((rank == 1) || + (rank == 2) || + (rank == 4)); +}; + +template < + typename T, + hipTextureReadMode readMode, + typename Enable = void> +struct __hip_tex_ret +{ + static_assert(std::is_same::value, "Invalid channel type!"); +}; + +template < + typename T, + hipTextureReadMode readMode> +using __hip_tex_ret_t = typename __hip_tex_ret::type; + +template +struct __hip_tex_ret< + T, + hipReadModeElementType, + typename std::enable_if<__hip_is_channel_type::value, bool>::type> +{ + using type = T; +}; + +template< + typename T, + unsigned int rank> +struct __hip_tex_ret< + HIP_vector_type, + hipReadModeElementType, + typename std::enable_if<__hip_is_channel_type>::value, bool>::type> +{ + using type = HIP_vector_type<__hip_tex_ret_t, rank>; +}; + +template +struct __hip_tex_ret< + T, + hipReadModeNormalizedFloat, + typename std::enable_if<__hip_is_normalized_channel_type::value, bool>::type> +{ + using type = float; +}; + +template< + typename T, + unsigned int rank> +struct __hip_tex_ret< + HIP_vector_type, + hipReadModeNormalizedFloat, + typename std::enable_if<__hip_is_normalized_channel_type>::value, bool>::type> +{ + using type = HIP_vector_type<__hip_tex_ret_t, rank>; +}; template static __forceinline__ __device__ __hip_tex_ret_t tex1Dfetch(texture t, int x) @@ -229,20 +315,48 @@ static __forceinline__ __device__ __hip_tex_ret_t tex3DGrad(texture return *reinterpret_cast<__hip_tex_ret_t*>(&tmp); } -template -struct __hip_tex2dgather_ret {}; +template < + typename T, + hipTextureReadMode readMode, + typename Enable = void> +struct __hip_tex2dgather_ret +{ + static_assert(std::is_same::value, "Invalid channel type!"); +}; -template -using __hip_tex2dgather_ret_t = typename __hip_tex2dgather_ret::type; +template < + typename T, + hipTextureReadMode readMode> +using __hip_tex2dgather_ret_t = typename __hip_tex2dgather_ret::type; template -struct __hip_tex2dgather_ret { using type = HIP_vector_type; }; +struct __hip_tex2dgather_ret< + T, + hipReadModeElementType, + typename std::enable_if<__hip_is_channel_type::value, bool>::type> +{ + using type = HIP_vector_type; +}; -template -struct __hip_tex2dgather_ret, hipReadModeElementType> { using type = HIP_vector_type; }; +template< + typename T, + unsigned int rank> +struct __hip_tex2dgather_ret< + HIP_vector_type, + hipReadModeElementType, + typename std::enable_if<__hip_is_channel_type>::value, bool>::type> +{ + using type = HIP_vector_type; +}; template -struct __hip_tex2dgather_ret { using type = float4; }; +struct __hip_tex2dgather_ret< + T, + hipReadModeNormalizedFloat, + typename std::enable_if<__hip_is_normalized_channel_type::value, bool>::type> +{ + using type = float4; +}; template static __forceinline__ __device__ __hip_tex2dgather_ret_t tex2Dgather(texture t, float x, float y, int comp=0)