-
Notifications
You must be signed in to change notification settings - Fork 797
[SYCL][Bindless] Update and add support for SPV_INTEL_bindless_image extension new revision #13753
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
dd48b8e
7fd7b37
7fd6ce0
9fb5c7d
f674ba9
b564671
76c25e8
b7f82d7
f8f391f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -230,6 +230,18 @@ template <typename SampledType, typename TempRetT, typename TempArgT> | |
extern __DPCPP_SYCL_EXTERNAL TempRetT __spirv_ImageSampleCubemap(SampledType, | ||
TempArgT); | ||
|
||
template <typename RetT> | ||
extern __DPCPP_SYCL_EXTERNAL RetT | ||
__spirv_ConvertHandleToImageINTEL(unsigned long); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. unsigned long is 32bit on windows? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we use following code?
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. Added. |
||
|
||
template <typename RetT> | ||
extern __DPCPP_SYCL_EXTERNAL RetT | ||
__spirv_ConvertHandleToSamplerINTEL(unsigned long); | ||
|
||
template <typename RetT> | ||
extern __DPCPP_SYCL_EXTERNAL RetT | ||
__spirv_ConvertHandleToSampledImageINTEL(unsigned long); | ||
|
||
#define __SYCL_OpGroupAsyncCopyGlobalToLocal __spirv_GroupAsyncCopy | ||
#define __SYCL_OpGroupAsyncCopyLocalToGlobal __spirv_GroupAsyncCopy | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,12 +50,24 @@ struct sampled_image_handle { | |
|
||
sampled_image_handle() : raw_handle(~0) {} | ||
|
||
sampled_image_handle(raw_image_handle_type raw_image_handle) | ||
: raw_handle(raw_image_handle) {} | ||
sampled_image_handle(raw_image_handle_type handle) : raw_handle(handle) {} | ||
|
||
raw_image_handle_type raw_handle; | ||
}; | ||
|
||
// Image types used for generating SPIR-V | ||
#ifdef __SYCL_DEVICE_ONLY__ | ||
template <int NDims> | ||
using OCLImageTyRead = | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this part of the specification or should it be moved into the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, yeah it should be in the detail namespace. Moved it. |
||
typename sycl::detail::opencl_image_type<NDims, sycl::access::mode::read, | ||
sycl::access::target::image>::type; | ||
|
||
template <int NDims> | ||
using OCLImageTyWrite = | ||
typename sycl::detail::opencl_image_type<NDims, sycl::access::mode::write, | ||
sycl::access::target::image>::type; | ||
#endif | ||
|
||
/** | ||
* @brief Allocate image memory based on image_descriptor | ||
* | ||
|
@@ -792,6 +804,43 @@ template <typename DataT> constexpr bool is_recognized_standard_type() { | |
std::is_floating_point_v<DataT> || std::is_same_v<DataT, sycl::half>); | ||
} | ||
|
||
#ifdef __SYCL_DEVICE_ONLY__ | ||
|
||
// Macros are required because it is not legal for a function to return | ||
// a variable of type 'opencl_image_type'. | ||
aelovikov-intel marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#if defined(__NVPTX__) | ||
#define CONVERT_HANDLE_TO_IMAGE(raw_handle, ImageType) raw_handle | ||
#elif defined(__SPIR__) | ||
#define CONVERT_HANDLE_TO_IMAGE(raw_handle, ImageType) \ | ||
__spirv_ConvertHandleToImageINTEL<ImageType>(raw_handle) | ||
#else | ||
#define CONVERT_HANDLE_TO_IMAGE(raw_handle, ImageType) raw_handle | ||
wenju-he marked this conversation as resolved.
Show resolved
Hide resolved
|
||
#endif | ||
|
||
#if defined(__NVPTX__) | ||
#define CONVERT_HANDLE_TO_SAMPLED_IMAGE(raw_handle, ImageType) raw_handle | ||
#elif defined(__SPIR__) | ||
#define CONVERT_HANDLE_TO_SAMPLED_IMAGE(raw_handle, ImageType) \ | ||
__spirv_ConvertHandleToSampledImageINTEL< \ | ||
typename sycl::detail::sampled_opencl_image_type<ImageType>::type>( \ | ||
raw_handle) | ||
#else | ||
#define CONVERT_HANDLE_TO_SAMPLED_IMAGE(raw_handle, ImageType) raw_handle | ||
#endif | ||
|
||
#if defined(__NVPTX__) | ||
#define FETCH_UNSAMPLED_IMAGE(DataT, raw_handle, coords) \ | ||
__invoke__ImageFetch<DataT>(raw_handle, coords) | ||
#elif defined(__SPIR__) | ||
#define FETCH_UNSAMPLED_IMAGE(DataT, raw_handle, coords) \ | ||
__invoke__ImageRead<DataT>(raw_handle, coords) | ||
#else | ||
#define FETCH_UNSAMPLED_IMAGE(DataT, raw_handle, coords) \ | ||
__invoke__ImageFetch<DataT>(raw_handle, coords) | ||
#endif | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are these all the same? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not quite. In the CUDA backend, Interestingly, and slightly annoyingly, Also, turns out, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have removed one of the redundant branches. |
||
|
||
#endif | ||
|
||
} // namespace detail | ||
|
||
/** | ||
|
@@ -826,15 +875,23 @@ DataT fetch_image(const unsampled_image_handle &imageHandle [[maybe_unused]], | |
|
||
#ifdef __SYCL_DEVICE_ONLY__ | ||
if constexpr (detail::is_recognized_standard_type<DataT>()) { | ||
return __invoke__ImageFetch<DataT>(imageHandle.raw_handle, coords); | ||
return FETCH_UNSAMPLED_IMAGE( | ||
DataT, | ||
CONVERT_HANDLE_TO_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
coords); | ||
|
||
} else { | ||
static_assert(sizeof(HintT) == sizeof(DataT), | ||
"When trying to read a user-defined type, HintT must be of " | ||
"the same size as the user-defined DataT."); | ||
static_assert(detail::is_recognized_standard_type<HintT>(), | ||
"HintT must always be a recognized standard type"); | ||
return sycl::bit_cast<DataT>( | ||
__invoke__ImageFetch<HintT>(imageHandle.raw_handle, coords)); | ||
return sycl::bit_cast<DataT>(FETCH_UNSAMPLED_IMAGE( | ||
HintT, | ||
CONVERT_HANDLE_TO_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
coords)); | ||
} | ||
#else | ||
assert(false); // Bindless images not yet implemented on host | ||
|
@@ -907,10 +964,15 @@ DataT fetch_image(const sampled_image_handle &imageHandle [[maybe_unused]], | |
|
||
#ifdef __SYCL_DEVICE_ONLY__ | ||
if constexpr (detail::is_recognized_standard_type<DataT>()) { | ||
return __invoke__SampledImageFetch<DataT>(imageHandle.raw_handle, coords); | ||
return __invoke__SampledImageFetch<DataT>( | ||
CONVERT_HANDLE_TO_SAMPLED_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
coords); | ||
} else { | ||
return sycl::bit_cast<DataT>( | ||
__invoke__SampledImageFetch<HintT>(imageHandle.raw_handle, coords)); | ||
return sycl::bit_cast<DataT>(__invoke__SampledImageFetch<HintT>( | ||
CONVERT_HANDLE_TO_SAMPLED_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
coords)); | ||
} | ||
#else | ||
assert(false); // Bindless images not yet implemented on host. | ||
|
@@ -954,10 +1016,15 @@ DataT sample_image(const sampled_image_handle &imageHandle [[maybe_unused]], | |
|
||
#ifdef __SYCL_DEVICE_ONLY__ | ||
if constexpr (detail::is_recognized_standard_type<DataT>()) { | ||
return __invoke__ImageRead<DataT>(imageHandle.raw_handle, coords); | ||
return __invoke__ImageRead<DataT>( | ||
CONVERT_HANDLE_TO_SAMPLED_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
coords); | ||
} else { | ||
return sycl::bit_cast<DataT>( | ||
__invoke__ImageRead<HintT>(imageHandle.raw_handle, coords)); | ||
return sycl::bit_cast<DataT>(__invoke__ImageRead<HintT>( | ||
CONVERT_HANDLE_TO_SAMPLED_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
coords)); | ||
} | ||
#else | ||
assert(false); // Bindless images not yet implemented on host. | ||
|
@@ -1026,15 +1093,20 @@ DataT sample_mipmap(const sampled_image_handle &imageHandle [[maybe_unused]], | |
|
||
#ifdef __SYCL_DEVICE_ONLY__ | ||
if constexpr (detail::is_recognized_standard_type<DataT>()) { | ||
return __invoke__ImageReadLod<DataT>(imageHandle.raw_handle, coords, level); | ||
return __invoke__ImageReadLod<DataT>( | ||
CONVERT_HANDLE_TO_SAMPLED_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why wouldn't you put There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do agree that putting Because these functions are used to also create the PTX instructions for the CUDA backend I feel putting it inside There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have moved There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Technically, this file is outside SYCL RT codeownership, so the decision is ultimately yours :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I will leave it as is for now. Potentially revisit this later. |
||
coords, level); | ||
} else { | ||
static_assert(sizeof(HintT) == sizeof(DataT), | ||
"When trying to read a user-defined type, HintT must be of " | ||
"the same size as the user-defined DataT."); | ||
static_assert(detail::is_recognized_standard_type<HintT>(), | ||
"HintT must always be a recognized standard type"); | ||
return sycl::bit_cast<DataT>( | ||
__invoke__ImageReadLod<HintT>(imageHandle.raw_handle, coords, level)); | ||
return sycl::bit_cast<DataT>(__invoke__ImageReadLod<HintT>( | ||
CONVERT_HANDLE_TO_SAMPLED_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
coords, level)); | ||
} | ||
#else | ||
assert(false); // Bindless images not yet implemented on host | ||
|
@@ -1070,16 +1142,20 @@ DataT sample_mipmap(const sampled_image_handle &imageHandle [[maybe_unused]], | |
|
||
#ifdef __SYCL_DEVICE_ONLY__ | ||
if constexpr (detail::is_recognized_standard_type<DataT>()) { | ||
return __invoke__ImageReadGrad<DataT>(imageHandle.raw_handle, coords, dX, | ||
dY); | ||
return __invoke__ImageReadGrad<DataT>( | ||
CONVERT_HANDLE_TO_SAMPLED_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
coords, dX, dY); | ||
} else { | ||
static_assert(sizeof(HintT) == sizeof(DataT), | ||
"When trying to read a user-defined type, HintT must be of " | ||
"the same size as the user-defined DataT."); | ||
static_assert(detail::is_recognized_standard_type<HintT>(), | ||
"HintT must always be a recognized standard type"); | ||
return sycl::bit_cast<DataT>( | ||
__invoke__ImageReadGrad<HintT>(imageHandle.raw_handle, coords, dX, dY)); | ||
return sycl::bit_cast<DataT>(__invoke__ImageReadGrad<HintT>( | ||
CONVERT_HANDLE_TO_SAMPLED_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
coords, dX, dY)); | ||
} | ||
#else | ||
assert(false); // Bindless images not yet implemented on host | ||
|
@@ -1224,16 +1300,20 @@ DataT fetch_image_array(const unsampled_image_handle &imageHandle | |
|
||
#ifdef __SYCL_DEVICE_ONLY__ | ||
if constexpr (detail::is_recognized_standard_type<DataT>()) { | ||
return __invoke__ImageArrayFetch<DataT>(imageHandle.raw_handle, coords, | ||
arrayLayer); | ||
return __invoke__ImageArrayFetch<DataT>( | ||
CONVERT_HANDLE_TO_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
coords, arrayLayer); | ||
} else { | ||
static_assert(sizeof(HintT) == sizeof(DataT), | ||
"When trying to fetch a user-defined type, HintT must be of " | ||
"the same size as the user-defined DataT."); | ||
static_assert(detail::is_recognized_standard_type<HintT>(), | ||
"HintT must always be a recognized standard type"); | ||
return sycl::bit_cast<DataT>(__invoke__ImageArrayFetch<HintT>( | ||
imageHandle.raw_handle, coords, arrayLayer)); | ||
CONVERT_HANDLE_TO_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
coords, arrayLayer)); | ||
} | ||
#else | ||
assert(false); // Bindless images not yet implemented on host. | ||
|
@@ -1277,19 +1357,24 @@ DataT fetch_cubemap(const unsampled_image_handle &imageHandle, | |
template <typename DataT, typename HintT = DataT> | ||
DataT sample_cubemap(const sampled_image_handle &imageHandle [[maybe_unused]], | ||
const sycl::float3 &dirVec [[maybe_unused]]) { | ||
[[maybe_unused]] constexpr size_t NDims = 2; | ||
|
||
#ifdef __SYCL_DEVICE_ONLY__ | ||
if constexpr (detail::is_recognized_standard_type<DataT>()) { | ||
return __invoke__ImageReadCubemap<DataT, uint64_t>(imageHandle.raw_handle, | ||
dirVec); | ||
return __invoke__ImageReadCubemap<DataT, uint64_t>( | ||
CONVERT_HANDLE_TO_SAMPLED_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<NDims>), | ||
dirVec); | ||
} else { | ||
static_assert(sizeof(HintT) == sizeof(DataT), | ||
"When trying to read a user-defined type, HintT must be of " | ||
"the same size as the user-defined DataT."); | ||
static_assert(detail::is_recognized_standard_type<HintT>(), | ||
"HintT must always be a recognized standard type"); | ||
return sycl::bit_cast<DataT>(__invoke__ImageReadCubemap<HintT, uint64_t>( | ||
imageHandle.raw_handle, dirVec)); | ||
CONVERT_HANDLE_TO_SAMPLED_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<NDims>), | ||
dirVec)); | ||
} | ||
#else | ||
assert(false); // Bindless images not yet implemented on host | ||
|
@@ -1318,12 +1403,15 @@ void write_image(unsampled_image_handle imageHandle [[maybe_unused]], | |
|
||
#ifdef __SYCL_DEVICE_ONLY__ | ||
if constexpr (detail::is_recognized_standard_type<DataT>()) { | ||
__invoke__ImageWrite((uint64_t)imageHandle.raw_handle, coords, color); | ||
__invoke__ImageWrite(CONVERT_HANDLE_TO_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyWrite<coordSize>), | ||
coords, color); | ||
} else { | ||
// Convert DataT to a supported backend write type when user-defined type is | ||
// passed | ||
__invoke__ImageWrite((uint64_t)imageHandle.raw_handle, coords, | ||
detail::convert_color(color)); | ||
__invoke__ImageWrite(CONVERT_HANDLE_TO_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyWrite<coordSize>), | ||
coords, detail::convert_color(color)); | ||
} | ||
#else | ||
assert(false); // Bindless images not yet implemented on host | ||
|
@@ -1354,13 +1442,17 @@ void write_image_array(unsampled_image_handle imageHandle [[maybe_unused]], | |
|
||
#ifdef __SYCL_DEVICE_ONLY__ | ||
if constexpr (detail::is_recognized_standard_type<DataT>()) { | ||
__invoke__ImageArrayWrite(static_cast<uint64_t>(imageHandle.raw_handle), | ||
coords, arrayLayer, color); | ||
__invoke__ImageArrayWrite( | ||
CONVERT_HANDLE_TO_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
coords, arrayLayer, color); | ||
} else { | ||
// Convert DataT to a supported backend write type when user-defined type is | ||
// passed | ||
__invoke__ImageArrayWrite(static_cast<uint64_t>(imageHandle.raw_handle), | ||
coords, arrayLayer, detail::convert_color(color)); | ||
__invoke__ImageArrayWrite( | ||
CONVERT_HANDLE_TO_IMAGE(imageHandle.raw_handle, | ||
OCLImageTyRead<coordSize>), | ||
coords, arrayLayer, detail::convert_color(color)); | ||
} | ||
#else | ||
assert(false); // Bindless images not yet implemented on host. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also update
clang/test/Driver/sycl-spirv-ext.c
to cover your new entry?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I missed that. Will do.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.