#pragma once #include "common.hpp" #include namespace kel { namespace lbm { namespace encode { template struct Sycl { }; } /* namespace impl { template struct struct_has_only_equal_dimension_array{}; } */ } } namespace saw { template class data, kel::lbm::encode::Sycl> final { public: using Schema = schema::FixedArray; private: acpp::sycl::queue* q_; data* values_; SAW_FORBID_COPY(data); public: data(acpp::sycl::queue& q__): q_{&q__}, values_{nullptr} { values_ = acpp::sycl::malloc>(ct_multiply::value,q_); } ~data(){ if(not values_){ return; } acpp::sycl::free(values_,q_); } static constexpr data> get_dims() { return {std::array{Dims...}}; } data& at(data>& index){ return values_[kel::lbm::flatten_index::apply(index,get_dims()).get()]; } constexpr data* flat_data() { return values_; } }; template class data,kel::lbm::encode::Sycl> final { public: using Schema = kel::lbm::sch::Chunk; private: using InnerSchema = typename Schema::InnerSchema; using ValueSchema = typename InnerSchema::ValueType; data> values_; public: data(acpp::sycl::queue& q__): values_{q__} {} data>& ghost_at(const data>& index){ return values_.at(index); } const data>& ghost_at(const data>& index) const { return values_.at(index); } static constexpr auto get_ghost_dims() { return data>::get_dims(); } data>& at(const data>& index){ std::decay_t ind; for(uint64_t i = 0u; i < sizeof...(Sides); ++i){ ind.at({i}) = index.at({i}) + Ghost; } return values_.at(ind); } const data>& at(const data>& index) const { std::decay_t ind; for(uint64_t i = 0u; i < sizeof...(Sides); ++i){ ind.at({i}) = index.at({i}) + Ghost; } return values_.at(ind); } static constexpr auto get_dims(){ return data,kel::lbm::encode::Sycl>{{Sides...}}; } auto flat_data(){ return values_.flat_data(); } static constexpr auto flat_size() { return data>::flat_size(); } }; template class data, Keys>...>, kel::lbm::encode::Sycl > final { public: static constexpr data> meta = {{Meta...}}; using StorageT = std::tuple,kel::lbm::encode::Sycl>...>; using Schema = schema::Struct, Keys>...>; private: /** * @todo Check by static assert that the members all have the same dimensions. Alternatively * Do it here by specializing. */ StorageT members_; public: data(acpp::sycl::queue& q__): members_{{data,kel::lbm::encode::Sycl>{q__}...}} {} template auto& get(){ return std::get::value>(members_); } }; } namespace kel { namespace lbm { namespace impl { template struct sycl_malloc_struct_helper; template struct sycl_malloc_struct_helper, Encode> final { using Schema = sch::Struct; template static saw::error_or allocate_on_device_member(typename saw::data>::StorageT& storage, sycl::queue& q){ if constexpr (i < sizeof...(Members)){ using M = typename saw::parameter_pack_type::type; auto& ptr = std::get(storage); ptr = sycl::malloc_device(1u,q); return allocate_on_device_member(storage,q); } return saw::make_void(); } static saw::error_or allocate_on_device(saw::data>& sycl_data, sycl::queue& q){ typename saw::data>::StorageT storage; auto eov = allocate_on_device_member<0u>(storage,q); sycl_data = {storage, q}; return eov; } }; template struct sycl_copy_helper; template struct sycl_copy_helper, Encode> final { using Schema = sch::Struct; template static saw::error_or copy_to_device_member(saw::data& host_data, saw::data>& sycl_data, sycl::queue& q){ if constexpr (i < sizeof...(Members)){ using M = typename saw::parameter_pack_type::type; auto& host_member_data = host_data.template get(); auto& sycl_member_data = sycl_data.template get(); auto host_ptr = host_member_data.flat_data(); auto sycl_ptr = sycl_member_data.flat_data(); q.memcpy(host_ptr, sycl_ptr, sizeof(std::decay_t) * host_member_data.flat_size() ); return copy_to_device_member(host_data,sycl_data,q); } return saw::make_void(); } static saw::error_or copy_to_device(saw::data& host_data, saw::data>& sycl_data, sycl::queue& q){ return copy_to_device_member<0u>(host_data, sycl_data, q); } template static saw::error_or copy_to_host_member(saw::data>& sycl_data, saw::data& host_data, sycl::queue& q){ if constexpr (i < sizeof...(Members)){ using M = typename saw::parameter_pack_type::type; auto& host_member_data = host_data.template get(); auto& sycl_member_data = sycl_data.template get(); auto host_ptr = host_member_data.flat_data(); auto sycl_ptr = sycl_member_data.flat_data(); q.memcpy(sycl_ptr, host_ptr, sizeof(std::decay_t) * host_member_data.flat_size() ); return copy_to_host_member(sycl_data,host_data,q); } return saw::make_void(); } static saw::error_or copy_to_host(saw::data& sycl_data, saw::data>& host_data, sycl::queue& q){ return copy_to_host_member<0u>(sycl_data, host_data, q); } }; } class device final { private: sycl::queue q_; SAW_FORBID_COPY(device); SAW_FORBID_MOVE(device); public: device() = default; ~device() = default; template saw::error_or allocate_on_device(saw::data>& sycl_data){ auto eov = impl::sycl_malloc_struct_helper::allocate_on_device(sycl_data, q_); if(eov.is_error()){ return eov; } return saw::make_void(); } template saw::error_or copy_to_device(saw::data& host_data, saw::data>& sycl_data){ return impl::sycl_copy_helper::copy_to_device(host_data, sycl_data, q_); } template saw::error_or copy_to_host(saw::data>& sycl_data, saw::data& host_data){ return impl::sycl_copy_helper::copy_to_host(sycl_data, host_data, q_); } auto& get_handle(){ return q_; } }; } }