diff --git a/sycl/include/sycl/ext/oneapi/experimental/detail/properties/graph_properties.def b/sycl/include/sycl/ext/oneapi/experimental/detail/properties/graph_properties.def new file mode 100644 index 0000000000000..ce177a9bb0a16 --- /dev/null +++ b/sycl/include/sycl/ext/oneapi/experimental/detail/properties/graph_properties.def @@ -0,0 +1,26 @@ +// --*- c++ -*--- +#ifndef __SYCL_DATA_LESS_PROP +#define __SYCL_DATA_LESS_PROP(NS_QUALIFIER, PROP_NAME, ENUM_VAL) +#endif +#ifndef __SYCL_MANUALLY_DEFINED_PROP +#define __SYCL_MANUALLY_DEFINED_PROP(NS_QUALIFIER, PROP_NAME) +#endif + +/// Property passed to command_graph constructor to disable checking for cycles. +__SYCL_DATA_LESS_PROP(property::graph, no_cycle_check, GraphNoCycleCheck) + +/// Property passed to command_graph constructor to allow buffers to be used +/// with graphs. Passing this property represents a promise from the user that +/// the buffer will outlive any graph that it is used in. +__SYCL_DATA_LESS_PROP(property::graph, assume_buffer_outlives_graph, GraphAssumeBufferOutlivesGraph) + +/// Property passed to command_graph::finalize() to +/// mark the resulting executable command_graph as able to be updated. +__SYCL_DATA_LESS_PROP(property::graph, updatable, GraphUpdatable) + +/// Property used to enable executable graph profiling. Enables profiling on +/// events returned by submissions of the executable graph +__SYCL_DATA_LESS_PROP(property::graph, enable_profiling, GraphEnableProfiling) + +#undef __SYCL_DATA_LESS_PROP +#undef __SYCL_MANUALLY_DEFINED_PROP diff --git a/sycl/include/sycl/ext/oneapi/experimental/detail/properties/graph_properties.hpp b/sycl/include/sycl/ext/oneapi/experimental/detail/properties/graph_properties.hpp new file mode 100644 index 0000000000000..6111e9f8aa5fb --- /dev/null +++ b/sycl/include/sycl/ext/oneapi/experimental/detail/properties/graph_properties.hpp @@ -0,0 +1,67 @@ +//==----------- graph_properties.hpp --- SYCL graph 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 // for DataLessPropKind +#include // for is_property_of + +#include // for true_type + +namespace sycl { +inline namespace _V1 { +namespace ext { +namespace oneapi { +namespace experimental { +#define __SYCL_DATA_LESS_PROP(NS_QUALIFIER, PROP_NAME, ENUM_VAL) \ + namespace NS_QUALIFIER { \ + class PROP_NAME \ + : public sycl::detail::DataLessProperty {}; \ + } +#include + +#define __SYCL_DATA_LESS_PROP(NS_QUALIFIER, PROP_NAME, ENUM_VAL) \ + namespace NS_QUALIFIER { \ + class PROP_NAME \ + : public sycl::detail::DataLessProperty {}; \ + } +#include + +class node; +namespace property::node { +class depends_on; +} // namespace property::node +// Graph property trait specializations. +enum class graph_state; +template class command_graph; + +} // namespace experimental +} // namespace oneapi +} // namespace ext + +#define __SYCL_MANUALLY_DEFINED_PROP(NS_QUALIFIER, PROP_NAME) \ + template \ + struct is_property_of> \ + : std::true_type {}; +#define __SYCL_DATA_LESS_PROP(NS_QUALIFIER, PROP_NAME, ENUM_VAL) \ + __SYCL_MANUALLY_DEFINED_PROP(NS_QUALIFIER, PROP_NAME) + +#include + +#define __SYCL_MANUALLY_DEFINED_PROP(NS_QUALIFIER, PROP_NAME) \ + template <> \ + struct is_property_of : std::true_type {}; +#define __SYCL_DATA_LESS_PROP(NS_QUALIFIER, PROP_NAME, ENUM_VAL) \ + __SYCL_MANUALLY_DEFINED_PROP(NS_QUALIFIER, PROP_NAME) + +#include + +} // namespace _V1 +} // namespace sycl diff --git a/sycl/include/sycl/ext/oneapi/experimental/detail/properties/node_properties.def b/sycl/include/sycl/ext/oneapi/experimental/detail/properties/node_properties.def new file mode 100644 index 0000000000000..7ded7609ca2d0 --- /dev/null +++ b/sycl/include/sycl/ext/oneapi/experimental/detail/properties/node_properties.def @@ -0,0 +1,17 @@ +// --*- c++ -*--- +#ifndef __SYCL_DATA_LESS_PROP +#define __SYCL_DATA_LESS_PROP(NS_QUALIFIER, PROP_NAME, ENUM_VAL) +#endif +#ifndef __SYCL_MANUALLY_DEFINED_PROP +#define __SYCL_MANUALLY_DEFINED_PROP(NS_QUALIFIER, PROP_NAME) +#endif + +/// Property used to to add all previous graph leaves as dependencies when +/// creating a new node with command_graph::add(). +__SYCL_DATA_LESS_PROP(property::node, depends_on_all_leaves, GraphDependOnAllLeaves) + +// Contains data field, defined explicitly. +__SYCL_MANUALLY_DEFINED_PROP(property::node, depends_on) + +#undef __SYCL_DATA_LESS_PROP +#undef __SYCL_MANUALLY_DEFINED_PROP diff --git a/sycl/include/sycl/ext/oneapi/experimental/graph.hpp b/sycl/include/sycl/ext/oneapi/experimental/graph.hpp index 8b399848d4b2f..e2e87c30ea945 100644 --- a/sycl/include/sycl/ext/oneapi/experimental/graph.hpp +++ b/sycl/include/sycl/ext/oneapi/experimental/graph.hpp @@ -18,6 +18,7 @@ #include #endif #include // for device +#include // for graph properties classes #include // for range, nd_range #include // for is_property, is_property_of #include // for property_list @@ -153,47 +154,7 @@ class __SYCL_EXPORT node { std::shared_ptr impl; }; -namespace property { -namespace graph { - -/// Property passed to command_graph constructor to disable checking for cycles. -/// -class no_cycle_check : public ::sycl::detail::DataLessProperty< - ::sycl::detail::GraphNoCycleCheck> { -public: - no_cycle_check() = default; -}; - -/// Property passed to command_graph constructor to allow buffers to be used -/// with graphs. Passing this property represents a promise from the user that -/// the buffer will outlive any graph that it is used in. -/// -class assume_buffer_outlives_graph - : public ::sycl::detail::DataLessProperty< - ::sycl::detail::GraphAssumeBufferOutlivesGraph> { -public: - assume_buffer_outlives_graph() = default; -}; - -/// Property passed to command_graph::finalize() to -/// mark the resulting executable command_graph as able to be updated. -class updatable - : public ::sycl::detail::DataLessProperty<::sycl::detail::GraphUpdatable> { -public: - updatable() = default; -}; - -/// Property used to enable executable graph profiling. Enables profiling on -/// events returned by submissions of the executable graph -class enable_profiling : public ::sycl::detail::DataLessProperty< - ::sycl::detail::GraphEnableProfiling> { -public: - enable_profiling() = default; -}; -} // namespace graph - -namespace node { - +namespace property::node { /// Property used to define dependent nodes when creating a new node with /// command_graph::add(). class depends_on : public ::sycl::detail::PropertyWithData< @@ -209,17 +170,7 @@ class depends_on : public ::sycl::detail::PropertyWithData< private: const std::vector<::sycl::ext::oneapi::experimental::node> MDeps; }; - -/// Property used to to add all previous graph leaves as dependencies when -/// creating a new node with command_graph::add(). -class depends_on_all_leaves : public ::sycl::detail::DataLessProperty< - ::sycl::detail::GraphDependOnAllLeaves> { -public: - depends_on_all_leaves() = default; -}; - -} // namespace node -} // namespace property +} // namespace property::node class __SYCL_EXPORT dynamic_command_group { public: @@ -260,6 +211,7 @@ class __SYCL_EXPORT modifiable_command_graph /// @param PropList Property list used to pass [0..n] predecessor nodes. /// @return Constructed empty node which has been added to the graph. node add(const property_list &PropList = {}) { + checkNodePropertiesAndThrow(PropList); if (PropList.has_property()) { auto Deps = PropList.get_property(); node Node = addImpl(Deps.get_dependencies()); @@ -280,6 +232,7 @@ class __SYCL_EXPORT modifiable_command_graph /// @param PropList Property list used to pass [0..n] predecessor nodes. /// @return Constructed node which has been added to the graph. template node add(T CGF, const property_list &PropList = {}) { + checkNodePropertiesAndThrow(PropList); if (PropList.has_property()) { auto Deps = PropList.get_property(); node Node = addImpl(CGF, Deps.get_dependencies()); @@ -391,6 +344,8 @@ class __SYCL_EXPORT modifiable_command_graph template friend T sycl::detail::createSyclObjFromImpl(decltype(T::impl) ImplObj); std::shared_ptr impl; + + static void checkNodePropertiesAndThrow(const property_list &Properties); }; #ifndef ___INTEL_PREVIEW_BREAKING_CHANGES @@ -555,24 +510,5 @@ command_graph(const context &SyclContext, const device &SyclDevice, } // namespace oneapi } // namespace ext -template <> -struct is_property - : std::true_type {}; - -template <> -struct is_property - : std::true_type {}; - -template <> -struct is_property_of< - ext::oneapi::experimental::property::graph::no_cycle_check, - ext::oneapi::experimental::command_graph< - ext::oneapi::experimental::graph_state::modifiable>> : std::true_type { -}; - -template <> -struct is_property_of : std::true_type {}; - } // namespace _V1 } // namespace sycl diff --git a/sycl/source/detail/graph_impl.cpp b/sycl/source/detail/graph_impl.cpp index 8d673bc844d44..e6181a559d8e6 100644 --- a/sycl/source/detail/graph_impl.cpp +++ b/sycl/source/detail/graph_impl.cpp @@ -302,6 +302,48 @@ void exec_graph_impl::makePartitions() { } } +static void checkGraphPropertiesAndThrow(const property_list &Properties) { + auto CheckDataLessProperties = [](int PropertyKind) { +#define __SYCL_DATA_LESS_PROP(NS_QUALIFIER, PROP_NAME, ENUM_VAL) \ + case NS_QUALIFIER::PROP_NAME::getKind(): \ + return true; +#define __SYCL_MANUALLY_DEFINED_PROP(NS_QUALIFIER, PROP_NAME) + switch (PropertyKind) { +#include + default: + return false; + } + }; + // No properties with data for graph now. + auto NoAllowedPropertiesCheck = [](int) { return false; }; + sycl::detail::PropertyValidator::checkPropsAndThrow( + Properties, CheckDataLessProperties, NoAllowedPropertiesCheck); +} + +graph_impl::graph_impl(const sycl::context &SyclContext, + const sycl::device &SyclDevice, + const sycl::property_list &PropList) + : MContext(SyclContext), MDevice(SyclDevice), MRecordingQueues(), + MEventsMap(), MInorderQueueMap() { + checkGraphPropertiesAndThrow(PropList); + if (PropList.has_property()) { + MSkipCycleChecks = true; + } + if (PropList.has_property()) { + MAllowBuffers = true; + } + + if (!SyclDevice.has(aspect::ext_oneapi_limited_graph) && + !SyclDevice.has(aspect::ext_oneapi_graph)) { + std::stringstream Stream; + Stream << SyclDevice.get_backend(); + std::string BackendString = Stream.str(); + throw sycl::exception( + sycl::make_error_code(errc::invalid), + BackendString + " backend is not supported by SYCL Graph extension."); + } +} + graph_impl::~graph_impl() { try { clearQueues(); @@ -872,7 +914,7 @@ exec_graph_impl::exec_graph_impl(sycl::context Context, MIsUpdatable(PropList.has_property()), MEnableProfiling( PropList.has_property()) { - + checkGraphPropertiesAndThrow(PropList); // If the graph has been marked as updatable then check if the backend // actually supports that. Devices supporting aspect::ext_oneapi_graph must // have support for graph update. @@ -1699,7 +1741,9 @@ modifiable_command_graph::finalize(const sycl::property_list &PropList) const { void modifiable_command_graph::begin_recording( queue &RecordingQueue, const sycl::property_list &PropList) { - std::ignore = PropList; + // No properties is handled here originally, just check that properties are + // related to graph at all. + checkGraphPropertiesAndThrow(PropList); auto QueueImpl = sycl::detail::getSyclObjImpl(RecordingQueue); assert(QueueImpl); @@ -1784,6 +1828,34 @@ std::vector modifiable_command_graph::get_root_nodes() const { return createNodesFromImpls(Impls); } +void modifiable_command_graph::checkNodePropertiesAndThrow( + const property_list &Properties) { + auto CheckDataLessProperties = [](int PropertyKind) { +#define __SYCL_DATA_LESS_PROP(NS_QUALIFIER, PROP_NAME, ENUM_VAL) \ + case NS_QUALIFIER::PROP_NAME::getKind(): \ + return true; +#define __SYCL_MANUALLY_DEFINED_PROP(NS_QUALIFIER, PROP_NAME) + switch (PropertyKind) { +#include + default: + return false; + } + }; + auto CheckPropertiesWithData = [](int PropertyKind) { +#define __SYCL_DATA_LESS_PROP(NS_QUALIFIER, PROP_NAME, ENUM_VAL) +#define __SYCL_MANUALLY_DEFINED_PROP(NS_QUALIFIER, PROP_NAME) \ + case NS_QUALIFIER::PROP_NAME::getKind(): \ + return true; + switch (PropertyKind) { +#include + default: + return false; + } + }; + sycl::detail::PropertyValidator::checkPropsAndThrow( + Properties, CheckDataLessProperties, CheckPropertiesWithData); +} + executable_command_graph::executable_command_graph( const std::shared_ptr &Graph, const sycl::context &Ctx, const property_list &PropList) diff --git a/sycl/source/detail/graph_impl.hpp b/sycl/source/detail/graph_impl.hpp index 2d714bcc96d66..e609123b4f285 100644 --- a/sycl/source/detail/graph_impl.hpp +++ b/sycl/source/detail/graph_impl.hpp @@ -779,27 +779,7 @@ class graph_impl : public std::enable_shared_from_this { /// @param SyclDevice Device to create nodes with. /// @param PropList Optional list of properties. graph_impl(const sycl::context &SyclContext, const sycl::device &SyclDevice, - const sycl::property_list &PropList = {}) - : MContext(SyclContext), MDevice(SyclDevice), MRecordingQueues(), - MEventsMap(), MInorderQueueMap() { - if (PropList.has_property()) { - MSkipCycleChecks = true; - } - if (PropList - .has_property()) { - MAllowBuffers = true; - } - - if (!SyclDevice.has(aspect::ext_oneapi_limited_graph) && - !SyclDevice.has(aspect::ext_oneapi_graph)) { - std::stringstream Stream; - Stream << SyclDevice.get_backend(); - std::string BackendString = Stream.str(); - throw sycl::exception( - sycl::make_error_code(errc::invalid), - BackendString + " backend is not supported by SYCL Graph extension."); - } - } + const sycl::property_list &PropList = {}); ~graph_impl(); diff --git a/sycl/source/detail/program_manager/program_manager.cpp b/sycl/source/detail/program_manager/program_manager.cpp index 3f1ae09a7966f..c26baf91035f8 100644 --- a/sycl/source/detail/program_manager/program_manager.cpp +++ b/sycl/source/detail/program_manager/program_manager.cpp @@ -2569,7 +2569,12 @@ std::vector ProgramManager::getSYCLDeviceImages( DevImgPlainWithDeps ProgramManager::compile(const DevImgPlainWithDeps &ImgWithDeps, const std::vector &Devs, - const property_list &) { + const property_list &PropList) { + { + auto NoAllowedPropertiesCheck = [](int) { return false; }; + detail::PropertyValidator::checkPropsAndThrow( + PropList, NoAllowedPropertiesCheck, NoAllowedPropertiesCheck); + } // TODO: Extract compile options from property list once the Spec clarifies // how they can be passed. @@ -2672,7 +2677,11 @@ std::vector ProgramManager::link(const DevImgPlainWithDeps &ImgWithDeps, const std::vector &Devs, const property_list &PropList) { - (void)PropList; + { + auto NoAllowedPropertiesCheck = [](int) { return false; }; + detail::PropertyValidator::checkPropsAndThrow( + PropList, NoAllowedPropertiesCheck, NoAllowedPropertiesCheck); + } const std::vector &Imgs = ImgWithDeps.getAll(); std::vector URPrograms; @@ -2763,7 +2772,11 @@ device_image_plain ProgramManager::build(const DevImgPlainWithDeps &DevImgWithDeps, const std::vector &Devs, const property_list &PropList) { - (void)PropList; + { + auto NoAllowedPropertiesCheck = [](int) { return false; }; + detail::PropertyValidator::checkPropsAndThrow( + PropList, NoAllowedPropertiesCheck, NoAllowedPropertiesCheck); + } const std::shared_ptr &MainInputImpl = getSyclObjImpl(DevImgWithDeps.getMain()); @@ -2815,7 +2828,11 @@ ProgramManager::getOrCreateKernel(const context &Context, const property_list &PropList, ur_program_handle_t Program) { - (void)PropList; + { + auto NoAllowedPropertiesCheck = [](int) { return false; }; + detail::PropertyValidator::checkPropsAndThrow( + PropList, NoAllowedPropertiesCheck, NoAllowedPropertiesCheck); + } const ContextImplPtr Ctx = getSyclObjImpl(Context); diff --git a/sycl/test/abi/sycl_symbols_linux.dump b/sycl/test/abi/sycl_symbols_linux.dump index 76512bcd3a70c..26a129e33ef85 100644 --- a/sycl/test/abi/sycl_symbols_linux.dump +++ b/sycl/test/abi/sycl_symbols_linux.dump @@ -3086,6 +3086,7 @@ _ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graph13end_reco _ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graph15begin_recordingERKSt6vectorINS0_5queueESaIS7_EERKNS0_13property_listE _ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graph15begin_recordingERNS0_5queueERKNS0_13property_listE _ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graph24addGraphLeafDependenciesENS3_4nodeE +_ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graph27checkNodePropertiesAndThrowERKNS0_13property_listE _ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graph7addImplERKSt6vectorINS3_4nodeESaIS7_EE _ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graph7addImplERNS3_21dynamic_command_groupERKSt6vectorINS3_4nodeESaIS9_EE _ZN4sycl3_V13ext6oneapi12experimental6detail24modifiable_command_graph7addImplESt8functionIFvRNS0_7handlerEEERKSt6vectorINS3_4nodeESaISC_EE diff --git a/sycl/test/abi/sycl_symbols_windows.dump b/sycl/test/abi/sycl_symbols_windows.dump index 1e52355d67ee7..a439081b1f382 100644 --- a/sycl/test/abi/sycl_symbols_windows.dump +++ b/sycl/test/abi/sycl_symbols_windows.dump @@ -3749,6 +3749,7 @@ ?build_impl@detail@_V1@sycl@@YA?AV?$shared_ptr@Vkernel_bundle_impl@detail@_V1@sycl@@@std@@AEBV?$kernel_bundle@$0A@@23@AEBV?$vector@Vdevice@_V1@sycl@@V?$allocator@Vdevice@_V1@sycl@@@std@@@5@AEBVproperty_list@23@@Z ?cancel_fusion@fusion_wrapper@experimental@codeplay@ext@_V1@sycl@@QEAAXXZ ?category@exception@_V1@sycl@@QEBAAEBVerror_category@std@@XZ +?checkNodePropertiesAndThrow@modifiable_command_graph@detail@experimental@oneapi@ext@_V1@sycl@@KAXAEBVproperty_list@67@@Z ?clearArgs@handler@_V1@sycl@@AEAAXXZ ?code@exception@_V1@sycl@@QEBAAEBVerror_code@std@@XZ ?compile_impl@?$online_compiler@$00@experimental@intel@ext@_V1@sycl@@CA?AV?$vector@EV?$allocator@E@std@@@std@@Vstring_view@detail@56@AEBV?$vector@Vstring_view@detail@_V1@sycl@@V?$allocator@Vstring_view@detail@_V1@sycl@@@std@@@8@U?$pair@HH@8@W4device_type@info@56@Vdevice_arch@23456@_N0AEAPEAX6@Z diff --git a/sycl/test/basic_tests/property_traits.cpp b/sycl/test/basic_tests/property_traits.cpp index f827803220f34..85611b48b1a69 100644 --- a/sycl/test/basic_tests/property_traits.cpp +++ b/sycl/test/basic_tests/property_traits.cpp @@ -77,6 +77,19 @@ int main() { // Reduction is_property CHECK_IS_PROPERTY(property::reduction::initialize_to_identity); + // Graph is_property + CHECK_IS_PROPERTY(ext::oneapi::experimental::property::graph::no_cycle_check); + CHECK_IS_PROPERTY( + ext::oneapi::experimental::property::graph::assume_buffer_outlives_graph); + CHECK_IS_PROPERTY(ext::oneapi::experimental::property::graph::updatable); + CHECK_IS_PROPERTY( + ext::oneapi::experimental::property::graph::enable_profiling); + + // Node is_property + CHECK_IS_PROPERTY( + ext::oneapi::experimental::property::node::depends_on_all_leaves); + CHECK_IS_PROPERTY(ext::oneapi::experimental::property::node::depends_on); + //---------------------------------------------------------------------------- // is_property negative tests //---------------------------------------------------------------------------- @@ -127,8 +140,32 @@ int main() { CHECK_IS_PROPERTY_OF(ext::oneapi::cuda::property::queue::use_default_stream, queue); + // Graph is_property_of + CHECK_IS_PROPERTY_OF( + ext::oneapi::experimental::property::graph::no_cycle_check, + ext::oneapi::experimental::command_graph< + ext::oneapi::experimental::graph_state::modifiable>); + CHECK_IS_PROPERTY_OF( + ext::oneapi::experimental::property::graph::assume_buffer_outlives_graph, + ext::oneapi::experimental::command_graph< + ext::oneapi::experimental::graph_state::modifiable>); + CHECK_IS_PROPERTY_OF(ext::oneapi::experimental::property::graph::updatable, + ext::oneapi::experimental::command_graph< + ext::oneapi::experimental::graph_state::modifiable>); + CHECK_IS_PROPERTY_OF( + ext::oneapi::experimental::property::graph::enable_profiling, + ext::oneapi::experimental::command_graph< + ext::oneapi::experimental::graph_state::modifiable>); + + // Node is_property_of + CHECK_IS_PROPERTY_OF( + ext::oneapi::experimental::property::node::depends_on_all_leaves, + ext::oneapi::experimental::node); + CHECK_IS_PROPERTY_OF(ext::oneapi::experimental::property::node::depends_on, + ext::oneapi::experimental::node); + //---------------------------------------------------------------------------- - // is_property_of positive tests + // is_property_of negative tests //---------------------------------------------------------------------------- // Valid properties with invalid object type @@ -155,6 +192,24 @@ int main() { CHECK_IS_NOT_PROPERTY_OF( ext::oneapi::cuda::property::queue::use_default_stream, NotASYCLObject); + CHECK_IS_NOT_PROPERTY_OF( + ext::oneapi::experimental::property::graph::no_cycle_check, + NotASYCLObject); + CHECK_IS_NOT_PROPERTY_OF( + ext::oneapi::experimental::property::graph::assume_buffer_outlives_graph, + NotASYCLObject); + CHECK_IS_NOT_PROPERTY_OF( + ext::oneapi::experimental::property::graph::updatable, NotASYCLObject); + CHECK_IS_NOT_PROPERTY_OF( + ext::oneapi::experimental::property::graph::enable_profiling, + NotASYCLObject); + + CHECK_IS_NOT_PROPERTY_OF( + ext::oneapi::experimental::property::node::depends_on_all_leaves, + NotASYCLObject); + CHECK_IS_NOT_PROPERTY_OF( + ext::oneapi::experimental::property::node::depends_on, NotASYCLObject); + // Invalid properties with valid object type CHECK_IS_NOT_PROPERTY_OF(NotAProperty, accessor); CHECK_IS_NOT_PROPERTY_OF(NotAProperty, host_accessor); @@ -162,6 +217,10 @@ int main() { CHECK_IS_NOT_PROPERTY_OF(NotAProperty, context); CHECK_IS_NOT_PROPERTY_OF(NotAProperty, image<1>); CHECK_IS_NOT_PROPERTY_OF(NotAProperty, queue); + CHECK_IS_NOT_PROPERTY_OF(NotAProperty, ext::oneapi::experimental::node); + CHECK_IS_NOT_PROPERTY_OF( + NotAProperty, ext::oneapi::experimental::command_graph< + ext::oneapi::experimental::graph_state::modifiable>); // Invalid properties with invalid object type CHECK_IS_NOT_PROPERTY_OF(NotAProperty, NotASYCLObject); @@ -194,6 +253,23 @@ int main() { CHECK_IS_PROPERTY_V(property::queue::cuda::use_default_stream); CHECK_IS_PROPERTY_V(ext::oneapi::cuda::property::queue::use_default_stream); + // Reduction is_property_v + CHECK_IS_PROPERTY_V(property::reduction::initialize_to_identity); + + // Graph is_property_v + CHECK_IS_PROPERTY_V( + ext::oneapi::experimental::property::graph::no_cycle_check); + CHECK_IS_PROPERTY_V( + ext::oneapi::experimental::property::graph::assume_buffer_outlives_graph); + CHECK_IS_PROPERTY_V(ext::oneapi::experimental::property::graph::updatable); + CHECK_IS_PROPERTY_V( + ext::oneapi::experimental::property::graph::enable_profiling); + + // Node is_property_v + CHECK_IS_PROPERTY_V( + ext::oneapi::experimental::property::node::depends_on_all_leaves); + CHECK_IS_PROPERTY_V(ext::oneapi::experimental::property::node::depends_on); + //---------------------------------------------------------------------------- // is_property_v negative tests //---------------------------------------------------------------------------- @@ -264,8 +340,30 @@ int main() { CHECK_IS_PROPERTY_OF_V(ext::oneapi::cuda::property::queue::use_default_stream, queue); - // Reduction is_property_v - CHECK_IS_PROPERTY_V(property::reduction::initialize_to_identity); + // Graph is_property_of_v + CHECK_IS_PROPERTY_OF_V( + ext::oneapi::experimental::property::graph::no_cycle_check, + ext::oneapi::experimental::command_graph< + ext::oneapi::experimental::graph_state::modifiable>); + CHECK_IS_PROPERTY_OF_V( + ext::oneapi::experimental::property::graph::assume_buffer_outlives_graph, + ext::oneapi::experimental::command_graph< + ext::oneapi::experimental::graph_state::modifiable>); + CHECK_IS_PROPERTY_OF_V( + ext::oneapi::experimental::property::graph::updatable, + ext::oneapi::experimental::command_graph< + ext::oneapi::experimental::graph_state::modifiable>); + CHECK_IS_PROPERTY_OF_V( + ext::oneapi::experimental::property::graph::enable_profiling, + ext::oneapi::experimental::command_graph< + ext::oneapi::experimental::graph_state::modifiable>); + + // Node is_property_of_v + CHECK_IS_PROPERTY_OF_V( + ext::oneapi::experimental::property::node::depends_on_all_leaves, + ext::oneapi::experimental::node); + CHECK_IS_PROPERTY_OF_V(ext::oneapi::experimental::property::node::depends_on, + ext::oneapi::experimental::node); //---------------------------------------------------------------------------- // is_property_of positive tests @@ -295,6 +393,24 @@ int main() { CHECK_IS_NOT_PROPERTY_OF_V( ext::oneapi::cuda::property::queue::use_default_stream, NotASYCLObject); + CHECK_IS_NOT_PROPERTY_OF_V( + ext::oneapi::experimental::property::graph::no_cycle_check, + NotASYCLObject); + CHECK_IS_NOT_PROPERTY_OF_V( + ext::oneapi::experimental::property::graph::assume_buffer_outlives_graph, + NotASYCLObject); + CHECK_IS_NOT_PROPERTY_OF_V( + ext::oneapi::experimental::property::graph::updatable, NotASYCLObject); + CHECK_IS_NOT_PROPERTY_OF_V( + ext::oneapi::experimental::property::graph::enable_profiling, + NotASYCLObject); + + CHECK_IS_NOT_PROPERTY_OF_V( + ext::oneapi::experimental::property::node::depends_on_all_leaves, + NotASYCLObject); + CHECK_IS_NOT_PROPERTY_OF_V( + ext::oneapi::experimental::property::node::depends_on, NotASYCLObject); + // Invalid properties with valid object type CHECK_IS_NOT_PROPERTY_OF_V(NotAProperty, accessor); CHECK_IS_NOT_PROPERTY_OF_V(NotAProperty, host_accessor); @@ -302,6 +418,10 @@ int main() { CHECK_IS_NOT_PROPERTY_OF_V(NotAProperty, context); CHECK_IS_NOT_PROPERTY_OF_V(NotAProperty, image<1>); CHECK_IS_NOT_PROPERTY_OF_V(NotAProperty, queue); + CHECK_IS_NOT_PROPERTY_OF_V(NotAProperty, ext::oneapi::experimental::node); + CHECK_IS_NOT_PROPERTY_OF_V( + NotAProperty, ext::oneapi::experimental::command_graph< + ext::oneapi::experimental::graph_state::modifiable>); // Invalid properties with invalid object type CHECK_IS_NOT_PROPERTY_OF_V(NotAProperty, NotASYCLObject); diff --git a/sycl/test/include_deps/sycl_detail_core.hpp.cpp b/sycl/test/include_deps/sycl_detail_core.hpp.cpp index 8d33cf1fb850e..ac0f6c202262a 100644 --- a/sycl/test/include_deps/sycl_detail_core.hpp.cpp +++ b/sycl/test/include_deps/sycl_detail_core.hpp.cpp @@ -113,6 +113,9 @@ // CHECK-NEXT: ext/oneapi/properties/property_utils.hpp // CHECK-NEXT: ext/oneapi/experimental/event_mode_property.hpp // CHECK-NEXT: ext/oneapi/experimental/graph.hpp +// CHECK-NEXT: ext/oneapi/experimental/detail/properties/graph_properties.hpp +// CHECK-NEXT: ext/oneapi/experimental/detail/properties/graph_properties.def +// CHECK-NEXT: ext/oneapi/experimental/detail/properties/node_properties.def // CHECK-NEXT: handler.hpp // CHECK-NEXT: detail/cl.h // CHECK-NEXT: CL/cl.h diff --git a/sycl/unittests/Extensions/CommandGraph/CMakeLists.txt b/sycl/unittests/Extensions/CommandGraph/CMakeLists.txt index b7213d2eaeae6..31f899f6a2349 100644 --- a/sycl/unittests/Extensions/CommandGraph/CMakeLists.txt +++ b/sycl/unittests/Extensions/CommandGraph/CMakeLists.txt @@ -10,4 +10,5 @@ add_sycl_unittest(CommandGraphExtensionTests OBJECT Regressions.cpp Subgraph.cpp Update.cpp + Properties.cpp ) diff --git a/sycl/unittests/Extensions/CommandGraph/Properties.cpp b/sycl/unittests/Extensions/CommandGraph/Properties.cpp new file mode 100644 index 0000000000000..a896e4ba47314 --- /dev/null +++ b/sycl/unittests/Extensions/CommandGraph/Properties.cpp @@ -0,0 +1,47 @@ +//==------------------------- Properties.cpp -------------------------------==// +// +// 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 +// +//===----------------------------------------------------------------------===// +#include "Common.hpp" + +using namespace sycl; +using namespace sycl::ext::oneapi; + +class UnknownProperty : public ::sycl::detail::DataLessProperty< + ::sycl::detail::LastKnownDataLessPropKind + 1> { +public: + UnknownProperty() = default; +}; + +// Negative tests for properties of graph. Positive checks are included to other +// graph tests verifying exact properties usage. +TEST_F(CommandGraphTest, PropertiesCheckInvalidNode) { + try { + auto Node1 = Graph.add( + [&](sycl::handler &cgh) { cgh.single_task>([]() {}); }, + UnknownProperty{}); + } catch (sycl::exception &e) { + EXPECT_EQ(e.code(), sycl::errc::invalid); + EXPECT_STREQ(e.what(), "The property list contains property unsupported " + "for the current object"); + return; + } + + FAIL() << "Test must exit in exception handler. Exception is not thrown."; +} + +TEST_F(CommandGraphTest, PropertiesCheckFinalize) { + try { + auto ExecGraphUpdatable = Graph.finalize(UnknownProperty{}); + } catch (sycl::exception &e) { + EXPECT_EQ(e.code(), sycl::errc::invalid); + EXPECT_STREQ(e.what(), "The property list contains property unsupported " + "for the current object"); + return; + } + + FAIL() << "Test must exit in exception handler. Exception is not thrown."; +} diff --git a/sycl/unittests/kernel-and-program/KernelBuildOptions.cpp b/sycl/unittests/kernel-and-program/KernelBuildOptions.cpp index 2cf52e27cd648..2c34ba6d11604 100644 --- a/sycl/unittests/kernel-and-program/KernelBuildOptions.cpp +++ b/sycl/unittests/kernel-and-program/KernelBuildOptions.cpp @@ -110,13 +110,39 @@ TEST(KernelBuildOptions, KernelBundleBasic) { sycl::kernel_bundle KernelBundle = sycl::get_kernel_bundle(Ctx, {Dev}, {KernelID}); + try { + // unsupported property + auto ExecBundle = sycl::build(KernelBundle, sycl::property::no_init{}); + FAIL(); + } catch (sycl::exception &e) { + EXPECT_EQ(e.code(), sycl::errc::invalid); + EXPECT_STREQ(e.what(), "The property list contains property unsupported " + "for the current object"); + } auto ExecBundle = sycl::build(KernelBundle); EXPECT_EQ(BuildOpts, "-compile-img -vc-codegen -disable-finalizer-msg -link-img"); - + try { + auto ObjBundle = sycl::compile(KernelBundle, KernelBundle.get_devices(), + sycl::property::no_init{}); + FAIL(); + } catch (sycl::exception &e) { + EXPECT_EQ(e.code(), sycl::errc::invalid); + EXPECT_STREQ(e.what(), "The property list contains property unsupported " + "for the current object"); + } auto ObjBundle = sycl::compile(KernelBundle, KernelBundle.get_devices()); EXPECT_EQ(BuildOpts, "-compile-img -vc-codegen -disable-finalizer-msg"); + try { + auto LinkBundle = sycl::link(ObjBundle, ObjBundle.get_devices(), + sycl::property::no_init{}); + FAIL(); + } catch (sycl::exception &e) { + EXPECT_EQ(e.code(), sycl::errc::invalid); + EXPECT_STREQ(e.what(), "The property list contains property unsupported " + "for the current object"); + } auto LinkBundle = sycl::link(ObjBundle, ObjBundle.get_devices()); EXPECT_EQ(BuildOpts, "-link-img"); }