2017-12-21 00:45:38 +01:00
/*
2025-02-26 14:32:25 +00:00
* Copyright ( C ) 2018 - 2025 Intel Corporation
2017-12-21 00:45:38 +01:00
*
2018-09-18 09:11:08 +02:00
* SPDX - License - Identifier : MIT
2017-12-21 00:45:38 +01:00
*
*/
# pragma once
2020-02-23 22:44:01 +01:00
# include "shared/source/helpers/debug_helpers.h"
2018-01-05 12:54:12 +01:00
2022-04-07 13:09:40 +00:00
# include <algorithm>
2022-11-23 15:09:23 +00:00
# include <cstdint>
2020-02-24 22:07:46 +01:00
# include <limits>
feature: Affinity mask plus ReturnSubDevicesAsApiDevices
When using ReturnSubDevicesAsApiDevices=1 to have
sub-devices-as-root-devices, then the driver should read the values
passed in the mask as those corresponding to the physical
sub-devices.
For instance, in a dual system with multi-tile device, we would have:
card 0, tile 0
card 0, tile 1
card 1, tile 0
card 1, tile 1
With:
ReturnSubDevicesAsApiDevices=0
ZE_AFFINITY_MASK=0,1
Then all tiles in card 0 and card 1 need to be exposed.
With:
ReturnSubDevicesAsApiDevices=1
ZE_AFFINITY_MASK=0,3
Then card 0 tile 0, and card 1 tile 1 need to be exposed.
Related-To: NEO-7137
Signed-off-by: Jaime Arteaga <jaime.a.arteaga.molina@intel.com>
2023-02-02 02:54:47 +00:00
# include <tuple>
2017-12-21 00:45:38 +01:00
# include <vector>
2023-11-30 10:36:43 +00:00
template < size_t onStackCapacity >
2020-02-24 22:07:46 +01:00
struct StackVecSize {
static constexpr size_t max32 = std : : numeric_limits < uint32_t > : : max ( ) ;
static constexpr size_t max16 = std : : numeric_limits < uint16_t > : : max ( ) ;
static constexpr size_t max8 = std : : numeric_limits < uint8_t > : : max ( ) ;
2023-11-30 10:36:43 +00:00
using SizeT = std : : conditional_t < ( onStackCapacity < max8 ) , uint8_t ,
std : : conditional_t < ( onStackCapacity < max16 ) , uint16_t ,
std : : conditional_t < ( onStackCapacity < max32 ) , uint32_t , size_t > > > ;
2020-02-24 22:07:46 +01:00
} ;
2023-11-30 10:36:43 +00:00
template < typename DataType , size_t onStackCapacity ,
typename StackSizeT = typename StackVecSize < onStackCapacity > : : SizeT >
2022-05-09 17:40:30 +00:00
class StackVec { // NOLINT(clang-analyzer-optin.performance.Padding)
2017-12-21 00:45:38 +01:00
public :
2023-11-30 10:36:43 +00:00
using value_type = DataType ; // NOLINT(readability-identifier-naming)
2020-02-24 22:07:46 +01:00
using SizeT = StackSizeT ;
2023-11-30 10:36:43 +00:00
using iterator = DataType * ; // NOLINT(readability-identifier-naming)
using const_iterator = const DataType * ; // NOLINT(readability-identifier-naming)
using reverse_iterator = std : : reverse_iterator < iterator > ; // NOLINT(readability-identifier-naming)
using const_reverse_iterator = std : : reverse_iterator < const_iterator > ; // NOLINT(readability-identifier-naming)
2017-12-21 00:45:38 +01:00
2023-11-30 10:36:43 +00:00
static constexpr SizeT onStackCaps = onStackCapacity ;
2018-01-05 12:54:12 +01:00
2020-02-24 22:07:46 +01:00
StackVec ( ) {
2024-09-13 14:30:14 +00:00
switchToStackMem ( ) ;
2020-02-24 22:07:46 +01:00
}
2017-12-21 00:45:38 +01:00
template < typename ItType >
2020-02-24 22:07:46 +01:00
StackVec ( ItType beginIt , ItType endIt ) {
2024-09-13 14:30:14 +00:00
switchToStackMem ( ) ;
2017-12-21 00:45:38 +01:00
size_t count = ( endIt - beginIt ) ;
2023-11-30 10:36:43 +00:00
if ( count > onStackCapacity ) {
2017-12-21 00:45:38 +01:00
dynamicMem = new std : : vector < DataType > ( beginIt , endIt ) ;
return ;
}
while ( beginIt ! = endIt ) {
push_back ( * beginIt ) ;
+ + beginIt ;
}
2020-02-24 22:07:46 +01:00
onStackSize = static_cast < SizeT > ( count ) ;
2017-12-21 00:45:38 +01:00
}
2020-02-24 22:07:46 +01:00
StackVec ( const StackVec & rhs ) {
2024-09-13 14:30:14 +00:00
switchToStackMem ( ) ;
2017-12-21 00:45:38 +01:00
if ( onStackCaps < rhs . size ( ) ) {
dynamicMem = new std : : vector < DataType > ( rhs . begin ( ) , rhs . end ( ) ) ;
return ;
}
for ( const auto & v : rhs ) {
push_back ( v ) ;
}
}
2018-01-05 12:54:12 +01:00
explicit StackVec ( size_t initialSize )
: StackVec ( ) {
2024-09-13 14:30:14 +00:00
switchToStackMem ( ) ;
2018-01-05 12:54:12 +01:00
resize ( initialSize ) ;
}
2019-01-28 14:26:33 +01:00
StackVec ( std : : initializer_list < DataType > init ) {
2024-09-13 14:30:14 +00:00
switchToStackMem ( ) ;
2019-01-28 14:26:33 +01:00
reserve ( init . size ( ) ) ;
for ( const auto & obj : init ) {
push_back ( obj ) ;
}
}
2017-12-21 00:45:38 +01:00
StackVec & operator = ( const StackVec & rhs ) {
2021-07-22 18:51:08 +00:00
if ( this = = & rhs ) {
return * this ;
}
2017-12-21 00:45:38 +01:00
clear ( ) ;
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
this - > dynamicMem - > assign ( rhs . begin ( ) , rhs . end ( ) ) ;
2017-12-21 00:45:38 +01:00
return * this ;
}
if ( onStackCaps < rhs . size ( ) ) {
this - > dynamicMem = new std : : vector < DataType > ( rhs . begin ( ) , rhs . end ( ) ) ;
return * this ;
}
for ( const auto & v : rhs ) {
push_back ( v ) ;
}
return * this ;
}
2018-01-05 12:54:12 +01:00
2025-06-05 13:28:04 +00:00
StackVec ( StackVec & & rhs ) noexcept {
2020-02-24 22:07:46 +01:00
onStackMem = reinterpret_cast < DataType * const > ( onStackMemRawBytes ) ;
if ( rhs . usesDynamicMem ( ) ) {
this - > dynamicMem = rhs . dynamicMem ;
2024-09-13 14:30:14 +00:00
rhs . switchToStackMem ( ) ;
2017-12-21 00:45:38 +01:00
return ;
}
for ( const auto & v : rhs ) {
push_back ( v ) ;
}
2020-02-24 22:07:46 +01:00
rhs . clear ( ) ;
2017-12-21 00:45:38 +01:00
}
2018-01-05 12:54:12 +01:00
2025-06-05 13:28:04 +00:00
StackVec & operator = ( StackVec & & rhs ) noexcept {
2021-07-22 18:51:08 +00:00
if ( this = = & rhs ) {
return * this ;
}
2017-12-21 00:45:38 +01:00
clear ( ) ;
2020-02-24 22:07:46 +01:00
if ( rhs . usesDynamicMem ( ) ) {
if ( usesDynamicMem ( ) ) {
delete this - > dynamicMem ;
}
this - > dynamicMem = rhs . dynamicMem ;
2024-09-13 14:30:14 +00:00
rhs . switchToStackMem ( ) ;
2017-12-21 00:45:38 +01:00
return * this ;
}
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
this - > dynamicMem - > assign ( rhs . begin ( ) , rhs . end ( ) ) ;
2017-12-21 00:45:38 +01:00
return * this ;
}
for ( const auto & v : rhs ) {
push_back ( v ) ;
}
2020-02-24 22:07:46 +01:00
rhs . clear ( ) ;
2017-12-21 00:45:38 +01:00
return * this ;
}
2025-02-26 14:32:25 +00:00
template < typename T >
constexpr iterator insert ( const_iterator pos , T & & value ) {
auto offset = pos - begin ( ) ;
push_back ( std : : forward < T > ( value ) ) ;
std : : rotate ( begin ( ) + offset , end ( ) - 1 , end ( ) ) ;
return begin ( ) + offset ;
}
2022-03-02 18:51:53 +00:00
template < typename RhsT >
void swap ( RhsT & rhs ) {
if ( this - > usesDynamicMem ( ) & & rhs . usesDynamicMem ( ) ) {
this - > dynamicMem - > swap ( * rhs . dynamicMem ) ;
return ;
}
size_t smallerSize = this - > size ( ) < rhs . size ( ) ? this - > size ( ) : rhs . size ( ) ;
size_t i = 0 ;
for ( ; i < smallerSize ; + + i ) {
std : : swap ( ( * this ) [ i ] , rhs [ i ] ) ;
}
if ( this - > size ( ) = = smallerSize ) {
auto biggerSize = rhs . size ( ) ;
for ( ; i < biggerSize ; + + i ) {
this - > push_back ( std : : move ( rhs [ i ] ) ) ;
}
rhs . resize ( smallerSize ) ;
} else {
auto biggerSize = this - > size ( ) ;
for ( ; i < biggerSize ; + + i ) {
rhs . push_back ( std : : move ( ( * this ) [ i ] ) ) ;
}
this - > resize ( smallerSize ) ;
}
}
2017-12-21 00:45:38 +01:00
~ StackVec ( ) {
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
2017-12-21 00:45:38 +01:00
delete dynamicMem ;
return ;
}
2020-02-24 22:07:46 +01:00
clearStackObjects ( ) ;
2017-12-21 00:45:38 +01:00
}
size_t size ( ) const {
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
2017-12-21 00:45:38 +01:00
return dynamicMem - > size ( ) ;
}
return onStackSize ;
}
2019-10-27 19:48:26 +01:00
bool empty ( ) const {
return 0U = = size ( ) ;
}
2017-12-21 00:45:38 +01:00
size_t capacity ( ) const {
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
2017-12-21 00:45:38 +01:00
return dynamicMem - > capacity ( ) ;
}
2023-11-30 10:36:43 +00:00
return onStackCapacity ;
2017-12-21 00:45:38 +01:00
}
void reserve ( size_t newCapacity ) {
if ( newCapacity > onStackCaps ) {
ensureDynamicMem ( ) ;
dynamicMem - > reserve ( newCapacity ) ;
}
}
void clear ( ) {
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
2017-12-21 00:45:38 +01:00
dynamicMem - > clear ( ) ;
return ;
}
2018-01-05 12:54:12 +01:00
clearStackObjects ( ) ;
2017-12-21 00:45:38 +01:00
}
2022-05-09 17:40:30 +00:00
void push_back ( const DataType & v ) { // NOLINT(readability-identifier-naming)
2022-07-20 15:05:27 +00:00
isDynamicMemNeeded ( ) ;
2017-12-21 00:45:38 +01:00
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
2017-12-21 00:45:38 +01:00
dynamicMem - > push_back ( v ) ;
return ;
}
2020-02-24 22:07:46 +01:00
new ( reinterpret_cast < DataType * > ( onStackMemRawBytes ) + onStackSize ) DataType ( v ) ;
2017-12-21 00:45:38 +01:00
+ + onStackSize ;
}
2022-07-20 15:05:27 +00:00
void push_back ( DataType & & v ) { // NOLINT(readability-identifier-naming)
isDynamicMemNeeded ( ) ;
if ( usesDynamicMem ( ) ) {
dynamicMem - > push_back ( std : : move ( v ) ) ;
return ;
}
new ( reinterpret_cast < DataType * > ( onStackMemRawBytes ) + onStackSize ) DataType ( std : : move ( v ) ) ;
+ + onStackSize ;
}
2022-05-09 17:40:30 +00:00
void pop_back ( ) { // NOLINT(readability-identifier-naming)
2020-05-25 16:39:16 +02:00
if ( usesDynamicMem ( ) ) {
dynamicMem - > pop_back ( ) ;
return ;
}
UNRECOVERABLE_IF ( 0 = = onStackSize ) ;
clearStackObjects ( onStackSize - 1 , 1U ) ;
- - onStackSize ;
}
2017-12-21 00:45:38 +01:00
DataType & operator [ ] ( std : : size_t idx ) {
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
2017-12-21 00:45:38 +01:00
return ( * dynamicMem ) [ idx ] ;
}
2020-02-24 22:07:46 +01:00
return * ( reinterpret_cast < DataType * > ( onStackMemRawBytes ) + idx ) ;
2017-12-21 00:45:38 +01:00
}
2022-03-02 18:51:53 +00:00
DataType & at ( std : : size_t idx ) { return this - > operator [ ] ( idx ) ; }
const DataType & at ( std : : size_t idx ) const { return this - > operator [ ] ( idx ) ; }
2017-12-21 00:45:38 +01:00
const DataType & operator [ ] ( std : : size_t idx ) const {
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
2017-12-21 00:45:38 +01:00
return ( * dynamicMem ) [ idx ] ;
}
2020-02-24 22:07:46 +01:00
return * ( reinterpret_cast < const DataType * > ( onStackMemRawBytes ) + idx ) ;
2017-12-21 00:45:38 +01:00
}
2018-01-05 12:54:12 +01:00
iterator begin ( ) {
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
2017-12-21 00:45:38 +01:00
return dynamicMem - > data ( ) ;
}
2020-02-24 22:07:46 +01:00
return reinterpret_cast < DataType * > ( onStackMemRawBytes ) ;
2017-12-21 00:45:38 +01:00
}
2018-12-17 15:23:35 +01:00
reverse_iterator rbegin ( ) {
return reverse_iterator ( end ( ) ) ;
}
const_reverse_iterator crbegin ( ) const {
return const_reverse_iterator ( end ( ) ) ;
}
2018-01-05 12:54:12 +01:00
const_iterator begin ( ) const {
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
2017-12-21 00:45:38 +01:00
return dynamicMem - > data ( ) ;
}
2020-02-24 22:07:46 +01:00
return reinterpret_cast < const DataType * > ( onStackMemRawBytes ) ;
2017-12-21 00:45:38 +01:00
}
2018-01-05 12:54:12 +01:00
iterator end ( ) {
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
2017-12-21 00:45:38 +01:00
return dynamicMem - > data ( ) + dynamicMem - > size ( ) ;
}
2020-02-24 22:07:46 +01:00
return reinterpret_cast < DataType * > ( onStackMemRawBytes ) + onStackSize ;
2017-12-21 00:45:38 +01:00
}
2018-12-17 15:23:35 +01:00
reverse_iterator rend ( ) {
return reverse_iterator ( begin ( ) ) ;
}
const_reverse_iterator crend ( ) const {
return const_reverse_iterator ( begin ( ) ) ;
}
2018-01-05 12:54:12 +01:00
const_iterator end ( ) const {
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
2017-12-21 00:45:38 +01:00
return dynamicMem - > data ( ) + dynamicMem - > size ( ) ;
}
2020-02-24 22:07:46 +01:00
return reinterpret_cast < const DataType * > ( onStackMemRawBytes ) + onStackSize ;
2017-12-21 00:45:38 +01:00
}
2018-01-05 12:54:12 +01:00
void resize ( size_t newSize ) {
2025-07-22 10:48:57 +00:00
this - > resizeImpl ( newSize ) ;
2018-01-05 12:54:12 +01:00
}
void resize ( size_t newSize , const DataType & value ) {
2025-07-22 10:48:57 +00:00
resizeImpl ( newSize , value ) ;
2018-01-05 12:54:12 +01:00
}
2020-02-24 22:07:46 +01:00
bool usesDynamicMem ( ) const {
2024-09-13 14:30:14 +00:00
return reinterpret_cast < uintptr_t > ( this - > onStackMem ) ! = reinterpret_cast < uintptr_t > ( onStackMemRawBytes ) & & this - > dynamicMem ;
2020-02-24 22:07:46 +01:00
}
2025-02-26 14:32:25 +00:00
DataType * data ( ) {
2020-06-09 14:17:19 +02:00
if ( usesDynamicMem ( ) ) {
return dynamicMem - > data ( ) ;
}
2020-10-16 12:41:41 +02:00
return reinterpret_cast < DataType * > ( onStackMemRawBytes ) ;
2020-06-09 14:17:19 +02:00
}
2025-02-26 14:32:25 +00:00
const DataType * data ( ) const {
if ( usesDynamicMem ( ) ) {
return dynamicMem - > data ( ) ;
}
return reinterpret_cast < const DataType * > ( onStackMemRawBytes ) ;
}
2018-01-05 12:54:12 +01:00
private :
2023-11-30 10:36:43 +00:00
template < typename RhsDataType , size_t rhsOnStackCapacity , typename RhsStackSizeT >
2022-03-02 18:51:53 +00:00
friend class StackVec ;
2020-02-24 22:07:46 +01:00
2025-07-22 10:48:57 +00:00
template < typename . . . OptValueT >
void resizeImpl ( size_t newSize , OptValueT & & . . . optValue ) {
constexpr bool nonDefaultInitializer = sizeof . . . ( OptValueT ) > 0 ;
static_assert ( ! nonDefaultInitializer | | std : : is_copy_constructible < DataType > ( ) , " Stackvec cannot resize with value if DataType is not copy-constructible! " ) ;
2018-01-05 12:54:12 +01:00
// new size does not fit into internal mem
if ( newSize > onStackCaps ) {
2017-12-21 00:45:38 +01:00
ensureDynamicMem ( ) ;
2018-01-05 12:54:12 +01:00
}
// memory already backed by stl vector
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
2025-07-22 10:48:57 +00:00
if constexpr ( nonDefaultInitializer ) {
dynamicMem - > resize ( newSize , std : : forward < OptValueT > ( optValue ) . . . ) ;
2018-01-05 12:54:12 +01:00
} else {
dynamicMem - > resize ( newSize ) ;
}
return ;
}
2024-09-19 09:45:55 +00:00
auto currentSize = std : : min ( onStackSize , onStackCaps ) ;
if ( newSize < = currentSize ) {
2018-01-05 12:54:12 +01:00
// trim elements
2024-09-19 09:45:55 +00:00
clearStackObjects ( newSize , currentSize - newSize ) ;
2020-02-24 22:07:46 +01:00
onStackSize = static_cast < SizeT > ( newSize ) ;
2018-01-05 12:54:12 +01:00
return ;
}
2025-07-22 10:48:57 +00:00
while ( onStackSize < newSize ) {
if constexpr ( nonDefaultInitializer ) {
new ( reinterpret_cast < DataType * > ( onStackMemRawBytes ) + onStackSize ) DataType ( std : : forward < OptValueT > ( optValue ) . . . ) ;
} else {
2020-02-24 22:07:46 +01:00
new ( reinterpret_cast < DataType * > ( onStackMemRawBytes ) + onStackSize ) DataType ( ) ;
2018-01-05 12:54:12 +01:00
}
2025-07-22 10:48:57 +00:00
+ + onStackSize ;
2017-12-21 00:45:38 +01:00
}
}
2022-07-20 15:05:27 +00:00
void isDynamicMemNeeded ( ) {
if ( onStackSize = = onStackCaps ) {
ensureDynamicMem ( ) ;
}
}
2017-12-21 00:45:38 +01:00
void ensureDynamicMem ( ) {
2020-02-24 22:07:46 +01:00
if ( usesDynamicMem ( ) ) {
return ;
}
dynamicMem = new std : : vector < DataType > ( ) ;
if ( onStackSize > 0 ) {
dynamicMem - > reserve ( onStackSize ) ;
for ( auto it = reinterpret_cast < DataType * > ( onStackMemRawBytes ) , end = reinterpret_cast < DataType * > ( onStackMemRawBytes ) + onStackSize ; it ! = end ; + + it ) {
dynamicMem - > push_back ( std : : move ( * it ) ) ;
2017-12-21 00:45:38 +01:00
}
2020-02-24 22:07:46 +01:00
clearStackObjects ( ) ;
2017-12-21 00:45:38 +01:00
}
}
2018-01-05 12:54:12 +01:00
void clearStackObjects ( ) {
clearStackObjects ( 0 , onStackSize ) ;
onStackSize = 0 ;
}
void clearStackObjects ( size_t offset , size_t count ) {
UNRECOVERABLE_IF ( offset + count > onStackSize ) ;
2020-02-24 22:07:46 +01:00
for ( auto it = reinterpret_cast < DataType * > ( onStackMemRawBytes ) + offset , end = reinterpret_cast < DataType * > ( onStackMemRawBytes ) + offset + count ; it ! = end ; + + it ) {
2017-12-21 00:45:38 +01:00
it - > ~ DataType ( ) ;
}
}
2024-09-13 14:30:14 +00:00
void switchToStackMem ( ) {
onStackMem = reinterpret_cast < DataType * const > ( onStackMemRawBytes ) ;
}
2017-12-21 00:45:38 +01:00
2020-02-24 22:07:46 +01:00
union {
std : : vector < DataType > * dynamicMem ;
DataType * onStackMem ;
} ;
2023-08-25 11:01:12 +02:00
alignas ( alignof ( DataType ) ) char onStackMemRawBytes [ sizeof ( DataType [ onStackCaps ] ) ] ;
2020-02-24 22:07:46 +01:00
SizeT onStackSize = 0U ;
2017-12-21 00:45:38 +01:00
} ;
2018-01-05 12:54:12 +01:00
2020-02-24 22:07:46 +01:00
namespace {
static_assert ( sizeof ( StackVec < char , 1U > : : SizeT ) = = 1u , " " ) ;
static_assert ( sizeof ( StackVec < char , 7U > ) < = 16u , " " ) ;
static_assert ( sizeof ( StackVec < uint32_t , 3U > ) < = 24u , " " ) ;
} // namespace
2023-11-30 10:36:43 +00:00
template < typename T , size_t lhsStackCaps , size_t rhsStackCaps >
bool operator = = ( const StackVec < T , lhsStackCaps > & lhs ,
const StackVec < T , rhsStackCaps > & rhs ) {
2018-01-05 12:54:12 +01:00
if ( lhs . size ( ) ! = rhs . size ( ) ) {
return false ;
}
auto lhsIt = lhs . begin ( ) ;
auto lhsEnd = lhs . end ( ) ;
auto rhsIt = rhs . begin ( ) ;
for ( ; lhsIt ! = lhsEnd ; + + lhsIt , + + rhsIt ) {
if ( * lhsIt ! = * rhsIt ) {
return false ;
}
}
return true ;
}
2019-01-28 14:26:33 +01:00
2023-11-30 10:36:43 +00:00
template < typename T , size_t lhsStackCaps , size_t rhsStackCaps >
bool operator ! = ( const StackVec < T , lhsStackCaps > & lhs ,
const StackVec < T , rhsStackCaps > & rhs ) {
2019-01-28 14:26:33 +01:00
return false = = ( lhs = = rhs ) ;
}
2022-04-07 13:09:40 +00:00
2023-11-30 10:36:43 +00:00
constexpr size_t maxRootDeviceIndices = 16 ;
class RootDeviceIndicesContainer : protected StackVec < uint32_t , maxRootDeviceIndices > {
2023-06-12 13:52:45 +00:00
public :
2023-11-30 10:36:43 +00:00
using StackVec < uint32_t , maxRootDeviceIndices > : : StackVec ;
using StackVec < uint32_t , maxRootDeviceIndices > : : at ;
using StackVec < uint32_t , maxRootDeviceIndices > : : begin ;
using StackVec < uint32_t , maxRootDeviceIndices > : : end ;
using StackVec < uint32_t , maxRootDeviceIndices > : : size ;
using StackVec < uint32_t , maxRootDeviceIndices > : : operator [ ] ;
2023-06-12 13:52:45 +00:00
inline void pushUnique ( uint32_t rootDeviceIndex ) {
2023-09-05 15:33:39 +00:00
if ( indexPresent . size ( ) < = rootDeviceIndex ) {
indexPresent . resize ( rootDeviceIndex + 1 ) ;
}
if ( ! indexPresent [ rootDeviceIndex ] ) {
2023-06-12 13:52:45 +00:00
push_back ( rootDeviceIndex ) ;
2023-09-05 15:33:39 +00:00
indexPresent [ rootDeviceIndex ] = 1 ;
2023-06-12 13:52:45 +00:00
}
}
protected :
2023-11-30 10:36:43 +00:00
StackVec < int8_t , maxRootDeviceIndices > indexPresent ;
2023-06-12 13:52:45 +00:00
} ;
2023-11-30 10:36:43 +00:00
using RootDeviceIndicesMap = StackVec < std : : tuple < uint32_t , uint32_t > , maxRootDeviceIndices > ;