英文:
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);
这将始终将其转换为正确的类型(使用错误的类型将产生编译错误),并且MaskType
与VkFlags
之间的转换应该是隐式的。
英文:
In vulkan.hpp the Flags class is defined as
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;
};
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<VkMemoryPropertyFlagBits> flags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
VkFlags vkFlags = static_cast<decltype(flags)::MaskType>(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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论