c++ 将Vulkan MemoryPropertyFlags转换为MemoryPropertyFlagBits

hmmo2u0o  于 2023-05-30  发布在  其他
关注(0)|答案(1)|浏览(118)

在Vulkan c++ API中,physical_device.getMemoryProperties().memoryTypes返回MemoryPropertyFlags的示例,也称为Flags<MemoryPropertyFlagBits>。我想简单地恢复位掩码,以便轻松地将其与MemoryPropertyFlagBits匹配,用于缓冲区创建请求。
我意识到这是一个简单的问题,但由于某种原因,我无法找到任何信息的旗帜和导航,虽然标题导致我无处可去。从clang completion中我所知道的是Flags有一些二元运算符。

mwg9r5ms

mwg9r5ms1#

在vulkan.hpp中,Flags类定义为

template <typename BitType>
class Flags
{
public:
    using MaskType = typename std::underlying_type<BitType>::type;

    // constructors
    constexpr Flags() noexcept : m_mask( 0 ) {}

    constexpr Flags( BitType bit ) noexcept : m_mask( static_cast<MaskType>( bit ) ) {}

    constexpr Flags( Flags<BitType> const & rhs ) noexcept = default;

    constexpr explicit Flags( MaskType flags ) noexcept : m_mask( flags ) {}

    // relational operators
#if defined( VULKAN_HPP_HAS_SPACESHIP_OPERATOR )
    auto operator<=>( Flags<BitType> const & ) const = default;
#else
    constexpr bool operator<( Flags<BitType> const & rhs ) const noexcept
    {
        return m_mask < rhs.m_mask;
    }

    constexpr bool operator<=( Flags<BitType> const & rhs ) const noexcept
    {
        return m_mask <= rhs.m_mask;
    }

    constexpr bool operator>( Flags<BitType> const & rhs ) const noexcept
    {
        return m_mask > rhs.m_mask;
    }

    constexpr bool operator>=( Flags<BitType> const & rhs ) const noexcept
    {
        return m_mask >= rhs.m_mask;
    }

    constexpr bool operator==( Flags<BitType> const & rhs ) const noexcept
    {
        return m_mask == rhs.m_mask;
    }

    constexpr bool operator!=( Flags<BitType> const & rhs ) const noexcept
    {
        return m_mask != rhs.m_mask;
    }
#endif

    // logical operator
    constexpr bool operator!() const noexcept
    {
        return !m_mask;
    }

    // bitwise operators
    constexpr Flags<BitType> operator&( Flags<BitType> const & rhs ) const noexcept
    {
        return Flags<BitType>( m_mask & rhs.m_mask );
    }

    constexpr Flags<BitType> operator|( Flags<BitType> const & rhs ) const noexcept
    {
        return Flags<BitType>( m_mask | rhs.m_mask );
    }

    constexpr Flags<BitType> operator^( Flags<BitType> const & rhs ) const noexcept
    {
        return Flags<BitType>( m_mask ^ rhs.m_mask );
    }

    constexpr Flags<BitType> operator~() const noexcept
    {
        return Flags<BitType>( m_mask ^ FlagTraits<BitType>::allFlags.m_mask );
    }

    // assignment operators
    constexpr Flags<BitType> & operator=( Flags<BitType> const & rhs ) noexcept = default;

    constexpr Flags<BitType> & operator|=( Flags<BitType> const & rhs ) noexcept
    {
        m_mask |= rhs.m_mask;
        return *this;
    }

    constexpr Flags<BitType> & operator&=( Flags<BitType> const & rhs ) noexcept
    {
        m_mask &= rhs.m_mask;
        return *this;
    }

    constexpr Flags<BitType> & operator^=( Flags<BitType> const & rhs ) noexcept
    {
        m_mask ^= rhs.m_mask;
        return *this;
    }

    // cast operators
    explicit constexpr operator bool() const noexcept
    {
        return !!m_mask;
    }

    explicit constexpr operator MaskType() const noexcept
    {
        return m_mask;
    }

#if defined( VULKAN_HPP_FLAGS_MASK_TYPE_AS_PUBLIC )
public:
#else
private:
#endif
    MaskType m_mask;
};

Flags类可以通过传入位类型或底层类型(VkMemoryPropertyFlagBits是一个枚举,底层类型可能类似于int)来构造。有一个显式的运算符来获取基础值,可以通过将Flags类静态转换为基础类型来访问该值。您也可以在编译标志中声明VULKAN_HPP_FLAGS_MASK_TYPE_AS_PUBLIC,并直接访问掩码。当然,还定义了所有必要的操作符,以与Flags类交互,就好像它是一个原始整数一样。
假设VkFlags是一个uint32_t,我不知道为什么他们不提供VkFlags的隐式或显式转换。
最安全的方法可能是

vk::Flags<VkMemoryPropertyFlagBits> flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
VkFlags vkFlags = static_cast<decltype(flags)::MaskType>(flags);

这将始终将其转换为正确的类型(使用错误的类型将产生编译错误),并且MaskTypeVkFlags之间的转换应该是隐式的。

相关问题