Introduce MergeInto helper for simplified construction of arrays of structs

In the upcoming GPU code each state member will hold a reference to its corresponding Maxwell 3D regs, this helper is needed to allow easy transformation from the the main 3D register struct into them.

Example:
```c++
struct Regs {
    std::array<View, 10> viewRegs;
    u32 enable;
} regs;

struct ViewState {
    const View &view;
    const u32 &enable;
    size_t index;
};

std::array<ViewState, 10> viewStates{MergeInto<ViewState, 10>(regs.viewRegs, regs.enable, IncrementingT{})
```
This commit is contained in:
Billy Laws 2022-08-31 13:39:16 +01:00
parent 2c682f19a6
commit 64a9db2e82

View File

@ -8,6 +8,7 @@
#include <span>
#include <frozen/unordered_map.h>
#include <frozen/string.h>
#include <type_traits>
#include <xxhash.h>
#include "base.h"
#include "exception.h"
@ -309,4 +310,43 @@ namespace skyline::util {
std::array<T, Size> MakeFilledArray(TArgs &&... args) {
return MakeFilledArray<T>(std::make_index_sequence<Size>(), std::forward<TArgs>(args)...);
}
template<typename T>
struct IncrementingT {
using Type = T;
};
template<typename T>
struct IsIncrementingT : std::false_type {};
template<typename T>
struct IsIncrementingT<IncrementingT<T>> : std::true_type {};
template<typename T, size_t Index, typename... TSrcs>
T MakeMergeElem(TSrcs &&... srcs) {
auto readElem{[index = Index](auto &&src) -> decltype(auto) {
using SrcType = std::decay_t<decltype(src)>;
if constexpr (requires { src[Index]; })
return src[Index];
else if constexpr (IsIncrementingT<SrcType>{})
return static_cast<typename SrcType::Type>(index);
else
return src;
}};
return T{readElem(std::forward<TSrcs>(srcs))...};
}
template<typename T, size_t... Is, typename... TSrcs>
std::array<T, sizeof...(Is)> MergeInto(std::index_sequence<Is...> seq, TSrcs &&... srcs) {
return {MakeMergeElem<T, Is>(std::forward<TSrcs>(srcs)...)...};
}
/**
* @brief Constructs {{scalar0, array0[0], array1[0], ... arrayN[0], scalar1}, {scalar0, array0[1], array1[1]. ... arrayN[1], scalar0}, ...}
*/
template<typename T, size_t Size, typename... TSrcs>
std::array<T, Size> MergeInto(TSrcs &&... srcs) {
return MergeInto<T>(std::make_index_sequence<Size>(), std::forward<TSrcs>(srcs)...);
}
}