🌋
Vulkan.hppで関数ポインタを設定したはずなのに何故か関数呼び出しでエラーが起きる
エラー
こんな感じのエラーが出てきた(本質的にはvkCmdPipelineBarrier以外でも起きえる)
Assertion failed: d.vkCmdPipelineBarrier && "Function <vkCmdPipelineBarrier> requires <VK_VERSION_1_0>", file C:\VulkanSDK\1.4.304.1\Include\vulkan\vulkan_funcs.hpp, line 5662
結論
引数が一つ多い(Dispatchを上書きしてしまっている)
// NG
m_commandBuffer->pipelineBarrier(
srcStage,
dstStage,
vk::DependencyFlagBits(0),
{},
{},
{ imageMemoryBarrier },
{}
);
// OK
m_commandBuffer->pipelineBarrier(
srcStage,
dstStage,
vk::DependencyFlagBits(0),
{},
{},
{ imageMemoryBarrier }
);
なぜ起きるのか
Vulkan.hppではDispatchという関数ポインタを保持しているものを通して、APIの関数を呼び出している。
実際、Pipeline Barrierの関数を見ると最後の引数はDispatchを指定するとこになっており、内部処理はそのDispatchを呼び出すようになっている。
template <typename Dispatch>
VULKAN_HPP_INLINE void
CommandBuffer::pipelineBarrier( VULKAN_HPP_NAMESPACE::PipelineStageFlags srcStageMask,
VULKAN_HPP_NAMESPACE::PipelineStageFlags dstStageMask,
VULKAN_HPP_NAMESPACE::DependencyFlags dependencyFlags,
VULKAN_HPP_NAMESPACE::ArrayProxy<const VULKAN_HPP_NAMESPACE::MemoryBarrier> const & memoryBarriers,
VULKAN_HPP_NAMESPACE::ArrayProxy<const VULKAN_HPP_NAMESPACE::BufferMemoryBarrier> const & bufferMemoryBarriers,
VULKAN_HPP_NAMESPACE::ArrayProxy<const VULKAN_HPP_NAMESPACE::ImageMemoryBarrier> const & imageMemoryBarriers,
Dispatch const & d ) const VULKAN_HPP_NOEXCEPT
{
VULKAN_HPP_ASSERT( d.getVkHeaderVersion() == VK_HEADER_VERSION );
# if ( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 )
VULKAN_HPP_ASSERT( d.vkCmdPipelineBarrier && "Function <vkCmdPipelineBarrier> requires <VK_VERSION_1_0>" );
# endif
d.vkCmdPipelineBarrier( m_commandBuffer,
static_cast<VkPipelineStageFlags>( srcStageMask ),
static_cast<VkPipelineStageFlags>( dstStageMask ),
static_cast<VkDependencyFlags>( dependencyFlags ),
memoryBarriers.size(),
reinterpret_cast<const VkMemoryBarrier *>( memoryBarriers.data() ),
bufferMemoryBarriers.size(),
reinterpret_cast<const VkBufferMemoryBarrier *>( bufferMemoryBarriers.data() ),
imageMemoryBarriers.size(),
reinterpret_cast<const VkImageMemoryBarrier *>( imageMemoryBarriers.data() ) );
}
Dispatchはデフォルト引数で設定しなくても動くようにはなっているが、定義的に{}
で上書きすることも可能で、これはコンパイルに引っかからない。
今回のエラーは{}
を指定してしまい、nullptrの関数を呼び出したことによるエラーであったわけでした。しょうもないエラーではあるが、Pipeline Barreirなど{}を指定する関数だとうっかりしかねないので気を付ける必要がある。
Discussion