Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 177 additions & 0 deletions sycl/include/sycl/detail/properties/property.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
//==---------- property.hpp --- SYCL compile-time property engine ----------==//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// Shared, namespace-neutral core of the "new-style" compile-time property
// engine: the `PropKind` registry and the property key/value base classes that
// property definitions are built on. This lives in `sycl::detail` so that both
// the `sycl::ext::oneapi::experimental` extensions and the `sycl::khr` KHR
// properties layer can define their properties on top of a single registry.
//
// NOTE: This header deliberately contains only the property-*definition*
// infrastructure -- the pieces that appear inside a property type's definition
// but never in a public API's mangled signature. The property list container
// (`properties`), `property_value`, the list traits (`is_property_list`,
// `is_property_value`), and the applicability/customization traits
// (`is_property_key_of`, `PropertyMetaInfo`, ...) remain in the facades
// (see <sycl/ext/oneapi/properties/property.hpp>) so that moving this engine
// does not change any mangled symbol name. See the "HOW-TO" comments in that
// facade header for how to define a new property.
//
//===----------------------------------------------------------------------===//

#pragma once

#include <stdint.h> // for uint32_t
#include <type_traits> // for is_same_v

#include <sycl/detail/defines_elementary.hpp>

namespace sycl {
inline namespace _V1 {
// Forward declaration of the experimental property list container so the
// property key/value base classes can befriend it across namespaces (the
// container accesses the protected `get_property_impl`).
namespace ext::oneapi::experimental {
template <typename> class __SYCL_EBO properties;
} // namespace ext::oneapi::experimental

namespace detail {

// List of all properties.
//
// This is a scoped enumeration so that its enumerators do not leak into the
// enclosing `sycl::detail` namespace, where they would otherwise collide with
// the enumerators of the old-style property enums (DataLessPropKind /
// PropWithDataKind in <sycl/detail/property_helper.hpp>).
enum class PropKind : uint32_t {
DeviceImageScope = 0,
HostAccess = 1,
WorkGroupSize = 2,
WorkGroupSizeHint = 3,
SubGroupSize = 4,
DeviceHas = 5,
Alignment = 6,
CacheConfig = 7,
UseRootSync = 8,
GRFSize = 9,
GRFSizeAutomatic = 10,
ESIMDL1CacheHint = 11,
ESIMDL2CacheHint = 12,
ESIMDL3CacheHint = 13,
UsmKind = 14,
CacheControlReadHint = 15,
CacheControlReadAssertion = 16,
CacheControlWrite = 17,
BuildOptions = 18,
BuildLog = 19,
FloatingPointControls = 20,
DataPlacement = 21,
ContiguousMemory = 22,
FullGroup = 23,
Naive = 24,
WorkGroupProgress = 25,
SubGroupProgress = 26,
WorkItemProgress = 27,
NDRangeKernel = 28,
SingleTaskKernel = 29,
IndirectlyCallable = 30,
CallsIndirectly = 31,
InputDataPlacement = 32,
OutputDataPlacement = 33,
IncludeFiles = 34,
RegisteredNames = 35,
ClusterLaunch = 36,
MaxWorkGroupSize = 37,
MaxLinearWorkGroupSize = 38,
Prefetch = 39,
Deterministic = 40,
InitializeToIdentity = 41,
WorkGroupScratchSize = 42,
Unaliased = 43,
EventMode = 44,
NativeLocalBlockIO = 45,
InitialThreshold = 46,
MaximumSize = 47,
ZeroInit = 48,
FastLink = 49,
EnableIPC = 50,
RegisterHostMemoryReadOnly = 51,
EnableProfiling = 52,
MaximumRegisters = 53,
MaximumRegistersAutomatic = 54,
// PropKindSize must always be the last value.
PropKindSize = 55,
};

template <typename PropertyT> struct PropertyToKind {
static constexpr PropKind Kind = PropertyT::Kind;
};

struct property_tag {};

// This is used to implement has/get_property via inheritance queries.
template <typename property_key_t> struct property_key_tag : property_tag {};

template <typename property_t, PropKind Kind,
typename property_key_t = property_t>
struct property_base : property_key_tag<property_key_t> {
using key_t = property_key_t;

protected:
constexpr property_t get_property_impl(property_key_tag<key_t>) const {
return *static_cast<const property_t *>(this);
}

// For key_t access in error reporting specialization. The property list
// container lives in the experimental facade namespace.
template <typename>
friend class __SYCL_EBO ext::oneapi::experimental::properties;

#if !defined(_MSC_VER)
// Temporary, to ensure new code matches previous behavior and to catch any
// silly copy-paste mistakes. MSVC can't compile it, but linux-only is
// enough for this temporary check.
static_assert([]() constexpr -> bool {
if constexpr (std::is_same_v<property_t, key_t>)
// key_t is incomplete at this point for runtime properties.
return true;
else
return Kind == PropertyToKind<key_t>::Kind;
}());
#endif
};

struct property_key_base_tag {};
struct compile_time_property_key_base_tag : property_key_base_tag {};

template <typename property_t, PropKind Kind_>
struct run_time_property_key : property_key_base_tag,
property_base<property_t, Kind_> {
protected:
static constexpr PropKind Kind = Kind_;

template <typename T> friend struct PropertyToKind;
};

template <PropKind Kind_>
struct compile_time_property_key : compile_time_property_key_base_tag {
protected:
static constexpr PropKind Kind = Kind_;

template <typename T> friend struct PropertyToKind;
};

// Get unique ID for property.
template <typename PropertyT> struct PropertyID {
static constexpr int value =
static_cast<int>(PropertyToKind<PropertyT>::Kind);
};

} // namespace detail
} // namespace _V1
} // namespace sycl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ template <int Dim>
struct cluster_size
: ::sycl::ext::oneapi::experimental::detail::run_time_property_key<
cluster_size<Dim>,
::sycl::ext::oneapi::experimental::detail::ClusterLaunch> {
::sycl::ext::oneapi::experimental::detail::PropKind::ClusterLaunch> {
cluster_size(const range<Dim> &size) : size(size) {}
sycl::range<Dim> get_cluster_size() const { return size; }

Expand Down
155 changes: 23 additions & 132 deletions sycl/include/sycl/ext/oneapi/properties/property.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
//===----------------------------------------------------------------------===//

// HOW-TO: Add new compile-time property
// 1. Add a new enumerator to
// `sycl::ext::oneapi::experimental::detail::PropKind` representing the new
// property. Increment
// `sycl::ext::oneapi::experimental::detail::PropKind::PropKindSize`.
// 1. Add a new enumerator to `sycl::detail::PropKind` representing the new
// property (this is the shared engine registry in
// <sycl/detail/properties/property.hpp>). Increment
// `sycl::detail::PropKind::PropKindSize`.
// 2. Define property key class inherited from
// `detail::compile_time_property_key` with `value_t` that must be
// `property_value` with the first template argument being the property
Expand Down Expand Up @@ -71,9 +71,8 @@ template <> struct PropertyMetaInfo<bar_key::value_t> {
*******************************************************************************/

// HOW-TO: Add new runtime property
// 1. Add a new enumerator to `sycl::ext::oneapi::detail::PropKind`
// representing the new property. Increment
// `sycl::ext::oneapi::experimental::detail::PropKind::PropKindSize`
// 1. Add a new enumerator to `sycl::detail::PropKind` representing the new
// property. Increment `sycl::detail::PropKind::PropKindSize`
// 2. Define property class, inheriting from `detail::run_time_property_key`.
// 3. Declare the property key as an alias to the property class. The name of
// the key class must be the property name suffixed by `_key`, i.e. for a
Expand Down Expand Up @@ -120,10 +119,10 @@ template <> struct is_property_key_of<foo, SYCL_OBJ> : std::true_type {};
#pragma once

#include <cstddef> // for nullptr_t
#include <stdint.h> // for uint32_t
#include <type_traits> // for false_type

#include <sycl/detail/defines_elementary.hpp>
#include <sycl/detail/properties/property.hpp>

namespace sycl {
inline namespace _V1 {
Expand All @@ -140,130 +139,22 @@ inline constexpr bool is_property_list_v = is_property_list<propertiesT>::value;

namespace detail {

// List of all properties.
enum PropKind : uint32_t {
DeviceImageScope = 0,
HostAccess = 1,
WorkGroupSize = 2,
WorkGroupSizeHint = 3,
SubGroupSize = 4,
DeviceHas = 5,
Alignment = 6,
CacheConfig = 7,
UseRootSync = 8,
GRFSize = 9,
GRFSizeAutomatic = 10,
ESIMDL1CacheHint = 11,
ESIMDL2CacheHint = 12,
ESIMDL3CacheHint = 13,
UsmKind = 14,
CacheControlReadHint = 15,
CacheControlReadAssertion = 16,
CacheControlWrite = 17,
BuildOptions = 18,
BuildLog = 19,
FloatingPointControls = 20,
DataPlacement = 21,
ContiguousMemory = 22,
FullGroup = 23,
Naive = 24,
WorkGroupProgress = 25,
SubGroupProgress = 26,
WorkItemProgress = 27,
NDRangeKernel = 28,
SingleTaskKernel = 29,
IndirectlyCallable = 30,
CallsIndirectly = 31,
InputDataPlacement = 32,
OutputDataPlacement = 33,
IncludeFiles = 34,
RegisteredNames = 35,
ClusterLaunch = 36,
MaxWorkGroupSize = 37,
MaxLinearWorkGroupSize = 38,
Prefetch = 39,
Deterministic = 40,
InitializeToIdentity = 41,
WorkGroupScratchSize = 42,
Unaliased = 43,
EventMode = 44,
NativeLocalBlockIO = 45,
InitialThreshold = 46,
MaximumSize = 47,
ZeroInit = 48,
FastLink = 49,
EnableIPC = 50,
RegisterHostMemoryReadOnly = 51,
EnableProfiling = 52,
MaximumRegisters = 53,
MaximumRegistersAutomatic = 54,
// PropKindSize must always be the last value.
PropKindSize = 55,
};

template <typename PropertyT> struct PropertyToKind {
static constexpr PropKind Kind = PropertyT::Kind;
};

struct property_tag {};

// This is used to implement has/get_property via inheritance queries.
template <typename property_key_t> struct property_key_tag : property_tag {};

template <typename property_t, PropKind Kind,
typename property_key_t = property_t>
struct property_base : property_key_tag<property_key_t> {
using key_t = property_key_t;

protected:
constexpr property_t get_property_impl(property_key_tag<key_t>) const {
return *static_cast<const property_t *>(this);
}

// For key_t access in error reporting specialization.
template <typename> friend class __SYCL_EBO properties;

#if !defined(_MSC_VER)
// Temporary, to ensure new code matches previous behavior and to catch any
// silly copy-paste mistakes. MSVC can't compile it, but linux-only is
// enough for this temporary check.
static_assert([]() constexpr -> bool {
if constexpr (std::is_same_v<property_t, key_t>)
// key_t is incomplete at this point for runtime properties.
return true;
else
return Kind == PropertyToKind<key_t>::Kind;
}());
#endif
};

struct property_key_base_tag {};
struct compile_time_property_key_base_tag : property_key_base_tag {};

template <typename property_t, PropKind Kind_>
struct run_time_property_key : property_key_base_tag,
property_base<property_t, Kind_> {
protected:
static constexpr PropKind Kind = Kind_;

template <typename T>
friend struct PropertyToKind;
};

template <PropKind Kind_>
struct compile_time_property_key : compile_time_property_key_base_tag {
protected:
static constexpr PropKind Kind = Kind_;

template <typename T>
friend struct PropertyToKind;
};

// Get unique ID for property.
template <typename PropertyT> struct PropertyID {
static constexpr int value =
static_cast<int>(PropertyToKind<PropertyT>::Kind);
};
// The property-definition infrastructure has been promoted to the shared engine
// in <sycl/detail/properties/property.hpp> so it can be reused by the KHR
// properties layer. Re-export exactly those names here (rather than a blanket
// `using namespace sycl::detail;`) so existing experimental code that refers to
// them via `experimental::detail::...` keeps working, without pulling the rest
// of `sycl::detail` into this namespace's lookup.
using sycl::detail::compile_time_property_key;
using sycl::detail::compile_time_property_key_base_tag;
using sycl::detail::property_base;
using sycl::detail::property_key_base_tag;
using sycl::detail::property_key_tag;
using sycl::detail::property_tag;
using sycl::detail::PropertyID;
using sycl::detail::PropertyToKind;
using sycl::detail::PropKind;
using sycl::detail::run_time_property_key;

// Trait for property compile-time meta names and values.
template <typename PropertyT> struct PropertyMetaInfo {
Expand Down
8 changes: 6 additions & 2 deletions sycl/include/sycl/ext/oneapi/properties/property_value.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,18 @@ template <typename V, typename O> struct is_property_value_of {
}();
};

} // namespace ext::oneapi::experimental

// PropertyID's primary lives in the shared engine (`sycl::detail`), so this
// specialization for property_value must be declared there.
namespace detail {

// Specialization of PropertyID for propagating IDs through property_value.
template <typename PropertyT, typename... PropertyValueTs>
struct PropertyID<property_value<PropertyT, PropertyValueTs...>>
struct PropertyID<
ext::oneapi::experimental::property_value<PropertyT, PropertyValueTs...>>
: PropertyID<PropertyT> {};

} // namespace detail
} // namespace ext::oneapi::experimental
} // namespace _V1
} // namespace sycl
Loading
Loading