diff --git a/sycl/CMakeLists.txt b/sycl/CMakeLists.txt index d540c23ea0a64..d03e65223ac12 100644 --- a/sycl/CMakeLists.txt +++ b/sycl/CMakeLists.txt @@ -14,7 +14,7 @@ include(AddSYCLExecutable) set(SYCL_MAJOR_VERSION 2) set(SYCL_MINOR_VERSION 1) set(SYCL_PATCH_VERSION 0) -set(SYCL_DEV_ABI_VERSION 3) +set(SYCL_DEV_ABI_VERSION 4) if (SYCL_ADD_DEV_VERSION_POSTFIX) set(SYCL_VERSION_POSTFIX "-${SYCL_DEV_ABI_VERSION}") endif() diff --git a/sycl/include/CL/sycl.hpp b/sycl/include/CL/sycl.hpp index 4fd3c55b0952c..2285f9ac63348 100644 --- a/sycl/include/CL/sycl.hpp +++ b/sycl/include/CL/sycl.hpp @@ -37,6 +37,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include diff --git a/sycl/include/CL/sycl/accessor.hpp b/sycl/include/CL/sycl/accessor.hpp index 18084a8a2d2b2..8631cee6ab640 100755 --- a/sycl/include/CL/sycl/accessor.hpp +++ b/sycl/include/CL/sycl/accessor.hpp @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include /// \file accessor.hpp diff --git a/sycl/include/CL/sycl/detail/property_helper.hpp b/sycl/include/CL/sycl/detail/property_helper.hpp new file mode 100644 index 0000000000000..3c8a82bc00117 --- /dev/null +++ b/sycl/include/CL/sycl/detail/property_helper.hpp @@ -0,0 +1,83 @@ +//==--------- property_helper.hpp --- SYCL property helper -----------------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include + +__SYCL_INLINE_NAMESPACE(cl) { +namespace sycl { + +namespace detail { + +// All properties are split here to dataless properties and properties with +// data. A dataless property is one which has no data stored in it. A property +// with data is one which has data stored in it and usually provides and access +// to it. For dataless property we just store a bool which indicates if a +// property is set or not. For properties with data we store a pointer to the +// base class because we do not know the size of such properties beforehand. + +// List of all dataless properties' IDs +enum DataLessPropKind { + BufferUseHostPtr = 0, + ImageUseHostPtr, + QueueEnableProfiling, + InOrder, + NoInit, + BufferUsePinnedHostMemory, + UsePrimaryContext, + DataLessPropKindSize +}; + +// List of all properties with data IDs +enum PropWithDataKind { + BufferUseMutex = 0, + BufferContextBound, + ImageUseMutex, + ImageContextBound, + PropWithDataKindSize +}; + +// Base class for dataless properties, needed to check that the type of an +// object passed to the property_list is a property. +class DataLessPropertyBase {}; + +// Helper class for the dataless properties. Every such property is supposed +// to inherit from it. The ID template parameter should be one from +// DataLessPropKind. +template class DataLessProperty : DataLessPropertyBase { +public: + static constexpr int getKind() { return ID; } +}; + +// Base class for properties with data, needed to check that the type of an +// object passed to the property_list is a property and for checking if two +// properties with data are of the same type. +class PropertyWithDataBase { +public: + PropertyWithDataBase(int ID) : MID(ID) {} + bool isSame(int ID) const { return ID == MID; } + virtual ~PropertyWithDataBase() = default; + +private: + int MID = -1; +}; + +// Helper class for the properties with data. Every such property is supposed +// to inherit from it. The ID template parameter should be one from +// PropWithDataKind. +template class PropertyWithData : public PropertyWithDataBase { +public: + PropertyWithData() : PropertyWithDataBase(ID) {} + static int getKind() { return ID; } +}; + +} // namespace detail + +} // namespace sycl +} // __SYCL_INLINE_NAMESPACE(cl) diff --git a/sycl/include/CL/sycl/detail/sycl_mem_obj_t.hpp b/sycl/include/CL/sycl/detail/sycl_mem_obj_t.hpp index 1ab0002cb6d7c..ad795d69806b5 100644 --- a/sycl/include/CL/sycl/detail/sycl_mem_obj_t.hpp +++ b/sycl/include/CL/sycl/detail/sycl_mem_obj_t.hpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include diff --git a/sycl/include/CL/sycl/properties/accessor_properties.hpp b/sycl/include/CL/sycl/properties/accessor_properties.hpp new file mode 100644 index 0000000000000..2aea424846ee6 --- /dev/null +++ b/sycl/include/CL/sycl/properties/accessor_properties.hpp @@ -0,0 +1,37 @@ +//==----------- accessor_properties.hpp --- SYCL accessor properties -------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include +#include + +__SYCL_INLINE_NAMESPACE(cl) { +namespace sycl { +namespace property { + +class noinit : public detail::DataLessProperty {}; + +} // namespace property + +#if __cplusplus > 201402L + +inline constexpr property::noinit noinit; + +#else + +namespace { + +constexpr const auto &noinit = + sycl::detail::InlineVariableHelper::value; +} + +#endif + +} // namespace sycl +} // __SYCL_INLINE_NAMESPACE(cl) diff --git a/sycl/include/CL/sycl/properties/buffer_properties.hpp b/sycl/include/CL/sycl/properties/buffer_properties.hpp new file mode 100644 index 0000000000000..fe83402485d21 --- /dev/null +++ b/sycl/include/CL/sycl/properties/buffer_properties.hpp @@ -0,0 +1,57 @@ +//==----------- buffer_properties.hpp --- SYCL buffer properties -----------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include +#include + +__SYCL_INLINE_NAMESPACE(cl) { +namespace sycl { + +namespace property { +namespace buffer { +class use_host_ptr : public detail::DataLessProperty { +}; + +class use_mutex : public detail::PropertyWithData { +public: + use_mutex(sycl::mutex_class &MutexRef) : MMutex(MutexRef) {} + + sycl::mutex_class *get_mutex_ptr() const { return &MMutex; } + +private: + sycl::mutex_class &MMutex; +}; + +class context_bound + : public detail::PropertyWithData { +public: + context_bound(sycl::context BoundContext) : MCtx(std::move(BoundContext)) {} + + context get_context() const { return MCtx; } + +private: + sycl::context MCtx; +}; +} // namespace buffer +} // namespace property + +namespace ext { +namespace oneapi { +namespace property { +namespace buffer { + +class use_pinned_host_memory + : public detail::DataLessProperty {}; +} // namespace buffer +} // namespace property +} // namespace oneapi +} // namespace ext +} // namespace sycl +} // __SYCL_INLINE_NAMESPACE(cl) diff --git a/sycl/include/CL/sycl/properties/context_properties.hpp b/sycl/include/CL/sycl/properties/context_properties.hpp new file mode 100644 index 0000000000000..49ec19890c439 --- /dev/null +++ b/sycl/include/CL/sycl/properties/context_properties.hpp @@ -0,0 +1,25 @@ +//==----------- context_properties.hpp --- SYCL context properties ---------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include +#include + +__SYCL_INLINE_NAMESPACE(cl) { +namespace sycl { +namespace property { +namespace context { +namespace cuda { +class use_primary_context + : public detail::DataLessProperty {}; +} // namespace cuda +} // namespace context +} // namespace property +} // namespace sycl +} // __SYCL_INLINE_NAMESPACE(cl) diff --git a/sycl/include/CL/sycl/properties/image_properties.hpp b/sycl/include/CL/sycl/properties/image_properties.hpp new file mode 100644 index 0000000000000..ebb7e5d2a2972 --- /dev/null +++ b/sycl/include/CL/sycl/properties/image_properties.hpp @@ -0,0 +1,44 @@ +//==----------- image_properties.hpp --- SYCL image properties -------------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include +#include + +__SYCL_INLINE_NAMESPACE(cl) { +namespace sycl { +namespace property { +namespace image { +class use_host_ptr : public detail::DataLessProperty { +}; + +class use_mutex : public detail::PropertyWithData { +public: + use_mutex(sycl::mutex_class &MutexRef) : MMutex(MutexRef) {} + + sycl::mutex_class *get_mutex_ptr() const { return &MMutex; } + +private: + sycl::mutex_class &MMutex; +}; + +class context_bound + : public detail::PropertyWithData { +public: + context_bound(sycl::context BoundContext) : MCtx(std::move(BoundContext)) {} + + context get_context() const { return MCtx; } + +private: + sycl::context MCtx; +}; +} // namespace image +} // namespace property +} // namespace sycl +} // __SYCL_INLINE_NAMESPACE(cl) diff --git a/sycl/include/CL/sycl/properties/queue_properties.hpp b/sycl/include/CL/sycl/properties/queue_properties.hpp new file mode 100644 index 0000000000000..6d596fcf6a67c --- /dev/null +++ b/sycl/include/CL/sycl/properties/queue_properties.hpp @@ -0,0 +1,23 @@ +//==----------- queue_properties.hpp --- SYCL queue properties -------------==// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include + +__SYCL_INLINE_NAMESPACE(cl) { +namespace sycl { +namespace property { +namespace queue { +class in_order : public detail::DataLessProperty {}; +class enable_profiling + : public detail::DataLessProperty {}; +} // namespace queue +} // namespace property +} // namespace sycl +} // __SYCL_INLINE_NAMESPACE(cl) diff --git a/sycl/include/CL/sycl/property_list.hpp b/sycl/include/CL/sycl/property_list.hpp index b727bf05671c2..5edaa636692f6 100644 --- a/sycl/include/CL/sycl/property_list.hpp +++ b/sycl/include/CL/sycl/property_list.hpp @@ -8,332 +8,123 @@ #pragma once -#include #include -#include +#include + +#include +#include #include -#include +#include __SYCL_INLINE_NAMESPACE(cl) { namespace sycl { -// HOW TO ADD NEW PROPERTY INSTRUCTION: -// 1. Add forward declaration of property class. -// 2. Add new record in PropKind enum. -// 3. Use RegisterProp macro passing new record from enum and new class. -// 4. Add implementation of the new property class using detail::Prop class with -// template parameter = new record in enum as a base class. - -namespace property { - -namespace image { -class use_host_ptr; -class use_mutex; -class context_bound; -} // namespace image - -namespace buffer { -class use_host_ptr; -class use_mutex; -class context_bound; -} // namespace buffer - -namespace queue { -class enable_profiling; -class in_order; -} // namespace queue - -class noinit; - -namespace detail { - -// Will be aliased in the sycl::ext::oneapi::property namespace -namespace buffer_ { -class use_pinned_host_memory; -} - -// List of all properties' IDs. -enum PropKind { - // Buffer properties - BufferUseHostPtr = 0, - BufferContextBound, - BufferUseMutex, - - // Image properties - ImageUseHostPtr, - ImageContextBound, - ImageUseMutex, - - // Queue properties - QueueEnableProfiling, - InOrder, - - // Accessor - NoInit, - - BufferUsePinnedHostMemory, - - PropKindSize -}; - -// Base class for all properties. Needed to check that user passed only -// SYCL's properties to property_list c'tor. -class PropBase {}; +/// Objects of the property_list class are containers for the SYCL properties +/// +/// \ingroup sycl_api +class property_list { -// Second base class, needed for mapping PropKind to class and vice versa. -template class Prop; + // The structs validate that all objects passed are SYCL properties + template struct AllProperties : std::true_type {}; + template + struct AllProperties + : std::conditional< + std::is_base_of::value || + std::is_base_of::value, + AllProperties, std::false_type>::type {}; -// This class is used in property_list to hold properties. -template class PropertyHolder { public: - PropertyHolder() = default; - - PropertyHolder(const PropertyHolder &P) { - if (P.isInitialized()) { - new (m_Mem) T(P.getProp()); - m_Initialized = true; - } - } - - ~PropertyHolder() { - if (m_Initialized) { - T *MemPtr = reinterpret_cast(m_Mem); - MemPtr->~T(); - } + template ::value>::type> + property_list(PropsT... Props) : MDataLessProps(false) { + ctorHelper(Props...); } - PropertyHolder &operator=(const PropertyHolder &Other) { - if (this != &Other) { - if (m_Initialized) { - T *MemPtr = reinterpret_cast(m_Mem); - MemPtr->~T(); - m_Initialized = false; - } - - if (Other.m_Initialized) { - new (m_Mem) T(Other.getProp()); - m_Initialized = true; - } - } - return *this; - } + template PropT get_property() const { + if (!has_property()) + throw sycl::invalid_object_error("The property is not found", + PI_INVALID_VALUE); - void setProp(const T &Rhs) { - new (m_Mem) T(Rhs); - m_Initialized = true; + return get_property_helper(); } - const T &getProp() const { - assert(true == m_Initialized && "Property was not set!"); - const T *MemPtr = reinterpret_cast(m_Mem); - return *MemPtr; + template bool has_property() const { + return has_property_helper(); } - bool isInitialized() const { return m_Initialized; } private: - // Memory that is used for property allocation - alignas(T) unsigned char m_Mem[sizeof(T)]; - // Indicate whether property initialized or not. - bool m_Initialized = false; -}; + void ctorHelper() {} -// This macro adds specialization of class Prop which provides possibility to -// convert PropKind to class and vice versa. -#define RegisterProp(PropKindT, Type) \ - template <> class Prop : public PropBase { \ - public: \ - static constexpr PropKind getKind() { return PropKindT; } \ - using FinalType = Type; \ + template + typename std::enable_if< + std::is_base_of::value>::type + ctorHelper(PropT &, PropsT... Props) { + const int PropKind = static_cast(PropT::getKind()); + MDataLessProps[PropKind] = true; + ctorHelper(Props...); } -// Image -RegisterProp(PropKind::ImageUseHostPtr, image::use_host_ptr); -RegisterProp(PropKind::ImageUseMutex, image::use_mutex); -RegisterProp(PropKind::ImageContextBound, image::context_bound); - -// Buffer -RegisterProp(PropKind::BufferUseHostPtr, buffer::use_host_ptr); -RegisterProp(PropKind::BufferUseMutex, buffer::use_mutex); -RegisterProp(PropKind::BufferContextBound, buffer::context_bound); -RegisterProp(PropKind::BufferUsePinnedHostMemory, - buffer_::use_pinned_host_memory); - -// Queue -RegisterProp(PropKind::QueueEnableProfiling, queue::enable_profiling); -RegisterProp(PropKind::InOrder, queue::in_order); - -// Accessor -RegisterProp(PropKind::NoInit, noinit); - -// Sentinel, needed for automatic build of tuple in property_list. -RegisterProp(PropKind::PropKindSize, PropBase); - -// Common class for use_mutex in buffer and image namespaces. -template class UseMutexBase : public Prop { -public: - UseMutexBase(mutex_class &MutexRef) : m_MutexClass(MutexRef) {} - mutex_class *get_mutex_ptr() const { return &m_MutexClass; } - -private: - mutex_class &m_MutexClass; -}; - -// Common class for context_bound in buffer and image namespaces. -template class ContextBoundBase : public Prop { -public: - ContextBoundBase(cl::sycl::context Context) : m_Context(Context) {} - context get_context() const { return m_Context; } - -private: - cl::sycl::context m_Context; -}; -} // namespace detail - -namespace image { - -class use_host_ptr : public detail::Prop {}; - -class use_mutex : public detail::UseMutexBase { -public: - use_mutex(mutex_class &MutexRef) : UseMutexBase(MutexRef) {} -}; - -class context_bound - : public detail::ContextBoundBase { -public: - context_bound(cl::sycl::context Context) : ContextBoundBase(Context) {} -}; - -} // namespace image - -namespace buffer { - -class use_host_ptr : public detail::Prop {}; - -class use_mutex - : public detail::UseMutexBase { -public: - use_mutex(mutex_class &MutexRef) : UseMutexBase(MutexRef) {} -}; - -class context_bound - : public detail::ContextBoundBase { -public: - context_bound(cl::sycl::context Context) : ContextBoundBase(Context) {} -}; - -} // namespace buffer - -namespace detail { -namespace buffer_ { -class use_pinned_host_memory - : public detail::Prop {}; -} // namespace buffer_ -} // namespace detail - -namespace queue { -class enable_profiling - : public detail::Prop {}; - -class in_order : public detail::Prop {}; -} // namespace queue - -class noinit : public detail::Prop {}; - -} // namespace property - -namespace ext { -namespace oneapi { -namespace property { -namespace buffer { -using use_pinned_host_memory = - sycl::property::detail::buffer_::use_pinned_host_memory; -} // namespace buffer -} // namespace property -} // namespace oneapi -} // namespace ext - -#if __cplusplus > 201402L - -inline constexpr property::noinit noinit; - -#else - -namespace { - -constexpr const auto &noinit = - sycl::detail::InlineVariableHelper::value; - -} - -#endif - -class property_list { - - // The structs validate that all objects passed are base of PropBase class. - template struct AllProperties : std::true_type {}; - template - struct AllProperties - : std::conditional::value, - AllProperties, std::false_type>::type {}; - - template - using PropertyHolder = cl::sycl::property::detail::PropertyHolder; - template - using Property = cl::sycl::property::detail::Prop; - - // The structs build tuple type that can hold all properties. - template struct DefineTupleType { - using Type = std::tuple; - }; - - template - struct BuildTupleType - : public std::conditional< - (Counter < property::detail::PropKind::PropKindSize), - BuildTupleType< - Counter + 1, Head..., - PropertyHolder::FinalType>>, - DefineTupleType>::type {}; - -public: - // C'tor initialize m_PropList with properties passed by invoking ctorHelper - // recursively - template ::value>::type> - property_list(propertyTN... Props) { + template + typename std::enable_if< + std::is_base_of::value>::type + ctorHelper(PropT &Prop, PropsT... Props) { + MPropsWithData.emplace_back(new PropT(Prop)); ctorHelper(Props...); } - template propertyT get_property() const { - if (!has_property()) { - throw sycl::invalid_object_error(); - } - const auto &PropHolder = - std::get(propertyT::getKind())>(m_PropsList); - return PropHolder.getProp(); + template + typename std::enable_if< + std::is_base_of::value, bool>::type + has_property_helper() const { + const int PropKind = static_cast(PropT::getKind()); + if (PropKind >= detail::DataLessPropKind::DataLessPropKindSize) + return false; + return MDataLessProps[PropKind]; } - template bool has_property() const { - if (static_cast(propertyT::getKind()) > - property::detail::PropKind::PropKindSize) - return false; - return std::get<(int)(propertyT::getKind())>(m_PropsList).isInitialized(); + template + typename std::enable_if< + std::is_base_of::value, bool>::type + has_property_helper() const { + const int PropKind = static_cast(PropT::getKind()); + for (const std::shared_ptr &Prop : + MPropsWithData) + if (Prop->isSame(PropKind)) + return true; + return false; } -private: - void ctorHelper() {} + template + typename std::enable_if< + std::is_base_of::value, PropT>::type + get_property_helper() const { + // In case of simple property we can just construct it + return PropT{}; + } - template - void ctorHelper(PropT &Prop, propertyTN... props) { - std::get(PropT::getKind())>(m_PropsList).setProp(Prop); - ctorHelper(props...); + template + typename std::enable_if< + std::is_base_of::value, PropT>::type + get_property_helper() const { + const int PropKind = static_cast(PropT::getKind()); + if (PropKind >= detail::PropWithDataKind::PropWithDataKindSize) + throw sycl::invalid_object_error("The property is not found", + PI_INVALID_VALUE); + + for (const std::shared_ptr &Prop : + MPropsWithData) + if (Prop->isSame(PropKind)) + return *static_cast(Prop.get()); + + throw sycl::invalid_object_error("The property is not found", + PI_INVALID_VALUE); } - // Tuple that able to hold all the properties. - BuildTupleType<0>::Type m_PropsList; +private: + // Stores enable/not enabled for simple properties + std::bitset MDataLessProps; + // Stores shared_ptrs to complex properties + std::vector> MPropsWithData; }; } // namespace sycl diff --git a/sycl/source/detail/queue_impl.hpp b/sycl/source/detail/queue_impl.hpp index 5cdcf8c3ee1f8..f3600318cac1b 100644 --- a/sycl/source/detail/queue_impl.hpp +++ b/sycl/source/detail/queue_impl.hpp @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/sycl/test/abi/symbol_size.cpp b/sycl/test/abi/symbol_size.cpp index 40270190afc4f..b6ae3965eda61 100644 --- a/sycl/test/abi/symbol_size.cpp +++ b/sycl/test/abi/symbol_size.cpp @@ -54,12 +54,12 @@ int main() { check_size(); #ifdef _MSC_VER check_size(); - check_size(); - check_size, 344>(); + check_size(); + check_size, 272>(); #else check_size(); - check_size(); - check_size, 312>(); + check_size(); + check_size, 240>(); #endif check_size, 16>(); check_size();