From 7400cb22f7dd9e08715867a962cdbd5dc1ffe8cc Mon Sep 17 00:00:00 2001 From: Konstantinos Parasyris Date: Wed, 9 Sep 2026 16:20:32 -0700 Subject: [PATCH 1/4] [SYCL] Fix sycl::khr::detail shadowing sycl::detail khr/properties.hpp defined its internals in sycl::khr::detail. Because sibling headers under namespace sycl::khr (e.g. free_function_commands.hpp) use bare detail::Foo intending sycl::detail::Foo, unqualified lookup finds sycl::khr::detail first and fails -- so under __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS did not compile. Move the property-definition infrastructure to sycl::khr::property::detail so no sycl::khr::detail exists. Also fix is_property to exclude the properties list itself (it privately inherits its properties, so is_base_of would report it as a property and is_property_for would probe an ambiguous __detail_key_t). Add a regression test that includes with the unfinished KHR extensions enabled. --- sycl/include/sycl/khr/properties.hpp | 52 +++++++++++++------ .../extensions/khr_properties/properties.cpp | 2 +- .../khr_properties/properties_layout.cpp | 2 +- .../khr_properties/properties_negative.cpp | 2 +- .../khr/include_sycl_with_unfinished_khr.cpp | 9 ++++ 5 files changed, 47 insertions(+), 20 deletions(-) create mode 100644 sycl/test/khr/include_sycl_with_unfinished_khr.cpp diff --git a/sycl/include/sycl/khr/properties.hpp b/sycl/include/sycl/khr/properties.hpp index 0287efde9c583..fb3d35f07c1c5 100644 --- a/sycl/include/sycl/khr/properties.hpp +++ b/sycl/include/sycl/khr/properties.hpp @@ -38,6 +38,11 @@ namespace khr { template class __SYCL_EBO properties; +// The property-definition infrastructure lives in `sycl::khr::property::detail` +// (not `sycl::khr::detail`) so it does not shadow `sycl::detail` for +// unqualified `detail::` lookups in sibling headers under `namespace +// sycl::khr`. +namespace property { namespace detail { //===----------------------------------------------------------------------===// @@ -77,13 +82,14 @@ inline constexpr bool __detail_has_runtime_value = // Base for a runtime property key (all of the property's values are supplied at // runtime). Usage: -// struct my_key : detail::runtime_property_key {}; -// struct my_prop : detail::runtime_property { int value; ... }; +// struct my_key : property::detail::runtime_property_key {}; +// struct my_prop : property::detail::runtime_property { int value; +// ... }; struct runtime_property_key : property_key_tag {}; template struct runtime_property : property_base {}; // Base for a compile-time property key with a single non-type value. Usage: -// struct my_key : detail::constant_value_property_key {}; +// struct my_key : property::detail::constant_value_property_key {}; // template // inline constexpr my_key::__detail_property_t my_prop; struct constant_value_property_key : compile_time_property_key_tag { @@ -94,7 +100,7 @@ struct constant_value_property_key : compile_time_property_key_tag { }; // Base for a compile-time property key with a single type value. Usage: -// struct my_key : detail::constant_type_property_key {}; +// struct my_key : property::detail::constant_type_property_key {}; // template // inline constexpr my_key::__detail_property_t my_prop; struct constant_type_property_key : compile_time_property_key_tag { @@ -107,8 +113,9 @@ struct constant_type_property_key : compile_time_property_key_tag { // Base for a hybrid property key (some values compile-time, some runtime). The // key is a runtime key (the property carries runtime data and is stored). // Usage: -// struct my_key : detail::hybrid_property_key {}; -// template struct my_prop : detail::hybrid_property { +// struct my_key : property::detail::hybrid_property_key {}; +// template struct my_prop : property::detail::hybrid_property +// { // static constexpr int x = X; int y; constexpr my_prop(int y):y{y}{} }; struct hybrid_property_key : property_key_tag {}; template struct hybrid_property : property_base {}; @@ -162,25 +169,36 @@ struct build_storage, P, Rest...> template using storage_for = typename build_storage, All...>::type; +// True if T is a khr::properties list. Used to exclude the list itself from +// is_property (the list privately inherits its properties, so is_base_of would +// otherwise report it as a property). +template struct is_properties_list : std::false_type {}; +template +struct is_properties_list> : std::true_type {}; + } // namespace detail +} // namespace property //===----------------------------------------------------------------------===// // Property traits //===----------------------------------------------------------------------===// template -struct is_property : std::is_base_of {}; +struct is_property + : std::bool_constant && + !property::detail::is_properties_list::value> {}; template inline constexpr bool is_property_v = is_property::value; template -struct is_property_key : std::is_base_of {}; +struct is_property_key + : std::is_base_of {}; template inline constexpr bool is_property_key_v = is_property_key::value; template struct is_property_key_compile_time - : std::is_base_of {}; + : std::is_base_of {}; template inline constexpr bool is_property_key_compile_time_v = is_property_key_compile_time::value; @@ -219,8 +237,8 @@ inline constexpr bool is_property_list_for_v = template class __SYCL_EBO properties - : private detail::storage_for { - using storage_t = detail::storage_for; + : private property::detail::storage_for { + using storage_t = property::detail::storage_for; static_assert((is_property_v && ...), "Template arguments of khr::properties must be properties."); @@ -251,18 +269,18 @@ class __SYCL_EBO properties template static constexpr auto get_property() -> std::enable_if_t< is_property_key_compile_time_v, - detail::property_of_key_t> { - return detail::property_of_key_t{}; + property::detail::property_of_key_t> { + return property::detail::property_of_key_t{}; } // Runtime (or hybrid) key: return a copy of the stored property. template constexpr auto get_property() const -> std::enable_if_t< !is_property_key_compile_time_v, - detail::property_of_key_t> { - return static_cast< - const detail::property_of_key_t &>( - *this); + property::detail::property_of_key_t> { + return static_cast &>(*this); } }; diff --git a/sycl/test/extensions/khr_properties/properties.cpp b/sycl/test/extensions/khr_properties/properties.cpp index 19db7ddd3c78c..4c118593b0aeb 100644 --- a/sycl/test/extensions/khr_properties/properties.cpp +++ b/sycl/test/extensions/khr_properties/properties.cpp @@ -13,7 +13,7 @@ #error "SYCL_KHR_PROPERTIES feature-test macro is not defined" #endif -namespace kd = sycl::khr::detail; +namespace kd = sycl::khr::property::detail; using namespace sycl::khr; struct MyClass {}; diff --git a/sycl/test/extensions/khr_properties/properties_layout.cpp b/sycl/test/extensions/khr_properties/properties_layout.cpp index d55bc2d848b9f..e746b03b46bde 100644 --- a/sycl/test/extensions/khr_properties/properties_layout.cpp +++ b/sycl/test/extensions/khr_properties/properties_layout.cpp @@ -12,7 +12,7 @@ #define __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS #include -namespace kd = sycl::khr::detail; +namespace kd = sycl::khr::property::detail; using namespace sycl::khr; struct rt1_key : kd::runtime_property_key {}; diff --git a/sycl/test/extensions/khr_properties/properties_negative.cpp b/sycl/test/extensions/khr_properties/properties_negative.cpp index d4615070837b9..3779aef26f286 100644 --- a/sycl/test/extensions/khr_properties/properties_negative.cpp +++ b/sycl/test/extensions/khr_properties/properties_negative.cpp @@ -9,7 +9,7 @@ #define __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS #include -namespace kd = sycl::khr::detail; +namespace kd = sycl::khr::property::detail; using namespace sycl::khr; struct rt_key : kd::property_key_tag {}; diff --git a/sycl/test/khr/include_sycl_with_unfinished_khr.cpp b/sycl/test/khr/include_sycl_with_unfinished_khr.cpp new file mode 100644 index 0000000000000..7f2218e6c594b --- /dev/null +++ b/sycl/test/khr/include_sycl_with_unfinished_khr.cpp @@ -0,0 +1,9 @@ +// Including with the unfinished KHR extensions enabled must +// compile cleanly. This guards against namespace shadowing where KHR headers +// in namespace sycl::khr use bare `detail::Foo` intending sycl::detail::Foo, +// but resolve to a sycl::khr::detail defined by another KHR header. +// RUN: %clangxx -fsycl -fsyntax-only -Xclang -verify %s +// expected-no-diagnostics +#define __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS +#include +int main() {} From 66f04b253c651e9499c755dc80936441c45ffe60 Mon Sep 17 00:00:00 2001 From: Konstantinos Parasyris Date: Wed, 9 Sep 2026 16:21:25 -0700 Subject: [PATCH 2/4] [SYCL] Add sycl_khr_properties queue properties Add the queue properties khr::property::{enable_profiling,in_order} (runtime bool, separate keys) to the single khr/properties.hpp, and the queue constructor overloads accepting a khr property or property list plus queue::khr_is_profiling_enabled(). The constructors translate the runtime-valued khr properties into an old-style property_list via a new befriended detail::PropertyListBuilder (property_list's runtime bitset constructor). is_in_order() already existed. --- sycl/include/sycl/khr/properties.hpp | 36 ++++++ sycl/include/sycl/property_list.hpp | 20 +++ sycl/include/sycl/queue.hpp | 117 +++++++++++++++++- .../khr_properties/queue_properties.cpp | 40 ++++++ 4 files changed, 212 insertions(+), 1 deletion(-) create mode 100644 sycl/test/extensions/khr_properties/queue_properties.cpp diff --git a/sycl/include/sycl/khr/properties.hpp b/sycl/include/sycl/khr/properties.hpp index fb3d35f07c1c5..d257f146e8810 100644 --- a/sycl/include/sycl/khr/properties.hpp +++ b/sycl/include/sycl/khr/properties.hpp @@ -34,6 +34,10 @@ namespace sycl { inline namespace _V1 { +// Forward declarations of the SYCL classes that the named properties below +// register against (via is_property_key_for). Only incomplete types are needed. +class queue; + namespace khr { template class __SYCL_EBO properties; @@ -291,6 +295,38 @@ properties(Properties... props) -> properties; using empty_properties_t = decltype(properties{}); +//===----------------------------------------------------------------------===// +// Named properties +// +// The concrete properties defined by this extension live here (one header for +// the whole extension). Each property registers the classes it applies to via +// is_property_key_for. Constructor/overload support for these lives in the +// respective SYCL object headers (e.g. queue.hpp). +//===----------------------------------------------------------------------===// + +namespace property { +namespace key { +struct enable_profiling : detail::runtime_property_key {}; +struct in_order : detail::runtime_property_key {}; +} // namespace key + +// Queue properties. +struct enable_profiling : detail::runtime_property { + constexpr enable_profiling(bool v = true) : value{v} {} + bool value; +}; +struct in_order : detail::runtime_property { + constexpr in_order(bool v = true) : value{v} {} + bool value; +}; +} // namespace property + +template <> +struct is_property_key_for + : std::true_type {}; +template <> +struct is_property_key_for : std::true_type {}; + } // namespace khr } // namespace _V1 } // namespace sycl diff --git a/sycl/include/sycl/property_list.hpp b/sycl/include/sycl/property_list.hpp index 4e4490833b82d..42df420338d98 100644 --- a/sycl/include/sycl/property_list.hpp +++ b/sycl/include/sycl/property_list.hpp @@ -26,6 +26,7 @@ template class accessor_property_list; namespace detail { class PropertyValidator; class SYCLMemObjT; +class PropertyListBuilder; } // namespace detail /// Objects of the property_list class are containers for the SYCL properties @@ -71,6 +72,7 @@ class property_list : protected detail::PropertyListBase { friend class ext::oneapi::accessor_property_list; friend class detail::PropertyValidator; friend class detail::SYCLMemObjT; + friend class detail::PropertyListBuilder; }; namespace detail { @@ -83,6 +85,24 @@ class PropertyValidator { std::move(FunctionForData)); } }; + +// Builds a property_list at runtime. Used to translate runtime-valued +// sycl_khr_properties into an old-style property_list. +class PropertyListBuilder { + std::bitset MDataLessProps; + std::vector> MPropsWithData; + +public: + template void add() { + MDataLessProps.set(DataLessPropT::getKind()); + } + void add(std::shared_ptr Prop) { + MPropsWithData.push_back(std::move(Prop)); + } + property_list finalize() { + return property_list(MDataLessProps, MPropsWithData); + } +}; } // namespace detail } // namespace _V1 diff --git a/sycl/include/sycl/queue.hpp b/sycl/include/sycl/queue.hpp index 629b73e8258f3..46cead3bbb838 100644 --- a/sycl/include/sycl/queue.hpp +++ b/sycl/include/sycl/queue.hpp @@ -38,7 +38,9 @@ #include // for is_queue_info_... #include // for auto_name #include // for kernel_handler +#include // for khr properties #include // for nd_range +#include // for property::queue::* #include // for property_list #include // for range #include // for sycl::span @@ -166,7 +168,7 @@ auto submit_kernel_direct_single_task( } // namespace detail -namespace ext ::oneapi ::experimental { +namespace ext::oneapi::experimental { // State of a queue with regards to graph recording, // returned by info::queue::state enum class queue_state { executing, recording }; @@ -356,6 +358,110 @@ class __SYCL_EXPORT queue : public detail::OwnerLessBase { queue(const context &SyclContext, const device &SyclDevice, const async_handler &AsyncHandler, const property_list &PropList = {}); +#ifdef __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS + // sycl_khr_properties queue constructors. These mirror the property_list + // constructors above but accept a khr property or property list, translating + // it to the corresponding old-style property_list. PropertyOrList is not + // defaulted: the property_list constructors already cover the no-property + // case, and defaulting here would make e.g. `queue q{}` ambiguous. +private: + template + static constexpr bool KhrPropsForQueue = + khr::is_property_for_v || + khr::is_property_list_for_v; + + // Translate a khr property or property list into an old-style property_list. + template + static property_list khrToPropertyList(const PropertyOrList &Props) { + if constexpr (khr::is_property_v) { + return khrToPropertyList(khr::properties{Props}); + } else { + detail::PropertyListBuilder Builder; + if constexpr (PropertyOrList::template has_property< + khr::property::key::in_order>()) + if (Props.template get_property().value) + Builder.template add(); + if constexpr (PropertyOrList::template has_property< + khr::property::key::enable_profiling>()) + if (Props.template get_property() + .value) + Builder.template add(); + return Builder.finalize(); + } + } + +public: + template >> + explicit queue(PropertyOrList props) : queue(khrToPropertyList(props)) {} + + template >> + explicit queue(const async_handler &AsyncHandler, PropertyOrList props) + : queue(AsyncHandler, khrToPropertyList(props)) {} + + template , + typename PropertyOrList, + typename = std::enable_if_t>> + explicit queue(const DeviceSelector &deviceSelector, PropertyOrList props) + : queue(deviceSelector, khrToPropertyList(props)) {} + + template , + typename PropertyOrList, + typename = std::enable_if_t>> + explicit queue(const DeviceSelector &deviceSelector, + const async_handler &AsyncHandler, PropertyOrList props) + : queue(deviceSelector, AsyncHandler, khrToPropertyList(props)) {} + + template >> + explicit queue(const device &SyclDevice, PropertyOrList props) + : queue(SyclDevice, khrToPropertyList(props)) {} + + template >> + explicit queue(const device &SyclDevice, const async_handler &AsyncHandler, + PropertyOrList props) + : queue(SyclDevice, AsyncHandler, khrToPropertyList(props)) {} + + template , + typename PropertyOrList, + typename = std::enable_if_t>> + explicit queue(const context &SyclContext, + const DeviceSelector &deviceSelector, PropertyOrList props) + : queue(SyclContext, deviceSelector, khrToPropertyList(props)) {} + + template , + typename PropertyOrList, + typename = std::enable_if_t>> + explicit queue(const context &SyclContext, + const DeviceSelector &deviceSelector, + const async_handler &AsyncHandler, PropertyOrList props) + : queue(SyclContext, deviceSelector, AsyncHandler, + khrToPropertyList(props)) {} + + template >> + explicit queue(const context &SyclContext, const device &SyclDevice, + PropertyOrList props) + : queue(SyclContext, SyclDevice, khrToPropertyList(props)) {} + + template >> + explicit queue(const context &SyclContext, const device &SyclDevice, + const async_handler &AsyncHandler, PropertyOrList props) + : queue(SyclContext, SyclDevice, AsyncHandler, khrToPropertyList(props)) { + } +#endif // __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS + /// Constructs a SYCL queue with an optional async_handler from an OpenCL /// cl_command_queue. /// @@ -3625,6 +3731,15 @@ class __SYCL_EXPORT queue : public detail::OwnerLessBase { /// void khr_flush() const; +#ifdef __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS + /// Returns true only if this queue was constructed with profiling enabled. + /// + /// Equivalent to has_property(). + bool khr_is_profiling_enabled() const { + return has_property(); + } +#endif + std::optional ext_oneapi_get_last_event() const { return static_cast>(ext_oneapi_get_last_event_impl()); } diff --git a/sycl/test/extensions/khr_properties/queue_properties.cpp b/sycl/test/extensions/khr_properties/queue_properties.cpp new file mode 100644 index 0000000000000..65ffe4781104d --- /dev/null +++ b/sycl/test/extensions/khr_properties/queue_properties.cpp @@ -0,0 +1,40 @@ +// RUN: %clangxx -fsycl -fsyntax-only -Xclang -verify %s +// expected-no-diagnostics +// +// Tests the sycl_khr_properties queue properties (enable_profiling, in_order): +// their traits, that a queue can be constructed with them, and the queue +// members is_in_order / khr_is_profiling_enabled. + +#define __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS +#include + +namespace kp = sycl::khr::property; +using namespace sycl::khr; + +struct OtherClass {}; + +// Traits: both are runtime queue properties. +static_assert(is_property_v && + is_property_v); +static_assert(is_property_key_v && + is_property_key_v); +static_assert(!is_property_key_compile_time_v && + !is_property_key_compile_time_v); +static_assert(is_property_for_v && + is_property_for_v); +static_assert(!is_property_for_v); + +// A property list is not itself a property. +static_assert(!is_property_v>); +static_assert(is_property_list_for_v< + decltype(properties{kp::enable_profiling{true}, kp::in_order{}}), + sycl::queue>); + +// A queue can be constructed from a single khr property or a khr property list. +void ctors() { + sycl::queue q1{kp::enable_profiling{true}}; + sycl::queue q2{kp::in_order{false}}; + sycl::queue q3{properties{kp::enable_profiling{true}, kp::in_order{true}}}; + (void)q1.is_in_order(); + (void)q1.khr_is_profiling_enabled(); +} From 48cf7ba441500526778cc3af38d2c724a2a2ff46 Mon Sep 17 00:00:00 2001 From: Konstantinos Parasyris Date: Wed, 9 Sep 2026 17:00:58 -0700 Subject: [PATCH 3/4] [SYCL] Fix MSVC C2686 on khr::properties::get_property MSVC rejects the static (compile-time key) and non-static const (runtime key) get_property overloads as differing only in return type during class definition, before the enable_if SFINAE applies. Give the runtime overload a defaulted dummy int parameter so the two have distinct parameter lists (as the experimental properties container does). --- sycl/include/sycl/khr/properties.hpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sycl/include/sycl/khr/properties.hpp b/sycl/include/sycl/khr/properties.hpp index d257f146e8810..b13236a1b84c5 100644 --- a/sycl/include/sycl/khr/properties.hpp +++ b/sycl/include/sycl/khr/properties.hpp @@ -279,8 +279,13 @@ class __SYCL_EBO properties } // Runtime (or hybrid) key: return a copy of the stored property. + // + // The dummy `int` parameter gives this overload a parameter list distinct + // from the static compile-time overload above. Without it, MSVC rejects the + // two overloads (static vs non-static) as differing only in return type + // (C2686) during class definition, before the enable_if SFINAE applies. template - constexpr auto get_property() const -> std::enable_if_t< + constexpr auto get_property(int = 0) const -> std::enable_if_t< !is_property_key_compile_time_v, property::detail::property_of_key_t> { return static_cast Date: Mon, 14 Sep 2026 12:47:37 -0700 Subject: [PATCH 4/4] Address reviews --- sycl/include/sycl/khr/properties.hpp | 90 +++++-------------- sycl/include/sycl/queue.hpp | 66 +++++++------- sycl/test/abi/sycl_symbols_windows.dump | 1 + .../khr/include_sycl_with_unfinished_khr.cpp | 3 + 4 files changed, 60 insertions(+), 100 deletions(-) diff --git a/sycl/include/sycl/khr/properties.hpp b/sycl/include/sycl/khr/properties.hpp index b13236a1b84c5..43a811f453d0c 100644 --- a/sycl/include/sycl/khr/properties.hpp +++ b/sycl/include/sycl/khr/properties.hpp @@ -7,19 +7,10 @@ //===----------------------------------------------------------------------===// // // Implementation of the sycl_khr_properties extension: the -// `sycl::khr::properties` compile-time property list container and the -// associated classification traits. +// `sycl::khr::properties` container and its classification traits. // -// Design notes: -// * The list stores its properties as private base classes. Properties whose -// values are all compile-time (empty types) are NOT stored -- they are -// default-constructed on retrieval -- so an all-compile-time list is -// zero-overhead and a mixed list only pays for its runtime members. This -// keeps the list trivially copyable and cheap to compile (no std::tuple). -// * The list does not canonicalize (sort) its element order. Per the -// extension, two lists built from the same properties in a different order -// may have different types; comparison operators are intentionally not -// provided. +// Compile-time-only properties are not stored (they are default-constructed on +// retrieval); the list preserves element order (no sorting) per the extension. // //===----------------------------------------------------------------------===// @@ -49,16 +40,9 @@ template class __SYCL_EBO properties; namespace property { namespace detail { -//===----------------------------------------------------------------------===// -// Base tags -// -// Every property derives (directly or via a convenience base) from -// `property_tag`, and exposes a `__detail_key_t` alias naming its key. Every -// key derives from `property_key_tag`; a key whose property has no -// runtime-provided values additionally derives from -// `compile_time_property_key_tag`. -//===----------------------------------------------------------------------===// - +// Every property derives from `property_tag` and exposes a `__detail_key_t` +// alias naming its key. Every key derives from `property_key_tag`; a +// compile-time key also derives from `compile_time_property_key_tag`. struct property_tag {}; struct property_key_tag {}; struct compile_time_property_key_tag : property_key_tag {}; @@ -76,26 +60,15 @@ inline constexpr bool __detail_has_runtime_value = !std::is_base_of_v; -//===----------------------------------------------------------------------===// -// Convenience base classes for defining properties -// -// These mirror the patterns in the extension's "Examples for implementors". -// Implementations may define properties directly on `property_base`/the tags, -// but these reduce boilerplate for the common shapes. -//===----------------------------------------------------------------------===// +// Convenience base classes for defining properties, mirroring the extension's +// examples for implementors. Properties may also be defined directly on the +// tags above. -// Base for a runtime property key (all of the property's values are supplied at -// runtime). Usage: -// struct my_key : property::detail::runtime_property_key {}; -// struct my_prop : property::detail::runtime_property { int value; -// ... }; +// Runtime property key: all of the property's values are supplied at runtime. struct runtime_property_key : property_key_tag {}; template struct runtime_property : property_base {}; -// Base for a compile-time property key with a single non-type value. Usage: -// struct my_key : property::detail::constant_value_property_key {}; -// template -// inline constexpr my_key::__detail_property_t my_prop; +// Compile-time key with a single non-type value. struct constant_value_property_key : compile_time_property_key_tag { template struct __detail_property_t : property_base { @@ -103,10 +76,7 @@ struct constant_value_property_key : compile_time_property_key_tag { }; }; -// Base for a compile-time property key with a single type value. Usage: -// struct my_key : property::detail::constant_type_property_key {}; -// template -// inline constexpr my_key::__detail_property_t my_prop; +// Compile-time key with a single type value. struct constant_type_property_key : compile_time_property_key_tag { template struct __detail_property_t : property_base { @@ -114,19 +84,12 @@ struct constant_type_property_key : compile_time_property_key_tag { }; }; -// Base for a hybrid property key (some values compile-time, some runtime). The -// key is a runtime key (the property carries runtime data and is stored). -// Usage: -// struct my_key : property::detail::hybrid_property_key {}; -// template struct my_prop : property::detail::hybrid_property -// { -// static constexpr int x = X; int y; constexpr my_prop(int y):y{y}{} }; +// Hybrid property key: some values compile-time, some runtime. The property +// carries runtime data and is stored. struct hybrid_property_key : property_key_tag {}; template struct hybrid_property : property_base {}; -//===----------------------------------------------------------------------===// -// Retrieval / storage machinery -//===----------------------------------------------------------------------===// +// Retrieval / storage machinery. // Selects, from a pack of properties, the one whose key is `Key`. Assumes // exactly one match (enforced by the "no duplicate key" mandate). @@ -183,10 +146,10 @@ struct is_properties_list> : std::true_type {}; } // namespace detail } // namespace property -//===----------------------------------------------------------------------===// -// Property traits -//===----------------------------------------------------------------------===// +// Classification traits. +// A property list is not itself a property: it privately inherits its +// properties, so is_base_of would otherwise report it as one -- exclude it. template struct is_property : std::bool_constant && @@ -235,10 +198,7 @@ template inline constexpr bool is_property_list_for_v = is_property_list_for::value; -//===----------------------------------------------------------------------===// -// The properties class -//===----------------------------------------------------------------------===// - +// The properties container. template class __SYCL_EBO properties : private property::detail::storage_for { @@ -300,15 +260,9 @@ properties(Properties... props) -> properties; using empty_properties_t = decltype(properties{}); -//===----------------------------------------------------------------------===// -// Named properties -// -// The concrete properties defined by this extension live here (one header for -// the whole extension). Each property registers the classes it applies to via -// is_property_key_for. Constructor/overload support for these lives in the -// respective SYCL object headers (e.g. queue.hpp). -//===----------------------------------------------------------------------===// - +// Named properties. Each registers its supported classes via +// is_property_key_for; constructor support lives in the object headers (e.g. +// queue.hpp). namespace property { namespace key { struct enable_profiling : detail::runtime_property_key {}; diff --git a/sycl/include/sycl/queue.hpp b/sycl/include/sycl/queue.hpp index 46cead3bbb838..b932447f31e91 100644 --- a/sycl/include/sycl/queue.hpp +++ b/sycl/include/sycl/queue.hpp @@ -200,6 +200,35 @@ event submit_with_event_impl(const queue &Q, PropertiesT Props, class __SYCL_EXPORT queue : public detail::OwnerLessBase { friend sycl::detail::ImplUtils; +#ifdef __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS + // sycl_khr_properties: predicate and translation used by the khr constructors + // below. Declared here (before the constructors) as they are referenced in + // the constructors' default template arguments. + template + static constexpr bool KhrPropsForQueue = + khr::is_property_for_v || + khr::is_property_list_for_v; + + template + static property_list khrToPropertyList(const PropertyOrList &Props) { + if constexpr (khr::is_property_v) { + return khrToPropertyList(khr::properties{Props}); + } else { + detail::PropertyListBuilder Builder; + if constexpr (PropertyOrList::template has_property< + khr::property::key::in_order>()) + if (Props.template get_property().value) + Builder.template add(); + if constexpr (PropertyOrList::template has_property< + khr::property::key::enable_profiling>()) + if (Props.template get_property() + .value) + Builder.template add(); + return Builder.finalize(); + } + } +#endif + public: /// Constructs a SYCL queue instance using the device returned by an instance /// of default_selector. @@ -359,38 +388,11 @@ class __SYCL_EXPORT queue : public detail::OwnerLessBase { const async_handler &AsyncHandler, const property_list &PropList = {}); #ifdef __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS - // sycl_khr_properties queue constructors. These mirror the property_list - // constructors above but accept a khr property or property list, translating - // it to the corresponding old-style property_list. PropertyOrList is not - // defaulted: the property_list constructors already cover the no-property - // case, and defaulting here would make e.g. `queue q{}` ambiguous. -private: - template - static constexpr bool KhrPropsForQueue = - khr::is_property_for_v || - khr::is_property_list_for_v; - - // Translate a khr property or property list into an old-style property_list. - template - static property_list khrToPropertyList(const PropertyOrList &Props) { - if constexpr (khr::is_property_v) { - return khrToPropertyList(khr::properties{Props}); - } else { - detail::PropertyListBuilder Builder; - if constexpr (PropertyOrList::template has_property< - khr::property::key::in_order>()) - if (Props.template get_property().value) - Builder.template add(); - if constexpr (PropertyOrList::template has_property< - khr::property::key::enable_profiling>()) - if (Props.template get_property() - .value) - Builder.template add(); - return Builder.finalize(); - } - } - -public: + // sycl_khr_properties queue constructors. Accept a khr property or property + // list and translate it to the old-style property_list (see khrToPropertyList + // in the private section). PropertyOrList is not defaulted: the property_list + // constructors already cover the no-property case, and defaulting here would + // make `queue q{}` ambiguous. template >> explicit queue(PropertyOrList props) : queue(khrToPropertyList(props)) {} diff --git a/sycl/test/abi/sycl_symbols_windows.dump b/sycl/test/abi/sycl_symbols_windows.dump index 70a39a2743b10..7c4945647f44d 100644 --- a/sycl/test/abi/sycl_symbols_windows.dump +++ b/sycl/test/abi/sycl_symbols_windows.dump @@ -4213,6 +4213,7 @@ ?khr_empty@queue@_V1@sycl@@QEBA_NXZ ?khr_flush@queue@_V1@sycl@@QEBAXXZ ?khr_get_default_context@platform@_V1@sycl@@QEBA?AVcontext@23@XZ +?khr_is_profiling_enabled@queue@_V1@sycl@@QEBA_NXZ ?lgamma_r_impl@detail@_V1@sycl@@YA?AVhalf@half_impl@123@V45123@PEAH@Z ?lgamma_r_impl@detail@_V1@sycl@@YAMMPEAH@Z ?lgamma_r_impl@detail@_V1@sycl@@YANNPEAH@Z diff --git a/sycl/test/khr/include_sycl_with_unfinished_khr.cpp b/sycl/test/khr/include_sycl_with_unfinished_khr.cpp index 7f2218e6c594b..01bf07b328185 100644 --- a/sycl/test/khr/include_sycl_with_unfinished_khr.cpp +++ b/sycl/test/khr/include_sycl_with_unfinished_khr.cpp @@ -2,6 +2,9 @@ // compile cleanly. This guards against namespace shadowing where KHR headers // in namespace sycl::khr use bare `detail::Foo` intending sycl::detail::Foo, // but resolve to a sycl::khr::detail defined by another KHR header. +// +// The failure mode is a compile error during header inclusion, so the include +// itself is the test; main is intentionally empty (nothing to run). // RUN: %clangxx -fsycl -fsyntax-only -Xclang -verify %s // expected-no-diagnostics #define __DPCPP_ENABLE_UNFINISHED_KHR_EXTENSIONS