blob: 529ddd54f1400475eb5c4d9b28704718d05a5ce2 [file] [edit]
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains the declaration of the SYCL 2020 group class.
///
//===----------------------------------------------------------------------===//
#ifndef _LIBSYCL___IMPL_GROUP_HPP
#define _LIBSYCL___IMPL_GROUP_HPP
#include <sycl/__impl/detail/config.hpp>
#include <sycl/__impl/detail/linearization.hpp>
#include <sycl/__impl/index_space_classes.hpp>
#include <sycl/__impl/memory_enums.hpp>
#include <sycl/__spirv/spirv_vars.hpp>
#include <cstddef>
_LIBSYCL_BEGIN_NAMESPACE_SYCL
template <int> class nd_item;
// SYCL2020 4.9.1.7. group class.
/// The group class encapsulates all functionality required to represent a
/// particular work-group within a parallel execution.
template <int Dimensions = 1> class group {
public:
using id_type = id<Dimensions>;
using range_type = range<Dimensions>;
using linear_id_type = std::size_t;
static constexpr int dimensions = Dimensions;
static constexpr memory_scope fence_scope = memory_scope::work_group;
group(const group &rhs) = default;
group(group &&rhs) = default;
group &operator=(const group &rhs) = default;
group &operator=(group &&rhs) = default;
/// \return an id representing the index of the work-group within the global
/// nd-range for every dimension.
id<Dimensions> get_group_id() const noexcept {
return __spirv::initBuiltInWorkgroupId<Dimensions, id<Dimensions>>();
}
/// Equivalent to `return get_group_id()[dimension]`.
std::size_t get_group_id(int dimension) const noexcept {
return get_group_id()[dimension];
}
/// \return a SYCL id representing the calling work-item’s position within the
/// work-group.
id<Dimensions> get_local_id() const noexcept {
return __spirv::initBuiltInLocalInvocationId<Dimensions, id<Dimensions>>();
}
/// Equivalent to `return get_local_id()[dimension]`.
std::size_t get_local_id(int dimension) const noexcept {
return get_local_id()[dimension];
}
/// \return a SYCL range representing all dimensions of the local range.
range<Dimensions> get_local_range() const noexcept {
return __spirv::initBuiltInWorkgroupSize<Dimensions, range<Dimensions>>();
}
/// Equivalent to `return get_local_range()[dimension]`.
std::size_t get_local_range(int dimension) const noexcept {
return get_local_range()[dimension];
}
/// \return a SYCL range representing the number of work-groups in the
/// nd-range.
range<Dimensions> get_group_range() const noexcept {
return __spirv::initBuiltInNumWorkgroups<Dimensions, range<Dimensions>>();
}
/// Equivalent to `return get_group_range()[dimension]`.
std::size_t get_group_range(int dimension) const noexcept {
return get_group_range()[dimension];
}
/// \return a SYCL range representing the maximum number of work-items in any
/// work-group in the nd-range.
range<Dimensions> get_max_local_range() const noexcept {
return get_local_range();
}
/// Equivalent to `return get_group_id(dimension)`.
std::size_t operator[](int dimension) const noexcept {
return get_group_id(dimension);
}
/// \return the linearized work-group id within the nd-range.
std::size_t get_group_linear_id() const noexcept {
return detail::linearize_id(get_group_id(), get_group_range());
}
/// \return a linearized version of the calling work-item’s local id.
std::size_t get_local_linear_id() const noexcept {
return detail::linearize_id(get_local_id(), get_local_range());
}
/// \return the total number of work-groups in the nd-range.
std::size_t get_group_linear_range() const noexcept {
auto groupRange = get_group_range();
return multiply_all_dims(groupRange);
}
/// \return the total number of work-items in this work-group.
std::size_t get_local_linear_range() const noexcept {
auto localRange = get_local_range();
return multiply_all_dims(localRange);
}
/// \return true for exactly one work-item in the work-group, if the calling
/// work-item is the leader of the work-group, and false for all other
/// work-items in the work-group.
bool leader() const noexcept { return (get_local_linear_id() == 0); }
// TODO: implement parallel_for_work_item, async_work_group_copy and wait_for.
protected:
group() = default;
static std::size_t
multiply_all_dims(const range<Dimensions> &Range) noexcept {
if constexpr (Dimensions == 1) {
return Range[0];
} else if constexpr (Dimensions == 2) {
return Range[0] * Range[1];
} else {
return Range[0] * Range[1] * Range[2];
}
}
friend class sycl::nd_item<Dimensions>;
};
_LIBSYCL_END_NAMESPACE_SYCL
#endif // _LIBSYCL___IMPL_GROUP_HPP