#ifndef XPU_SYCL_MEMORY_STORAGE_HELPER_HPP
#define XPU_SYCL_MEMORY_STORAGE_HELPER_HPP
#include <optional>
#include "xpu/sycl/memory_storage.hpp"
#ifdef DNNL_SYCL_CUDA
#include "gpu/nvidia/sycl_cuda_compat.hpp"
#endif
#ifdef DNNL_SYCL_HIP
#include "gpu/amd/sycl_hip_compat.hpp"
#endif
namespace dnnl {
namespace impl {
namespace xpu {
namespace sycl {
#define CTX_IN_SYCL_MEMORY(arg) \
dnnl::impl::xpu::sycl::interop_memory_arg_t<::sycl::access::mode::read>( \
&CTX_IN_STORAGE(arg), cgh)
#define CTX_OUT_SYCL_MEMORY(arg) \
dnnl::impl::xpu::sycl::interop_memory_arg_t<::sycl::access::mode::write>( \
&CTX_OUT_STORAGE(arg), cgh)
#define CTX_SCRATCH_SYCL_MEMORY(arg) \
dnnl::impl::xpu::sycl::interop_memory_arg_t< \
::sycl::access::mode::read_write>( \
ctx.get_scratchpad_grantor().get_memory_storage(arg).get(), cgh)
template <::sycl::access_mode mode>
class interop_memory_arg_t {
#if defined(DNNL_SYCL_CUDA)
static constexpr auto be = ::sycl::backend::ext_oneapi_cuda;
#elif defined(DNNL_SYCL_HIP)
static constexpr auto be = ::sycl::backend::ext_oneapi_hip;
#else
static_assert(false,
"This file is not expected to be used for Intel GPU vendor.");
#endif
public:
interop_memory_arg_t() = default;
interop_memory_arg_t(memory_storage_t *raw_mem, ::sycl::handler &cgh) {
if (!raw_mem || raw_mem->is_null()) { return; }
auto *mem = static_cast<memory_storage_base_t *>(raw_mem);
dim_t offset = mem->offset();
switch (mem->memory_kind()) {
case sycl::memory_kind::buffer: {
auto *buffer_storage
= utils::downcast<buffer_memory_storage_t *>(mem);
acc_.emplace(buffer_storage->buffer(), cgh);
offset_ = buffer_storage->base_offset() + offset;
break;
}
case sycl::memory_kind::usm: {
raw_ptr_ = utils::downcast<const usm_memory_storage_t *>(mem)
->usm_ptr();
offset_ = offset;
break;
}
default: assert(!"unexpected memory kind");
}
}
interop_memory_arg_t(::sycl::buffer<uint8_t> buf, ::sycl::handler &cgh,
size_t offset = 0)
: offset_ {offset} {
acc_.emplace(buf, cgh);
}
interop_memory_arg_t(uint8_t *usm_ptr, size_t offset = 0)
: offset_ {offset} {
raw_ptr_ = usm_ptr;
}
template <typename T = void>
T *get_native_pointer(
#ifdef DNNL_SYCL_CUDA
const gpu::nvidia::compat::interop_handle
#endif
#ifdef DNNL_SYCL_HIP
const gpu::amd::compat::interop_handle
#endif
&ih) const {
void *raw_ptr = nullptr;
if (acc_.has_value()) {
raw_ptr = reinterpret_cast<T *>(
reinterpret_cast<uint8_t *>(
ih.get_native_mem<be>(acc_.value()))
+ offset_);
} else {
raw_ptr = reinterpret_cast<T *>(
reinterpret_cast<uint8_t *>(raw_ptr_) + offset_);
}
return reinterpret_cast<T *>(raw_ptr);
}
bool empty() const { return !raw_ptr_ && !acc_.has_value(); }
private:
void *raw_ptr_ = nullptr;
std::optional<::sycl::accessor<uint8_t, 1, mode>> acc_;
size_t offset_ = 0;
};
} } } }
#endif