【发布时间】:2020-07-27 08:13:10
【问题描述】:
在大多数情况下,您可以将VK_NULL_HANDLE 分配给VK_DEFINE_HANDLE(object) 或VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) 定义的任何句柄,但std::exchange() 几乎在所有情况下都无法设置此值。
在大多数情况下,我必须致电 std::exchange(m_dispatchableHandle, nullptr) 和 std::exchange(m_nonDispatchableHandle, nullptr)
但是,在 x86 上,由于重新定义了 VK_DEFINE_NON_DISPATCHABLE_HANDLE,nullptr 无效。我必须将std::exchange 与NULL、0 或(最后)VK_NULL_HANDLE 一起使用。
我的问题:在遵循VK_DEFINE_HANDLE 宏模式时,不应该有两个如下定义的空句柄宏吗?
#define VK_NULL_HANDLE nullptr
#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
#define VK_NON_DISPATCHABLE_NULL_HANDLE nullptr
#else
#define VK_NON_DISPATCHABLE_NULL_HANDLE 0
#endif
如果不出意外,似乎#define VK_NULL_HANDLE nullptr 总体上会更实用。
我可能误解了 API 应该如何使用,所以我分享了有问题的故障代码:一个移动构造函数,它传输句柄并用 NULL 或 VK_NULL_HANDLE 填充旧对象。通过仔细管理所有权,可以简单地设计类并处理vkDestroy* 等。人。在它的析构函数中。
class RenderContext
{
public:
RenderContext(VkPhysicalDevice physicalDevice, uint32_t gfxQueueFamilyIdx, uint32_t presentQueueFamilyIdx);
RenderContext(const RenderContext& other) = delete;
RenderContext& operator=(const RenderContext& other) = delete;
RenderContext(RenderContext&& other) noexcept;
RenderContext&& operator=(RenderContext&& other) = delete;
~RenderContext();
private:
VkDevice _device;
VkCommandPool _gCmdPool;
VkCommandPool _pCmdPool;
VkQueue _gQueue;
VkQueue _pQueue;
};
RenderContext::RenderContext(VkPhysicalDevice physicalDevice, uint32_t gfxQueueFamilyIdx, uint32_t presentQueueFamilyIdx) :
_device(VK_NULL_HANDLE),
_gCmdPool(VK_NULL_HANDLE),
_pCmdPool(VK_NULL_HANDLE),
_gQueue(VK_NULL_HANDLE),
_pQueue(VK_NULL_HANDLE)
{
// ...
}
RenderContext::RenderContext(RenderContext&& other) noexcept :
_device(std::exchange(other._device, nullptr)),
_gCmdPool(std::exchange(other._gCmdPool, VK_NULL_HANDLE)),
_pCmdPool(std::exchange(other._pCmdPool, VK_NULL_HANDLE)),
_gQueue(std::exchange(other._gQueue, nullptr)),
_pQueue(std::exchange(other._pQueue, nullptr))
{}
RenderContext::~RenderContext()
{
vkDestroyCommandPool(_device, _pCmdPool, nullptr);
vkDestroyCommandPool(_device, _gCmdPool, nullptr);
vkDestroyDevice(_device, nullptr);
}
【问题讨论】:
-
那不是 C 库吗?
nullptr在 C 中不存在。 -
这难道不是说明 C 语言无法强制执行某些 Vulkan 规范吗?有一些特定的行为可以确定可调度句柄可以是 VK_NULL_HANDLE 而不可调度句柄可以是 NULL。如果 VK_NULL_HANDLE 扩展为 int,则两者实际上都是 int。
-
Vulkan 绝对不是我的领域,但
(void*)0是空指针常量通常会与int混淆的方式。当然0仍然适合两者,但在尝试将两者分开时并不理想。