将Vulkan的MemoryPropertyFlags转换为MemoryPropertyFlagBits。

huangapple go评论71阅读模式
英文:

Convert Vulkan MemoryPropertyFlags to MemoryPropertyFlagBits

问题

在Vulkan C++ API中,physical_device.getMemoryProperties().memoryTypes返回一个名为MemoryPropertyFlags的实例,也叫做Flags<MemoryPropertyFlagBits>
我想要简单地恢复位掩码,以便轻松与MemoryPropertyFlagBits匹配,用于缓冲区创建请求。

我意识到这是一个简单的问题,但由于某种原因,我无法找到有关Flags和导航头文件的任何信息。从clang的自动完成中,我只知道Flags有一些二进制操作符。

英文:

In the Vulkan c++ API, physical_device.getMemoryProperties().memoryTypes returns an instance of MemoryPropertyFlags, aka Flags<MemoryPropertyFlagBits>.
I'd like to simply recover the bit mask to easily match it with MemoryPropertyFlagBits for buffer creation requests.

I realize it is a simple question but for some reason I am unable to find any information on Flags and navigating though the headers leads me nowhere. All I know from clang completion is that Flags has a few binary operators.

答案1

得分: 1

在vulkan.hpp中,Flags类被定义如下:

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

    // 构造函数
    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) {}

    // 关系运算符
#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

    // 逻辑运算符
    constexpr bool operator!() const noexcept
    {
        return !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^(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);
    }

    // 赋值运算符
    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;
    }

    // 强制类型转换运算符
    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之间的转换应该是隐式的。

英文:

In vulkan.hpp the Flags class is defined as

template &lt;typename BitType&gt;
class Flags
{
public:
    using MaskType = typename std::underlying_type&lt;BitType&gt;::type;

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

    constexpr Flags( BitType bit ) noexcept : m_mask( static_cast&lt;MaskType&gt;( bit ) ) {}

    constexpr Flags( Flags&lt;BitType&gt; const &amp; rhs ) noexcept = default;

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

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

    constexpr bool operator&lt;=( Flags&lt;BitType&gt; const &amp; rhs ) const noexcept
    {
        return m_mask &lt;= rhs.m_mask;
    }

    constexpr bool operator&gt;( Flags&lt;BitType&gt; const &amp; rhs ) const noexcept
    {
        return m_mask &gt; rhs.m_mask;
    }

    constexpr bool operator&gt;=( Flags&lt;BitType&gt; const &amp; rhs ) const noexcept
    {
        return m_mask &gt;= rhs.m_mask;
    }

    constexpr bool operator==( Flags&lt;BitType&gt; const &amp; rhs ) const noexcept
    {
        return m_mask == rhs.m_mask;
    }

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

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

    // bitwise operators
    constexpr Flags&lt;BitType&gt; operator&amp;( Flags&lt;BitType&gt; const &amp; rhs ) const noexcept
    {
        return Flags&lt;BitType&gt;( m_mask &amp; rhs.m_mask );
    }

    constexpr Flags&lt;BitType&gt; operator|( Flags&lt;BitType&gt; const &amp; rhs ) const noexcept
    {
        return Flags&lt;BitType&gt;( m_mask | rhs.m_mask );
    }

    constexpr Flags&lt;BitType&gt; operator^( Flags&lt;BitType&gt; const &amp; rhs ) const noexcept
    {
        return Flags&lt;BitType&gt;( m_mask ^ rhs.m_mask );
    }

    constexpr Flags&lt;BitType&gt; operator~() const noexcept
    {
        return Flags&lt;BitType&gt;( m_mask ^ FlagTraits&lt;BitType&gt;::allFlags.m_mask );
    }

    // assignment operators
    constexpr Flags&lt;BitType&gt; &amp; operator=( Flags&lt;BitType&gt; const &amp; rhs ) noexcept = default;

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

    constexpr Flags&lt;BitType&gt; &amp; operator&amp;=( Flags&lt;BitType&gt; const &amp; rhs ) noexcept
    {
        m_mask &amp;= rhs.m_mask;
        return *this;
    }

    constexpr Flags&lt;BitType&gt; &amp; operator^=( Flags&lt;BitType&gt; const &amp; 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;
};

The Flags class can be constructed by passing in the bit type, or the underlying type (VkMemoryPropertyFlagBits is an enum, and the underlying type is probably going to be something like an int). There is an explicit operator to get out the underlying value, which can be accessed by static casting the Flags class to the underlying type. You can also declare VULKAN_HPP_FLAGS_MASK_TYPE_AS_PUBLIC in your compile flags and access the mask directly. There are of course also all necessary operators defined to interact with the Flags class as if it were a raw integer.

Given VkFlags is a uint32_t I'm not sure why they don't offer an implicit or explicit cast to VkFlags.

The safest way would probably be

vk::Flags&lt;VkMemoryPropertyFlagBits&gt; flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
VkFlags vkFlags = static_cast&lt;decltype(flags)::MaskType&gt;(flags);

This will always cast it to the correct type (using the wrong type will produce a compile error), and the conversion between MaskType and VkFlags should be implicit.

huangapple
  • 本文由 发表于 2023年5月25日 17:44:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76330930.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定