diff --git a/renderdoc/api/replay/renderdoc_replay.h b/renderdoc/api/replay/renderdoc_replay.h index 89bdc3fa0..e14c4d165 100644 --- a/renderdoc/api/replay/renderdoc_replay.h +++ b/renderdoc/api/replay/renderdoc_replay.h @@ -206,6 +206,144 @@ typedef void(RENDERDOC_CC *pRENDERDOC_FreeArrayMem)(const void *mem); extern "C" RENDERDOC_API void *RENDERDOC_CC RENDERDOC_AllocArrayMem(uint64_t sz); typedef void *(RENDERDOC_CC *pRENDERDOC_AllocArrayMem)(uint64_t sz); +#ifdef NO_ENUM_CLASS_OPERATORS + +#define BITMASK_OPERATORS(a) +#define ITERABLE_OPERATORS(a) + +#else + +#include + +// helper template that allows the result of & to be cast back to the enum or explicitly cast to +// bool for use in if() or ?: or so on or compared against 0. +// +// If you get an error about missing operator then you're probably doing something like +// (bitfield & value) == 0 or (bitfield & value) != 0 or similar. Instead prefer: +// !(bitfield & value) or (bitfield & value) to make use of the bool cast directly +template +struct EnumCastHelper +{ +public: + constexpr EnumCastHelper(enum_name v) : val(v) {} + constexpr operator enum_name() const { return val; } + constexpr explicit operator bool() const + { + typedef typename std::underlying_type::type etype; + return etype(val) != 0; + } + +private: + const enum_name val; +}; + +// helper templates for iterating over all values in an enum that has sequential values and is +// to be used for array indices or something like that. +template +struct ValueIterContainer +{ + struct ValueIter + { + ValueIter(enum_name v) : val(v) {} + enum_name val; + enum_name operator*() const { return val; } + bool operator!=(const ValueIter &it) const { return !(val == *it); } + const inline enum_name operator++() + { + ++val; + return val; + } + }; + + ValueIter begin() { return ValueIter(enum_name::First); } + ValueIter end() { return ValueIter(enum_name::Count); } +}; + +template +struct IndexIterContainer +{ + typedef typename std::underlying_type::type etype; + + struct IndexIter + { + IndexIter(enum_name v) : val(v) {} + enum_name val; + etype operator*() const { return etype(val); } + bool operator!=(const IndexIter &it) const { return !(val == it.val); } + const inline enum_name operator++() + { + ++val; + return val; + } + }; + + IndexIter begin() { return IndexIter(enum_name::First); } + IndexIter end() { return IndexIter(enum_name::Count); } +}; + +template +constexpr inline ValueIterContainer values() +{ + return ValueIterContainer(); +}; + +template +constexpr inline IndexIterContainer indices() +{ + return IndexIterContainer(); +}; + +template +constexpr inline size_t arraydim() +{ + typedef typename std::underlying_type::type etype; + return (size_t)etype(enum_name::Count); +}; + +// clang-format makes a even more of a mess of this multi-line macro than it usually does, for some +// reason. So we just disable it since it's still readable and this isn't really the intended case +// we are using clang-format for. + +// clang-format off +#define BITMASK_OPERATORS(enum_name) \ + \ +constexpr inline enum_name operator|(enum_name a, enum_name b) \ +{ \ + typedef typename std::underlying_type::type etype; \ + return enum_name(etype(a) | etype(b)); \ +} \ + \ +constexpr inline EnumCastHelper operator&(enum_name a, enum_name b) \ +{ \ + typedef typename std::underlying_type::type etype; \ + return EnumCastHelper(enum_name(etype(a) & etype(b))); \ +} \ + \ +constexpr inline enum_name operator~(enum_name a) \ +{ \ + typedef typename std::underlying_type::type etype; \ + return enum_name(~etype(a)); \ +} \ + \ +inline enum_name &operator|=(enum_name &a, enum_name b) \ +{ return a = a | b; } \ + \ +inline enum_name &operator&=(enum_name &a, enum_name b) \ +{ return a = a & b; } + +#define ITERABLE_OPERATORS(enum_name) \ + \ +inline enum_name operator++(enum_name &a) \ +{ \ + typedef typename std::underlying_type::type etype; \ + return a = enum_name(etype(a)+1); \ +} +// clang-format on + +#endif + +#define ENUM_ARRAY_SIZE(enum_name) size_t(enum_name::Count) + #include "basic_types.h" #ifdef RENDERDOC_EXPORTS diff --git a/renderdoc/api/replay/replay_enums.h b/renderdoc/api/replay/replay_enums.h index 59e1196dc..49f49cec2 100644 --- a/renderdoc/api/replay/replay_enums.h +++ b/renderdoc/api/replay/replay_enums.h @@ -25,144 +25,6 @@ #pragma once -#ifdef NO_ENUM_CLASS_OPERATORS - -#define BITMASK_OPERATORS(a) -#define ITERABLE_OPERATORS(a) - -#else - -#include - -// helper template that allows the result of & to be cast back to the enum or explicitly cast to -// bool for use in if() or ?: or so on or compared against 0. -// -// If you get an error about missing operator then you're probably doing something like -// (bitfield & value) == 0 or (bitfield & value) != 0 or similar. Instead prefer: -// !(bitfield & value) or (bitfield & value) to make use of the bool cast directly -template -struct EnumCastHelper -{ -public: - constexpr EnumCastHelper(enum_name v) : val(v) {} - constexpr operator enum_name() const { return val; } - constexpr explicit operator bool() const - { - typedef typename std::underlying_type::type etype; - return etype(val) != 0; - } - -private: - const enum_name val; -}; - -// helper templates for iterating over all values in an enum that has sequential values and is -// to be used for array indices or something like that. -template -struct ValueIterContainer -{ - struct ValueIter - { - ValueIter(enum_name v) : val(v) {} - enum_name val; - enum_name operator*() const { return val; } - bool operator!=(const ValueIter &it) const { return !(val == *it); } - const inline enum_name operator++() - { - ++val; - return val; - } - }; - - ValueIter begin() { return ValueIter(enum_name::First); } - ValueIter end() { return ValueIter(enum_name::Count); } -}; - -template -struct IndexIterContainer -{ - typedef typename std::underlying_type::type etype; - - struct IndexIter - { - IndexIter(enum_name v) : val(v) {} - enum_name val; - etype operator*() const { return etype(val); } - bool operator!=(const IndexIter &it) const { return !(val == it.val); } - const inline enum_name operator++() - { - ++val; - return val; - } - }; - - IndexIter begin() { return IndexIter(enum_name::First); } - IndexIter end() { return IndexIter(enum_name::Count); } -}; - -template -constexpr inline ValueIterContainer values() -{ - return ValueIterContainer(); -}; - -template -constexpr inline IndexIterContainer indices() -{ - return IndexIterContainer(); -}; - -template -constexpr inline size_t arraydim() -{ - typedef typename std::underlying_type::type etype; - return (size_t)etype(enum_name::Count); -}; - -// clang-format makes a even more of a mess of this multi-line macro than it usually does, for some -// reason. So we just disable it since it's still readable and this isn't really the intended case -// we are using clang-format for. - -// clang-format off -#define BITMASK_OPERATORS(enum_name) \ - \ -constexpr inline enum_name operator|(enum_name a, enum_name b) \ -{ \ - typedef typename std::underlying_type::type etype; \ - return enum_name(etype(a) | etype(b)); \ -} \ - \ -constexpr inline EnumCastHelper operator&(enum_name a, enum_name b) \ -{ \ - typedef typename std::underlying_type::type etype; \ - return EnumCastHelper(enum_name(etype(a) & etype(b))); \ -} \ - \ -constexpr inline enum_name operator~(enum_name a) \ -{ \ - typedef typename std::underlying_type::type etype; \ - return enum_name(~etype(a)); \ -} \ - \ -inline enum_name &operator|=(enum_name &a, enum_name b) \ -{ return a = a | b; } \ - \ -inline enum_name &operator&=(enum_name &a, enum_name b) \ -{ return a = a & b; } - -#define ITERABLE_OPERATORS(enum_name) \ - \ -inline enum_name operator++(enum_name &a) \ -{ \ - typedef typename std::underlying_type::type etype; \ - return a = enum_name(etype(a)+1); \ -} -// clang-format on - -#endif - -#define ENUM_ARRAY_SIZE(enum_name) size_t(enum_name::Count) - DOCUMENT(R"(A set of flags describing the properties of a path on a remote filesystem. .. data:: NoFlags