Vulkan-HPPの目標は、Vulkan C APIにヘッダーのみのC ++バインディングを提供して、CPUランタイムコストを導入せずに開発者Vulkanエクスペリエンスを改善することです。 enumsやビットフィールドのタイプ安全性、STLコンテナサポート、例外、単純な列挙などの機能を追加します。
| プラットフォーム | ステータスを構築します |
|---|---|
| Linux |
Vulkan-HPPは、バージョン1.0.24以来、Lunarg Vulkan SDKの一部です。 Just #include <vulkan/vulkan.hpp>では、C ++バインディングを使用する準備ができています。 Vulkan SDKによってまだサポートされていないVulkanバージョンを使用している場合は、ここで最新バージョンのヘッダーを見つけることができます。
Vulkan-HPPでは、コンパイルするC ++ 11対応コンパイラが必要です。次のコンパイラが機能することが知られています。
ローカルサンプルとテストをビルドするには、このリポジトリをクローンしてCmakeを実行して必要なビルドファイルを生成する必要があります
依存関係をインストールします。
gitを提供するシェルを開き、リポジトリにクローンを作成します。
git clone --recurse-submodules https://github.com/KhronosGroup/Vulkan-Hpp.git
現在のディレクトリを新しく作成したVulkan-HPPディレクトリに変更します。
cmakeでビルド環境を作成します:
cmake -DVULKAN_HPP_SAMPLES_BUILD=ON -DVULKAN_HPP_SAMPLES_BUILD_WITH_LOCAL_VULKAN_HPP=ON -DVULKAN_HPP_TESTS_BUILD=ON -DVULKAN_HPP_TESTS_BUILD_WITH_LOCAL_VULKAN_HPP=ON -B build
発電機の完全なリストを実行するには、 cmake -Gを実行するには、 -Gを介して発電機を指定する必要がある場合があります。
vk.xml xmlレジストリファイルからvulkan.hpp再構築するには、cmakeコマンドラインに-DVULKAN_HPP_RUN_GENERATOR=ONオプションを追加します。 IDEを使用して生成されたプロジェクトを開くか、Visual Studioなどを開くか、 cmake --build build --parallelでビルドプロセスを起動します。
オプション:Vulkan-HPPとそのサブモジュールを更新するにはgit pull --recurse-submodulesを実行します。
VCPKG依存関係マネージャーを使用して、Vulkan-HPPをダウンロードしてインストールできます。
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install vulkan-headersVCPKGのVulkan-HPPポートは、Microsoftチームのメンバーとコミュニティの貢献者によって最新の状態に保たれています。バージョンが古くなっている場合は、VCPKGリポジトリに問題を作成するか、リクエストをプルしてください。
プログラムのClang-formatがCmakeによって見つかった場合、Defing CLANG_FORMAT_EXECUTABLEはそれに応じて設定されます。その場合、生成されたvulkan.hppは、このプロジェクトのルートディレクトリにある.clang-formatファイルを使用してフォーマットされます。それ以外の場合は、発電機にハードコーディングされているようにフォーマットされています。
ファイルVulkanHpp.natvis 、Visual Studioのvk::Flagsに関するカスタムビューを提供します。このファイルをVisual Studioインストール(%userProfile% documents Visual Studio 2022 Visualizers)のユーザー固有のNATVISディレクトリに追加すると、すべてのビジュアルスタジオプロジェクトでDebuggerで適切にvk::Flagsされています。
Vulkan C APIとの名前の衝突を避けるために、C ++バインディングはvkネームスペースに存在します。以下のルールは、新しい命名に適用されます。
Vkプレフィックスが削除されています。これに加えて、最初の機能の文字は小文字です。vkCreateInstanceはvk::createInstanceとしてアクセスできます。VkImageTilingはvk::ImageTilingとしてアクセスできます。VkImageCreateInfo 、 vk::ImageCreateInfoとしてアクセスできます。VK_プレフィックスとタイプインフィックスを削除して「E」 +キャメルケースに変更されました。列挙タイプが拡張機能の場合、拡張サフィックスは列挙値から削除されています。他のすべての場合、拡張サフィックスは削除されていません。
VK_IMAGETYPE_2Dはvk::ImageType::e2Dなりました。VK_COLOR_SPACE_SRGB_NONLINEAR_KHR vk::ColorSpaceKHR::eSrgbNonlinearなりました。VK_STRUCTURE_TYPE_PRESENT_INFO_KHR vk::StructureType::ePresentInfoKHRなりました。_BIT接尾辞も削除されているという追加のスコープされた酵素のように処理されます。場合によっては、vulkan-hppをカスタムネームスペースに移動する必要がある場合があります。これは、vulkan-hppを含む前にVULKAN_HPP_NAMESPACE定義することで実現できます。
Vulkan-HPPは、すべてのハンドルのクラスを宣言して、完全なタイプの安全性を確保し、ハンドルにメンバー機能のサポートを追加します。対応するハンドルを最初のパラメーターとして受け入れる各関数のハンドルクラスにメンバー関数が追加されています。 vkBindBufferMemory(device, ...)の代わりにdevice.bindBufferMemory(...)またはvk::bindBufferMemory(device, ...)を書き込むことができます。
生成されたvulkan_raii.hppという名前の追加のヘッダーがあります。そのヘッダーには、ハンドルタイプのRAIIに準拠したラッパークラスがあります。つまり、ハンドルタイプVkInstanceなど、Raiiに準拠したラッパーvk::raii::Instanceがあります。ディレクトリRaii_samplesのこれらのクラスを使用してサンプルをご覧ください。
64ビットプラットフォームでは、Vulkan-HPPはC ++ VulkanハンドルとC Vulkanハンドル間の暗黙的な変換をサポートしています。 32ビットプラットフォームでは、すべての非発散性ハンドルはuint64_tとして定義されているため、コンパイル時間でタイプコンバージョンチェックを防ぎ、互換性のないハンドルタイプ間の割り当てをキャッチします。そのため、vulkan-hppはデフォルトで32ビットプラットフォームの暗黙的変換を有効にしないため、次のような変換にstatic_castを使用することをお勧めします: VkImage = static_cast<VkImage>(cppImage) 、任意のintをハンドルに変換したり、逆に逆に変換したりします。 64ビットプラットフォームでコードを開発しているが、明示的なキャストを追加せずに32ビットプラットフォーム用にコードをコンパイルしたい場合は、 VULKAN_HPP_TYPESAFE_CONVERSION vulkan.hppシステムに1に定義できます。 64ビットプラットフォームでは、この定義がデフォルトで1に設定されており、暗黙の変換を無効にするために0に設定できます。
スコープされた列挙機能は、フラグにタイプの安全性を追加しますが、 & |などのビットワイズ操作の入力としてフラグビットを使用することも防止します。 。
ソリューションとして、vulkan-hppはクラステンプレートvk::Flagsを提供し、 &= 、 |= 、 & |のような標準操作をもたらします。スコープされた酵素に。 0の初期化を除いて、このクラスは通常のビットマスクとまったく同じように動作し、対応する列挙で指定されていないビットを偶然に設定することは不可能であるという改善があります。ビットマスクの取り扱いの例をいくつか紹介します。
vk::ImageUsageFlags iu1; // initialize a bitmask with no bit set
vk::ImageUsageFlags iu2 = {}; // initialize a bitmask with no bit set
vk::ImageUsageFlags iu3 = vk::ImageUsageFlagBits::eColorAttachment; // initialize with a single value
vk::ImageUsageFlags iu4 = vk::ImageUsageFlagBits::eColorAttachment | vk::ImageUsageFlagBits::eStorage; // or two bits to get a bitmask
PipelineShaderStageCreateInfo ci ({} /* pass a flag without any bits set */ , ...); Vulkanでハンドルを構築するときは、通常、新しいハンドルを記述するいくつかのCreateInfo構造体を作成する必要があります。これにより、次のVulkan Cの例で見られるように、非常に長いコードが発生する可能性があります。
VkImageCreateInfo ci;
ci. sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
ci.pNext = nullptr ;
ci.flags = ...some flags...;
ci.imageType = VK_IMAGE_TYPE_2D;
ci.format = VK_FORMAT_R8G8B8A8_UNORM;
ci.extent = VkExtent3D { width, height, 1 };
ci.mipLevels = 1 ;
ci.arrayLayers = 1 ;
ci.samples = VK_SAMPLE_COUNT_1_BIT;
ci.tiling = VK_IMAGE_TILING_OPTIMAL;
ci.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
ci.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
ci.queueFamilyIndexCount = 0 ;
ci.pQueueFamilyIndices = 0 ;
ci.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
vkCreateImage (device, &ci, allocator, &image); Vulkan DevelopersがフィールドごとにCreateInfo構造体フィールドに記入する際に遭遇する2つの典型的な問題があります。
sTypeは間違っています。特に最初のものは検出が困難です。
Vulkan-HPPは、各メンバー変数に1つのパラメーターを受け入れるすべてのCreateInfoオブジェクトにコンストラクターを提供します。これにより、値が忘れられている場合、コンパイラはコンパイラエラーをスローします。このことに加えて、 sTypeは自動的に正しい値で満たされ、デフォルトでpNext nullptr設定されています。同じコードがコンストラクターでどのように見えるかは次のとおりです。
vk::ImageCreateInfo ci ({}, vk::ImageType::e2D, vk::Format::eR8G8B8A8Unorm,
{ width, height, 1 },
1 , 1 , vk::SampleCountFlagBits:: e1 ,
vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eColorAttachment,
vk::SharingMode::eExclusive, 0 , nullptr , vk::ImageLayout::eUndefined);
vk::Image image = device.createImage(ci); CreateInfo構造のコンストラクターを使用すると、次のようなVulkan関数に一時的なものを渡すこともできます。
vk::Image image = device.createImage({{}, vk::ImageType::e2D, vk::Format::eR8G8B8A8Unorm,
{ width, height, 1 },
1 , 1 , vk::SampleCountFlagBits:: e1 ,
vk::ImageTiling::eOptimal, vk::ImageUsageFlagBits::eColorAttachment,
vk::SharingMode::eExclusive, 0 , nullptr , vk::ImageLayout::eUndefined});C ++ 20から始めて、C ++は指定された初期剤をサポートします。その機能には、ユーザー宣言または継承されたコンストラクターがない必要があるため、 vulkan.hppからすべての構造と組合のコンストラクターを削除する#define VULKAN_HPP_NO_CONSTRUCTORSが必要です。代わりに、集約初期化を使用できます。ソースの最初のいくつかのVKラインは次のようになります。
// initialize the vk::ApplicationInfo structure
vk::ApplicationInfo applicationInfo{ . pApplicationName = AppName,
. applicationVersion = 1 ,
. pEngineName = EngineName,
. engineVersion = 1 ,
. apiVersion = VK_API_VERSION_1_1 };
// initialize the vk::InstanceCreateInfo
vk::InstanceCreateInfo instanceCreateInfo{ . pApplicationInfo = &applicationInfo };の代わりに
// initialize the vk::ApplicationInfo structure
vk::ApplicationInfo applicationInfo (AppName, 1 , EngineName, 1 , VK_API_VERSION_1_1);
// initialize the vk::InstanceCreateInfo
vk::InstanceCreateInfo instanceCreateInfo ({}, &applicationInfo);指定者の注文は、宣言命令と一致する必要があることに注意してください。同様に、VK構造のsTypeメンバーを明示的に設定できることにも注意してください。これは(デフォルトで正しく初期化されているため)ネクタリーではなく、推奨されません。
Vulkan APIには、2つの関数引数として必要ないくつかの場所(カウント、ポインター)があり、C ++にはこのペアに完全にマッピングされるコンテナがいくつかあります。開発を簡素化するために、Vulkan-HPPバインディングは、これらの引数ペアをvk::ArrayProxyクラステンプレートに置き換えました。これは、空の配列と単一の値を受け入れ、STL Containers std::initializer_list 、 std::arrayおよびstd::vector 。このようにして、単一の生成されたVulkanバージョンは、各コンテナタイプの関数を作成するときに発生する組み合わせ爆発を起こさずに、さまざまな入力を受け入れることができます。
vk::ArrayProxy使用方法に関するコードサンプルを次に示します。
vk::CommandBuffer c;
// pass an empty array
c.setScissor( 0 , nullptr );
// pass a single value. Value is passed as reference
vk::Rect2D scissorRect = { { 0 , 0 }, { 640 , 480 } };
c.setScissor( 0 , scissorRect);
// pass a temporary value.
c.setScissor( 0 , { { 0 , 0 }, { 640 , 480 } });
// pass a fixed size array
vk::Rect2D scissorRects[ 2 ] = { { { 0 , 0 }, { 320 , 240 } }, { { 320 , 240 }, { 320 , 240 } } };
c.setScissor( 0 , scissorRects);
// generate a std::initializer_list using two rectangles from the stack. This might generate a copy of the rectangles.
vk::Rect2D scissorRect1 = { { 0 , 0 }, { 320 , 240 } };
vk::Rect2D scissorRect2 = { { 320 , 240 }, { 320 , 240 } };
c.setScissor( 0 , { scissorRect, scissorRect2 });
// construct a std::initializer_list using two temporary rectangles.
c.setScissor( 0 , { { { 0 , 0 }, { 320 , 240 } },
{ { 320 , 240 }, { 320 , 240 } } });
// pass a std::array
std::array<vk::Rect2D, 2 > arr{ scissorRect1, scissorRect2 };
c.setScissor( 0 , arr);
// pass a std::vector of dynamic size
std::vector<vk::Rect2D> vec;
vec.push_back(scissorRect1);
vec.push_back(scissorRect2);
c.setScissor( 0 , vec);Vulkan-HPPは、構造体へのポインターの参照を生成します。この変換により、一時的な構造体を通過させると、コードが短くなる可能性があります。入力がオプションであるため、ヌルポインターを受け入れる場合、パラメータータイプはvk::Optional<T> const&になります。このタイプは、入力としてTまたはnullptrへの参照を受け入れるため、オプションの一時的な構造体を許可します。
// C
VkImageSubresource subResource;
subResource.aspectMask = 0 ;
subResource.mipLevel = 0 ;
subResource.arrayLayer = 0 ;
VkSubresourceLayout layout;
vkGetImageSubresourceLayout (device, image, &subresource, &layout);
// C++
auto layout = device.getImageSubresourceLayout(image, { {} /* flags */ , 0 /* miplevel */ , 0 /* arrayLayer */ });Vulkanは、 pNextポインターを介して構造のチェーンを許可します。 Vulkan-HPPには、最小限の労力でそのような構造チェーンを構築できるバリアードクラステンプレートがあります。これに加えて、仕様がそのようなpNextチェーンの構築を許可するかどうかをコンパイル時にチェックします。
// This will compile successfully.
vk::StructureChain<vk::MemoryAllocateInfo, vk::ImportMemoryFdInfoKHR> c;
vk::MemoryAllocateInfo &allocInfo = c.get<vk::MemoryAllocateInfo>();
vk::ImportMemoryFdInfoKHR &fdInfo = c.get<vk::ImportMemoryFdInfoKHR>();
// This will fail compilation since it's not valid according to the spec.
vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedRequirementsKHR> c;
vk::MemoryAllocateInfo &allocInfo = c.get<vk::MemoryAllocateInfo>();
vk::ImportMemoryFdInfoKHR &fdInfo = c.get<vk::ImportMemoryFdInfoKHR>(); Vulkan-HPPは、チェーンのすべての構造のリストを受け入れるCreateInfoオブジェクトに似たこれらのチェーンのコンストラクターを提供します。 pNextフィールドは、正しい値に自動的に設定されます。
vk::StructureChain<vk::MemoryAllocateInfo, vk::MemoryDedicatedAllocateInfo> c = {
vk::MemoryAllocateInfo (size, type),
vk::MemoryDedicatedAllocateInfo (image)
};いくつかのオプションの設定が原因で、構造変化の構造の1つを削除する場合、 vk::StructureChain::unlink<ClassType>()使用できます。指定された構造がPNEXT-Chainの一部ではなくなるように構造変化を変更します。 structurechainの実際のメモリレイアウトは、その関数によって変更されないことに注意してください。まったく同じ構造をstructureChainに再度再度付加する必要がある場合は、 vk::StructureChain::relink<ClassType>()を使用します。
場合によっては、ユーザーが情報を照会するために事前に配置された構造チェーンを渡す必要がある場合があります。これらの場合には、2つの対応するゲッター関数があります。 1つは、リターン値を構築するために少なくとも2つの要素の構造チェーンを生成するバリアードテンプレートを備えています。
// Query vk::MemoryRequirements2HR and vk::MemoryDedicatedRequirementsKHR when calling Device::getBufferMemoryRequirements2KHR:
auto result = device.getBufferMemoryRequirements2KHR<vk::MemoryRequirements2KHR, vk::MemoryDedicatedRequirementsKHR>({});
vk::MemoryRequirements2KHR &memReqs = result.get<vk::MemoryRequirements2KHR>();
vk::MemoryDedicatedRequirementsKHR &dedMemReqs = result.get<vk::MemoryDedicatedRequirementsKHR>();チェーンなしでベース構造のみを取得するには、提供された他のゲッター関数は、構造を取得するためのテンプレート引数を必要としません。
// Query just vk::MemoryRequirements2KHR
vk::MemoryRequirements2KHR memoryRequirements = device.getBufferMemoryRequirements2KHR({});デフォルトでは、Vulkan-HPPには例外が有効になっています。これは、Vulkan-HPPがvk::Resultを返す各関数呼び出しの戻りコードをチェックすることを意味します。 vk::Resultが失敗の場合、 std::runtime_errorがスローされます。もうエラーコードを返す必要がないため、C ++バインディングは実際の希望の返品値、つまりVulkanハンドルを返すことができます。そのような場合vk::ResultValue<SomeType>::type返されたタイプとして定義されます。
デバイスを作成するには、今すぐ書き込むことができます。
vk::Device device = physicalDevice.createDevice(createInfo);一部の関数では、 vk::Result::eSuccess以上のものが成功コードと見なされます。これらの関数については、常にvk::ResultValue<SomeType>を返します。例は、 acquireNextImage2KHRです。これは次のように使用できます。
vk::ResultValue< uint32_t > result = device-> acquireNextImage2KHR (acquireNextImageInfo);
switch (result.result)
{
case vk::Result::eSuccess:
currentBuffer = result. value ;
break ;
case vk::Result::eTimeout:
case vk::Result::eNotReady:
case vk::Result::eSuboptimalKHR:
// do something meaningful
break ;
default :
// should not happen, as other return codes are considered to be an error and throw an exception
break ;
}時間が経つにつれて、いくつかのVulkan関数が変化する可能性があり、 vk::Result::eSuccessよりも多くの結果コードをサクセスコードとしてサポートし始めます。その論理的な変更はC APIでは表示されませんが、C ++ APIでは、そのような関数がvk::ResultValue<SomeType>ではなくSomeTypeの代わりに戻ります。このような(まれな)場合、APIの変更を反映するためにCPPソースを調整する必要があります。
VULKAN_HPP_NO_EXCEPTIONSを定義して例外処理が無効になっている場合vk::ResultValue<SomeType>::typeのタイプは、 vk::ResultとSomeTypeを保持する構造体です。この構造体はstd::tieを使用して戻り値を開梱することをサポートします。
vk::ArrayProxyとReturn Value Transformationを使用したくない場合でも、Plain Cスタイルの関数を呼び出すことができます。以下は、APIを使用する3つの方法を示す3つの例です。
最初のスニペットは、例外なくAPIを使用する方法と戻り値変換を示しています。
// No exceptions, no return value transformation
vk::ShaderModuleCreateInfo createInfo (...);
vk::ShaderModule shader1;
vk::Result result = device.createShaderModule(&createInfo, allocator, &shader1);
if (result.result != vk::Result::eSuccess)
{
handle error code;
cleanup?
return ?
}
vk::ShaderModule shader2;
vk::Result result = device.createShaderModule(&createInfo, allocator, &shader2);
if (result != vk::Result::eSuccess)
{
handle error code;
cleanup?
return ?
}2番目のスニペットは、リターン値変換を使用してAPIを使用する方法を示していますが、例外はありません。すでに元のコードよりも少し短いです。
vk::ResultValue<ShaderModule> shaderResult1 = device.createShaderModule({...} /* createInfo temporary */ );
if (shaderResult1.result != vk::Result::eSuccess)
{
handle error code;
cleanup?
return ?
}
// std::tie support.
vk::Result result;
vk::ShaderModule shaderModule2;
std::tie (result, shaderModule2) = device.createShaderModule({...} /* createInfo temporary */ );
if (result != vk::Result::eSuccess)
{
handle error code;
cleanup?
return ?
}結果を開梱するより良い方法は、C ++ 17で構造化されたバインディングを使用することです。彼らは、単一のコードで結果を得ることができます:
auto [result, shaderModule2] = device.createShaderModule({...} /* createInfo temporary */ );最後に、最後のコードの例は、例外と返品値の変換を使用することです。これは、APIのデフォルトモードです。
vk::ShaderModule shader1;
vk::ShaderModule shader2;
try
{
shader1 = device. createShaderModule ({...});
shader2 = device. createShaderModule ({...});
}
catch (std:: exception const &e)
{
// handle error and free resources
}重要
vk -NamesPaceのVulkanハンドルはRaiiをサポートしていないため、エラーハンドラーでリソースをクリーンアップする必要があります。代わりに、 vk::raii -NamesPaceでハンドルラッパークラスを使用できます。
C ++ 17以降では、一部の関数は[[nodiscard]]で起因するため、返品値を何らかの形で使用しない場合は警告が発生します。 VULKAN_HPP_NO_NODISCARD_WARNINGSを定義することにより、これらの警告をオフにすることができます。
返品値の変換には、特別な取り扱いが必要な特別なクラスの返品値が1つあります。列挙の場合、通常、このようなコードを記述する必要があります。
std::vector<LayerProperties, Allocator> properties;
uint32_t propertyCount;
vk::Result result;
do
{
// determine number of elements to query
result = static_cast <vk::Result>( vk::enumerateDeviceLayerProperties (m_physicalDevice, &propertyCount, nullptr ));
if ((result == vk::Result::eSuccess) && propertyCount)
{
// allocate memory & query again
properties. resize (propertyCount);
result = static_cast <vk::Result>( vk::enumerateDeviceLayerProperties (m_physicalDevice, &propertyCount, reinterpret_cast
<VkLayerProperties*>(properties. data ())));
}
} while (result == vk::Result::eIncomplete);
// it's possible that the count has changed, start again if properties was not big enough
properties.resize(propertyCount);このループを何度も書くことは退屈であり、エラーが発生しやすいので、C ++バインディングが列挙の世話をしているので、次のように書くことができます。
std::vector<LayerProperties> properties = physicalDevice.enumerateDeviceLayerProperties();Vulkan-HPPはvk::UniqueHandle<Type, Deleter> interfaceを提供します。各vulkanハンドルタイプvk::Type vkがありますvk::UniqueType uniqueTypeがありますvk::UniqueBufferこれにより、破壊時に基礎となるVulkanリソースvk::Buffer削除します。
型vk::Type typeのvulkanハンドルを構築する各関数について、Vulkan-HPPはvk::UniqueTypeを返す2番目のバージョンを提供します。たとえばvk::Device::createBuffer vk::Device::createBufferUniqueがあり、 vk::allocateCommandBuffersにはvk::allocateCommandBuffersUniqueがあります。
vk::UniqueHandleを使用すると、ほとんどの削除機は自動破壊に必要なため、建設に使用されるvk::AllocationCallbacksと親のハンドルを保存する必要があるため、コストがかかります。
Vulkan-HPPはvk::SharedHandle<Type>インターフェイスを提供します。各vulkanハンドルタイプvk::Type共有ハンドルvk::SharedBuffer vk::SharedTypeがあり、破壊時に基礎となるVulkanリソースvk::Buffer削除します。
vk::UniqueHandleとは異なり、 vk::SharedHandle 、リソースとその親の共有所有権を取ります。これは、すべての子供のリソースが削除されるまで、親のハンドルが破壊されないことを意味します。これは、複数のスレッドまたはオブジェクト間で共有されるリソースに役立ちます。
このメカニズムは、親vk::SharedHandle子供のハンドルの前に破壊された場合でも、正しい破壊順序を保証します。それ以外の場合、ハンドルはstd::shared_ptrのように動作します。 vk::SharedInstanceまたはその子オブジェクトのいずれかを削除する必要があります(最初に作成され、クラス宣言で最初に作成されます)。
vk::SharedHandleを直接返す機能はまだありません。代わりに、vk :: vk :: vk::Handle vk::SharedHandleを作成できます。
vk::Buffer buffer = device.createBuffer(...);
vk::SharedBuffer sharedBuffer (buffer, device); // sharedBuffer now owns the bufferさまざまなハンドルタイプのvk::SharedHandleのいくつかの専門分野があります。たとえば、 vk::SharedImage追加の引数を取り、画像がSwapChainによって所有されているかどうかを指定する場合があります。
vk::Image image = swapchain.getImages(...)[ 0 ]; // get the first image from the swapchain
vk::SharedImage sharedImage (image, device, SwapChainOwns::yes); // sharedImage now owns the image, but won't destroy itまた、 vk::SwapchainKHRの専門化もあります。
vk::SwapchainKHR swapchain = device.createSwapchainKHR(...);
vk::SharedSwapchainKHR sharedSwapchain (swapchain, device, surface); // sharedSwapchain now owns the swapchain and surface SharedHandleBaseにいくつかのテンプレート引数を提供することにより、自分のハンドルタイプまたは独自の共有ハンドルのためにvk::SharedHandleオーバーロードを作成できます。
これにより、親のハンドルとハンドルを破壊するカスタム静的破壊関数internalDestroy提供します。基本クラスに友人の宣言を追加することを忘れないでください。
// Example of a custom shared device, that takes in an instance as a parent
class shared_handle <VkDevice> : public vk::SharedHandleBase<VkDevice, vk::SharedInstance, shared_handle<VkDevice>>
{
using base = vk::SharedHandleBase<VkDevice, vk::SharedInstance, shared_handle<VkDevice>>;
friend base;
public:
shared_handle () = default ;
explicit shared_handle (VkDevice handle, vk::SharedInstance parent) noexcept
: base(handle, std::move(parent)) {}
const auto & getParent () const noexcept
{
return getHeader ();
}
protected:
static void internalDestroy ( const vk::SharedInstance& /* control */ , VkDevice handle) noexcept
{
kDestroyDevice (handle);
}
};APIは拡張され、将来作成機能を提供します。
vk::UniqueHandlesとvk::SharedHandlesに加えて、 vk::raii namespaceに記載されているRaii-paradigm(リソース取得は初期化)に続くすべてのハンドルタイプのラッパークラスのセットがあります。
vk::UniqueHandleは、 std::unique_ptrに包まれたハンドルを模倣し、 vk::SharedHandle 、親情報を含むstd::shared_ptr vk::raii::Handleによってラップされたハンドルを模倣します。したがって、あなたはそれらを値として自由に使用したり、いくつかのスマートポインターでそれらを包むことができます。
vk::Handles以外に、それらのすべてのハンドルラッパークラスは追加のデータを保持する必要があるため、Vulkan Cハンドルと同一のバイナリではありません。
vk::UniqueHandlesとvk::SharedHandles vk::Handlesと同じディスパッチャーを使用すると、簡単に混合して一致させることができます。 vk::raii::Handlesいくつかのわずかに異なるディスパッチャーを使用するため、他のハンドルと互換性がありません!つまり、 vk-Handles 、 vk::UniqueHandles 、およびvk::SharedHandlesの場合、https://github.com/khronosgroup/vulkan-hpp#extensions - device-function-function-functionpointersに記載されているように、グローバルディスパッチャーをインスタンス化する必要があります。 vk::raii-Handlesの場合、これは独自のディスパッチャーを維持するため、必要ありません。ここでの大きな利点は、複数のデバイスがある場合です。VK vk::raii-Handlesを介して呼び出される関数は、常にデバイス固有の機能を呼び出します。
カスタムアロケーターを使用してstd::vector使用する必要がある場合があります。 Vulkan-HPPは、 vk::ArrayProxyおよびベクトルを返す機能の入力としてカスタムアロケーターを使用してベクトルをサポートします。後者の場合、お気に入りのカスタムアロケーターをこのような関数呼び出しにテンプレート引数として追加します。
std::vector<LayerProperties, MyCustomAllocator> properties = physicalDevice.enumerateDeviceLayerProperties<MyCustomAllocator>();また、それらの関数への引数としてそれを提供することにより、ステートフルなカスタムアロケーターを使用することもできます。残念ながら、コンパイラを幸せにするには、ディスパッチ引数を明示的に設定する必要があります。そこにデフォルトを取得するには、単純な{}で十分です:
MyStatefulCustomAllocator allocator;
std::vector<LayerProperties, MyStatefulCustomAllocator> properties = physicalDevice.enumerateDeviceLayerProperties(allocator, {});vulkan.hpp全体で、アサート機能にはいくつかの呼び出しがあります。 VULKAN_HPP_ASSERTを定義することにより、代わりに呼び出される独自のカスタマン機能を指定できます。
デフォルトでは、 VULKAN_HPP_NO_EXCEPTIONSが定義されている場合、 VULKAN_HPP_ASSERT_ON_RESULT結果のチェックに使用されます。自分でエラーを処理したい場合は、 VULKAN_HPP_ASSERTのように無効化/カスタマイズできます。
ファイルvulkan_static_assertions.hppには、各ハンドルクラスと各構造物にいくつかの静的アサーションがあります。そのファイルをソースファイルの少なくとも1つに含めることができます。 VULKAN_HPP_STATIC_ASSERTを定義することにより、これらのケースに使用する独自のカスタム静的アサーションを指定できます。つまり、それがNOPであると定義することにより、編集時間を少し短縮できます。
Vulkanローダーは、Vulkanコア関数と限られた数の拡張機能のみを公開します。拡張機能を備えたVulkan-HPPを使用するには、すべての使用されているVulkan関数にスタブを提供するライブラリを使用するか、Vulkan-HPPにそれらの機能ポインターを派遣するように指示する必要があります。 Vulkan-HPPは、各関数呼び出しの最後のパラメーターとしてディスパッチクラスを受け入れることにより、機能ごとのディスパッチメカニズムを提供します。ディスパッチクラスは、使用するVulkan関数ごとに呼び出し可能なタイプを提供する必要があります。 Vulkan-HPPは、1つの実装、 DispatchLoaderDynamic提供します。
// Providing a function pointer resolving vkGetInstanceProcAddr, just the few functions not depending an an instance or a device are fetched
vk::DispatchLoaderDynamic dld (getInstanceProcAddr);
// Providing an already created VkInstance and a function pointer resolving vkGetInstanceProcAddr, all functions are fetched
vk::DispatchLoaderDynamic dldi (instance, getInstanceProcAddr);
// Providing also an already created VkDevice and optionally a function pointer resolving vkGetDeviceProcAddr, all functions are fetched as well, but now device-specific functions are fetched via vkDeviceGetProcAddr.
vk::DispatchLoaderDynamic dldid ( nstance, getInstanceProcAddr, device);
// Pass dispatch class to function call as last parameter
device.getQueue(graphics_queue_family_index, 0 , &graphics_queue, dldid); To use the vk::DispatchLoaderDynamic as the default dispatcher (means: you don't need to explicitly add it to every function call), you need to #define VULKAN_HPP_DISPATCH_LOADER_DYNAMIC 1 , and have the macro VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE exactly once in your source code to provide storage for that default dispatcher.次に、以下のコードスニペットに示すように、Macro VULKAN_HPP_DEFAULT_DISPATCHERで使用できます。完全な特集vk::DispatchLoaderDynamic作成することは、2〜3段階のプロセスであり、最初のステップには3つの選択肢があります。
vk::DynamicLoaderを使用して内部的にすべての作業を行うようにします。 VULKAN_HPP_DEFAULT_DISPATCHER.init();getProcAddressを提供するだけです( vulkan.hppのvk::DynamicLoaderと比較): YourDynamicLoader ydl;
VULKAN_HPP_DEFAULT_DISPATCHER.init(ydl);注記
プログラムでVulkan関数を最後に呼び出すまで、その動的ローダーオブジェクトを生かし続ける必要があります。たとえば、静的にするか、グローバルに保存します。
PFN_vkGetInstanceProcAddrの独自の初期関数ポインターを使用します。 PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = your_own_function_pointer_getter();
VULKAN_HPP_DEFAULT_DISPATCHER.init(vkGetInstanceProcAddr);vk::Instanceで初期化して、他のすべての機能ポインターを取得します。 vk::Instance instance = vk::createInstance({}, nullptr );
VULKAN_HPP_DEFAULT_DISPATCHER.init(instance);vk::Deviceで初期化して、デバイス固有の機能ポインターを取得する std::vector<vk::PhysicalDevice> physicalDevices = instance.enumeratePhysicalDevices();
assert (!physicalDevices.empty());
vk::Device device = physicalDevices[ 0 ].createDevice({}, nullptr );
VULKAN_HPP_DEFAULT_DISPATCHER.init(device);上記の2番目のステップの後、ディスパッチャーは完全に機能します。 3番目のステップを追加すると、より効率的なコードが発生する可能性があります。ただし、複数のデバイスを使用する場合は、その3番目のステップを省略して、ドライバーにデバイスディスパッチを実行させることができます。
場合によっては、DispatchLoaderDynamicのストレージをDLLに埋め込む必要があります。これらの場合については、 VULKAN_HPP_STORAGE_SHAREDを定義して、vulkan-hppにストレージがDLLに存在することを伝える必要があります。ストレージでDLLをコンパイルするときは、 VULKAN_HPP_STORAGE_SHARED_EXPORTを定義して、必要なシンボルをエクスポートする必要があります。
すべての機能について、 VULKAN_HPP_DEFAULT_DISPATCHERがその関数の最後の引数のデフォルトです。すべての関数呼び出しのディスパッチャーを明示的に提供したい場合(たとえば、さまざまなデバイス用のvulkan.hppのディスパッチャーがある場合)、誤って関数呼び出しを見逃さないようにしたい場合は、 VULKAN_HPP_NO_DEFAULT_DISPATCHERを定義することができます。
vulkan.hppいくつかのタイプの特性を提供し、テンプレートメタプログラムを緩和します。
template <typename EnumType, EnumType value> struct CppType maps IndexType値( IndexType::eUint16 、 IndexType::eUint32 、...)に対応するタイプ( uint16_t 、 uint32_t 、...)にメンバーTypeによるもの。 MAPS ObjectType値( ObjectType::eInstance 、 ObjectType::eDevice 、...)に対応するタイプ( vk::Instance 、 vk::Device 、...)にメンバータイプのType 。 Maps DebugReportObjectType値( DebugReportObjectTypeEXT::eInstance 、 DebugReportObjectTypeEXT::eDevice 、...)に対応するType ( vk::Instance 、 vk::Device 、...)template <typename T> struct IndexTypeValueマップスカラータイプ( uint16_t 、 uint32_t 、...)に対応するIndexType値( IndexType::eUint16 、 IndexType::eUint32 、...)template <typename T> struct isVulkanHandleType静的メンバーvalueによってハンドルクラス( vk::Instance 、 vk::Device 、...)である場合にのみ、タイプをtrueにマップします。HandleClass::CTypeメンバータイプCTypeによって、対応するCタイプ( VkInstance 、 vk::Device 、...)にハンドルクラス( vk::Instance 、 VkDevice :: device、...)をマップします。HandleClass::objectTypeは、ハンドルクラス( vk::Instance 、 vk::Device 、...)を対応するObjectType値( ObjectType::eInstance 、 ObjectType::eDevice 、...)にobjectTypeします。HandleClass::debugReportObjectTypeハンドルクラス( vk::Instance 、 vk::Device 、...)を対応するDebugReportObjectTypeEXT DebugReportObjectTypeEXT::eInstance 、 debugReportObjectType DebugReportObjectTypeEXT::eDevice 、...)にマップします。追加のヘッダーvulkan_format_traits.hppを使用すると、 vk::Formatのいくつかの特性関数が提供されます。 C ++ 14以降では、これらのすべての関数はconstexprとしてマークされています。これは、適切な引数を使用して、コンパイル時に解決されます。
uin8_t blockSize( vk::Format format );この形式のテクセルブロックサイズをバイト単位で取得します。uint8_t texelsPerBlock( vk::Format format );テクセルブロックでテクセルの数を取得します。std::array<uint8_t, 3> blockExtent( vk::Format format ); Texelブロックの3次元範囲を取得します。char const * compressionScheme( vk::Format format );この形式の圧縮スキームのテキストの説明、または圧縮されていない場合は空のテキストを取得します。bool isCompressed( vk::Format format );確かに、フォーマットが圧縮形式である場合、それ以外の場合は偽りです。uint8_t packed( vk::Format format );フォーマットが詰め込まれているビット数を取得します。この形式の単一の画像要素は、このビット幅のスカラータイプと同じ空間に保存できます。uint8_t componentCount( vk::Format format );この形式のコンポーネントの数を取得します。bool componentsAreCompressed( vk::Format format );確かに、この形式のコンポーネントが圧縮されている場合、それ以外の場合は偽りです。uint8_t componentBits( vk::Format format, uint8_t component );圧縮されていない場合は、このコンポーネントのビット数を取得します。char const * componentName( vk::Format format, uint8_t component );このコンポーネントの名前をCストリングとして取得します。char const * componentNumericFormat( vk::Format format, uint8_t component );このコンポーネントの数値形式をCストリングとして取得します。uint8_t componentPlaneIndex( vk::Format format, uint8_t component );平面インデックスを取得します。このコンポーネントはにあります。uint8_t planeCount( vk::Format format );この形式の画像プレーンの数を取得します。vk::Format planeCompatibleFormat( vk::Format format, uint8_t plane );この平面と互換性のあるシングル面形式を取得します。uint8_t planeHeightDivisor( vk::Format format, uint8_t plane );この平面の相対的な高さを取得します。 kの値は、この平面が全体の形式の高さ1/kであることを意味します。uint8_t planeWidthDivisor( vk::Format format, uint8_t plane );この平面の相対幅を取得します。 kの値は、この平面が全体の形式の幅1/kであることを意味します。追加のヘッダーvulkan_hash.hppを使用すると、ハンドルラッパークラスのstd::hashの専門化を取得し、C ++ 14を構造ラッパー用にします。 VULKAN_HPP_HASH_COMBINEを使用すると、構造要素の独自のハッシュを組み合わせたアルゴリズムを定義できます。
追加のヘッダーvulkan_extension_inspection.hpp使用すると、拡張機能を検査するためのいくつかの関数が提供されます。 C ++ 20以降では、これらの関数の一部はconstexprとしてマークされています。これは、適切な引数を使用して、コンパイル時に解決されます。各拡張子は、その名前を保持する文字列によって識別されます。各拡張子のその名前で定義が存在することに注意してください。一部の関数は、Vulkanバージョンに依存する情報を提供する場合があります。ここでのすべての関数は文字列のみで機能するため、Vulkanバージョンは「VK_Version_」で始まる文字列によってエンコードされ、その後、このようなアンダーソーが区切られたメジャーとマイナーバージョンが続きます:「VK_Version_1_0」。
std::set<std::string> const & getDeviceExtensions();現在のプラットフォームに指定されたすべてのデバイス拡張機能を取得します。それらのすべてが実際のデバイスによってサポートされているわけではないことに注意してください。std::set<std::string> const & getInstanceExtensions();現在のプラットフォームに指定されたすべてのインスタンス拡張機能を取得します。それらのすべてが実際のインスタンスによってサポートされているわけではないことに注意してください。std::map<std::string, std::string> const & getDeprecatedExtensions();その機能を置き換えることになっている拡張機能またはVULKANバージョンに削除されたすべての拡張機能のマップを取得します。std::map<std::string, std::vector<std::vector<std::string>>> const & getExtensionDepends( std::string const & extension );一部の拡張機能は、他の拡張機能に依存します。その依存関係は異なるVulkanバージョンで異なる場合があり、まったく同じVulkanバージョンの依存関係が異なる場合があります。この関数は、与えられた拡張子が依存するVulkanバージョンごとの拡張機能のベクトルのベクトルを取得します。std::pair<bool, std::vector<std::vector<std::string>> const &> getExtensionDepends( std::string const & version, std::string const & extension );返されたstd::pairのfirstメンバーは、与えられたvulkanバージョンで指定された拡張機能が指定されている場合、それ以外の場合はfalse 。返されたstd::pairのsecondのメンバーは、拡張機能のベクトルのベクトルであり、指定された拡張機能が特定のVulkanバージョンに依存する個別の拡張セットをリストします。std::map<std::string, std::string> const & getObsoletedExtensions();その拡張機能を廃止したすべての廃止された拡張機能のマップを拡張バージョンまたはVulkanバージョンに取得します。std::map<std::string, std::string> const & getPromotedExtensions();別の拡張機能に宣伝されたすべての拡張機能のマップを取得します。VULKAN_HPP_CONSTEXPR_20 std::string getExtensionDeprecatedBy( std::string const & extension );拡張機能またはVulkanバージョンを取得します。VULKAN_HPP_CONSTEXPR_20 std::string getExtensionObsoletedBy( std::string const & extension );拡張機能またはVulkanバージョンを取得します。VULKAN_HPP_CONSTEXPR_20 std::string getExtensionPromotedTo( std::string const & extension );拡張機能またはVulkanバージョンを取得します。VULKAN_HPP_CONSTEXPR_20 bool isDeprecatedExtension( std::string const & extension );与えられた拡張機能が他の拡張機能またはVulkanバージョンによって非推奨される場合、 trueを返します。VULKAN_HPP_CONSTEXPR_20 bool isDeviceExtension( std::string const & extension );指定された拡張子がデバイス拡張機能である場合、 trueを返します。VULKAN_HPP_CONSTEXPR_20 bool isInstanceExtension( std::string const & extension );指定された拡張子がインスタンス拡張子である場合、 trueを返します。VULKAN_HPP_CONSTEXPR_20 bool isObsoletedExtension( std::string const & extension );与えられた拡張機能が他の拡張機能またはVulkanバージョンによって廃止されている場合、 trueを返します。VULKAN_HPP_CONSTEXPR_20 bool isPromotedExtension( std::string const & extension );与えられた拡張機能が他の拡張機能またはVulkanバージョンに宣伝されている場合、 trueを返します。警告
Microsoft Visual Studio 2022の現在のバージョンは、Vulkan.cppmモジュールを処理できません。バグが提出されます(https://developercommunity.visualstudio.com/t/on-building-a-c20-module:-fatal--error/10469799#t-nd10485943)。 VULKAN_HPP_NO_SMART_HANDLEを定義して、 vk::UniqueHandleまたはvk::SharedHandle必要としない、または使用したい場合は、少なくともこの機能を使用できます。
Vulkan-HPPは、 vulkan.cppmのc ++という名前のモジュール、 vulkan_hppを提供します。 C ++モジュールは、ヘッダーファイルに優先することを目的としています。宣言と定義は、ヘッダーを繰り返し解析することなく翻訳ユニット間で簡単に共有できるため、モジュールは大規模プロジェクトのコンピレーション時間を大幅に改善する可能性があります。 Vulkan-HPPには、いくつかの非常に長いヘッダー( vulkan_structs.hppなど)があり、C ++モジュールは、現在使用しているプロジェクトのコンパイル時間を短縮する可能性があります。
この機能には、完全なC ++ 20サポートを備えた最近のコンパイラが必要です。
cl.exe 19.28以降を提供)CmakeのC ++モジュールサポート(および場合によっては忍者)を使用する場合は、最近のツールが必要です。
cl.exe 19.34以降を提供)警告
Vulkan-HPP C ++という名前のモジュールは、まだ実験的です。 Some suggested ways to use it in your projects are below. The long-term goal is to submit patches to the CMake FindVulkan module so that users may transparently configure the named module, without needing to declare it as an additional library in consumer CMake code.
CMake is recommended for use with the Vulkan-Hpp named module, as it provides a convenient platform-agnostic way to configure your project. CMake version 3.28 or later is required to support C++ modules. Refer to the CMake documentation on the topic.
CMake provides the FindVulkan module, which may be used to source the Vulkan SDK and Vulkan headers on your system.
# find Vulkan SDK
find_package ( Vulkan REQUIRED )
# Require Vulkan version ≥ 1.3.256 (earliest version when the Vulkan module was available)
if ( ${Vulkan_VERSION} VERSION_LESS "1.3.256" )
message ( FATAL_ERROR "Minimum required Vulkan version for C++ modules is 1.3.256. "
"Found ${Vulkan_VERSION} ."
)
endif ()
# set up Vulkan C++ module as a library
add_library ( VulkanHppModule )
target_sources ( VulkanHppModule PRIVATE
FILE_SET CXX_MODULES
BASE_DIRS ${Vulkan_INCLUDE_DIR}
FILES ${Vulkan_INCLUDE_DIR} /vulkan/vulkan.cppm
)
target_compile_features ( VulkanHppModule PUBLIC cxx_std_20 )
target_link_libraries ( VulkanHppModule PUBLIC Vulkan::Vulkan )
# link Vulkan C++ module into your project
add_executable ( YourProject main.cpp )
target_link_libraries ( YourProject PRIVATE VulkanHppModule ) Configuring the named module is straightforward; add any required Vulkan-Hpp feature macros (listed in Configuration Options) to target_compile_definitions .例えば:
# Disable exceptions, disable smart handles, disable constructors
target_compile_definitions ( VulkanHppModule PRIVATE
VULKAN_HPP_NO_EXCEPTIONS
VULKAN_HPP_NO_SMART_HANDLE
VULKAN_HPP_NO_CONSTRUCTORS
) It is important to have VULKAN_HPP_DISPATCH_LOADER_DYNAMIC defined equally for both the module and an importing project. To use the dynamic dispatcher, set it to 1 ; otherwise, leave it undefined or set it to 0 . In CMake, do this in a single line with target_compile_definitions and the PUBLIC scope:
target_compile_definitions ( VulkanHppModule PUBLIC
VULKAN_HPP_DISPATCH_LOADER_DYNAMIC=1
)
# ...
target_link_libraries ( YourProject PRIVATE VulkanHppModule ) Furthermore, you may also prefer linking VulkanHppModule to just the Vulkan::Headers target with the PUBLIC scope instead of Vulkan::Vulkan , so that the vulkan-1 library is not linked in, and the Vulkan headers are available to your consuming project, as detailed further below.
target_link_libraries ( VulkanHppModule PUBLIC Vulkan::Headers ) Finally, supply the macro VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE exactly once in your source code, just as in the non-module case. In order to have that macro available, include vulkan_hpp_macros.hpp , a lightweight header providing all Vulkan-Hpp related macros and defines. And as explained above, you need to initialize that dispatcher in two or three steps:
import vulkan_hpp;
# include < vulkan/vulkan_hpp_macros.hpp >
# if VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1
VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
# endif
auto main ( int argc, char * const argv[]) -> int
{
# if ( VULKAN_HPP_DISPATCH_LOADER_DYNAMIC == 1 )
// initialize minimal set of function pointers
VULKAN_HPP_DEFAULT_DISPATCHER. init ();
# endif
auto appInfo = vk::ApplicationInfo ( " My App " , 1 , " My Engine " , 1 , vk::makeApiVersion ( 1 , 0 , 0 , 0 ));
// ...
} An example is provided in tests/Cpp20Modules/Cpp20Modules.cpp .
Finally, you can configure and build your project as usual. Note that CMake currently only supports the Ninja and Visual Studio generators for C++ modules.
If you want to use the Vulkan-Hpp C++ module without CMake, you must first pre-compile it, and then import it into your project. You will also need to define any macros that control various features of Vulkan-Hpp, such as VULKAN_HPP_NO_EXCEPTIONS and VULKAN_HPP_NO_SMART_HANDLE . Different compilers have different command-lines for module pre-compilation; however, for initial use, some examples are provided below, assuming the same main.cpp consumer as above.
For MSVC, source vcvars64.bat or use a Developer Command Prompt/Developer PowerShell instance, and run the following:
cl.exe /std:c++20 /interface /TP < path-to-vulkan-hpp > vulkan.cppm
cl.exe /std:c++20 /reference vulkan=vulkan.ifc main.cpp vulkan.obj
.main.exeFor Clang, run the following:
clang++ -std=c++20 < path-to-vulkan-hpp > /vulkan.cppm -precompile -o vulkan.pcm
clang++ -std=c++20 -fprebuilt-module-path=. main.cpp vulkan.pcm -o main
./mainMore information about module compilation may be found at the respective compiler's documentation:
When you configure your project using CMake, you can enable SAMPLES_BUILD to add some sample projects to your solution. Most of them are ports from the LunarG samples, but there are some more, like CreateDebugUtilsMessenger, InstanceVersion, PhysicalDeviceDisplayProperties, PhysicalDeviceExtensions, PhysicalDeviceFeatures, PhysicalDeviceGroups, PhysicalDeviceMemoryProperties, PhysicalDeviceProperties, PhysicalDeviceQueueFamilyProperties, and RayTracing. All those samples should just compile and run. When you configure your project using CMake, you can enable TESTS_BUILD to add some test projects to your solution. Those tests are just compilation tests and are not required to run.
As vulkan.hpp is pretty big, some compilers might need some time to digest all that stuff. In order to potentially reduce the time needed to compile that header, a couple of defines will be introduced, that allow you to hide certain features. Whenever you don't need that corresponding feature, defining that value might improve your compile time. Currently, there are just a couple of such defines:
VULKAN_HPP_NO_SPACESHIP_OPERATOR , which removes the spaceship operator on structures (available with C++20)VULKAN_HPP_NO_TO_STRING , which removes the various vk::to_string functions on enums and bitmasks.VULKAN_HPP_USE_REFLECT , this one needs to be defined to use the reflection function on structures. It's very slow to compile, though! As Vulkan-Hpp often needs to switch between C++ vk-types and corresponding bit-identical C-types, using reinterpret_cast , it is highly recommended to use the compile option -fno-strict-aliasing to prevent potentially breaking compile optimizations.
There are a couple of defines you can use to control the feature set and behaviour of vulkan.hpp :
At various places in vulkan.hpp an assertion statement is used. By default, the standard assert funtions from <cassert> is called. By defining VULKAN_HPP_ASSERT before including vulkan.hpp , you can change that to any function with the very same interface.
If there are no exceptions enabled (see VULKAN_HPP_NO_EXCEPTIONS ), an assertion statement checks for a valid success code returned from every vulkan call. By default, this is the very same assert function as defined by VULKAN_HPP_ASSERT , but by defining VULKAN_HPP_ASSERT_ON_RESULT you can replace just those assertions with your own function, using the very same interface.
Every vk-function gets a Dispatcher as its very last argument, which defaults to VULKAN_HPP_DEFAULT_DISPATCHER . If VULKAN_HPP_DISPATCH_LOADER_DYNAMIC is defined to be 1 , it is defaultDispatchLoaderDynamic . This in turn is the dispatcher instance, which is defined by VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE , which has to be used exactly once in your sources. If, on the other hand, VULKAN_HPP_DISPATCH_LOADER_DYNAMIC is defined to something different from 1 , VULKAN_HPP_DEFAULT_DISPATCHER is set to be DispatchLoaderStatic() . You can use your own default dispatcher by setting VULKAN_HPP_DEFAULT_DISPATCHER to an object that provides the same API. If you explicitly set VULKAN_HPP_DEFAULT_DISPATCHER , you need to set VULKAN_HPP_DEFAULT_DISPATCHER_TYPE accordingly as well.
This names the default dispatcher type, as specified by VULKAN_HPP_DEFAULT_DISPATCHER . Per default, it is DispatchLoaderDynamic or DispatchLoaderStatic, depending on VULKAN_HPP_DISPATCH_LOADER_DYNAMIC being 1 or not 1 , respectively. If you explicitly set VULKAN_HPP_DEFAULT_DISPATCHER , you need to set VULKAN_HPP_DEFAULT_DISPATCHER_TYPE accordingly as well.
If you have not defined your own VULKAN_HPP_DEFAULT_DISPATCHER , and have VULKAN_HPP_DISPATCH_LOADER_DYNAMIC defined to be 1 (the default), you need to have the macro VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE exactly once in any of your source files to provide storage for that default dispatcher. VULKAN_HPP_STORAGE_API then controls the import/export status of that default dispatcher.
When this is defined before including vulkan.hpp , you essentially disable all enhanced functionality. All you then get is:
vk::Flags for bitmasks;vk::StructureChain for compile-time construction of structure chains.If this is not defined, you additionally get:
vk::ArrayProxy<> ), simplifying handling of array data; returning requested data; throwing exceptions on errors (as long as VULKAN_HPP_NO_EXCEPTIONS is not defined);VULKAN_HPP_NO_STRUCT_CONSTRUCTORS is not defined) (consuming vk::ArrayProxyNoTemporaries<> );vk::ArrayProxyNoTemporaries<> );vk::ArrayProxy<> and vk::ArrayProxyNoTemporaries<>vulkan_raii.hpp This either selects the dynamic (when it's 1 ) or the static (when it's not 1 ) DispatchLoader as the default one, as long as it's not explicitly specified by VULKAN_HPP_DEFAULT_DISPATCHER . By default, this is defined to be 1 if VK_NO_PROTOTYPES is defined, otherwise 0 .
By default, a little helper class DynamicLoader is used to dynamically load the vulkan library. If you set it to something different than 1 before including vulkan.hpp , this helper is not available, and you need to explicitly provide your own loader type for the function DispatchLoaderDynamic::init() .
When this is not externally defined and VULKAN_HPP_CPP_VERSION is at least 23 , VULKAN_HPP_EXPECTED is defined to be std::expected , and VULKAN_HPP_UNEXPECTED is defined to be std::unexpected .
By default, the member m_mask of the Flags class template is private. This is to prevent accidentally setting a Flags with some inappropriate value. But it also prevents using a Flags , or a structure holding a Flags , to be used as a non-type template parameter. If you really need that functionality, and accept the reduced security, you can use this define to change the access specifier for m_mask from private to public, which allows using a Flags as a non-type template parameter.
This define can be used to enable m_handle = exchange( rhs.m_handle, {} ) in move constructors of Vulkan-Hpp handles, which default-initializes the rhs underlying value. By default Vulkan-Hpp handles behave like trivial types -- move constructors copying value.
This define can be used to specify your own hash combiner function. In order to determine the hash of a vk-structure, the hashes of the members of that struct are to be combined. This is done by this define, which by default is identical to what the function boost::hash_combine() does. It gets the type of the to-be-combined value, the seed, which is the combined value up to that point, and finally the to-be-combined value. This hash calculation determines a "shallow" hash, as it takes the hashes of any pointer in a structure, and not the hash of a pointed-to value.
This is set to be the compiler-dependent attribute used to mark functions as inline. If your compiler happens to need some different attribute, you can set this define accordingly before including vulkan.hpp .
By default, the namespace used with vulkan.hpp is vk . By defining VULKAN_HPP_NAMESPACE before including vulkan.hpp , you can adjust this.
By default, the file vulkan_to_string.hpp is included by vulkan.hpp and provides functions vk::to_string for enums and bitmasks. If you don't need those functions, you can define VULKAN_HPP_NO_TO_STRING to prevent that inclusion. If you have certain files where you want to use those functions nevertheless, you can explicitly include vulkan_to_string.hpp there.
With C++20, designated initializers are available. Their use requires the absence of any user-defined constructors. Define VULKAN_HPP_NO_CONSTRUCTORS to remove constructors from structs and unions.
When a vulkan function returns an error code that is not specified to be a success code, an exception is thrown unless VULKAN_HPP_NO_EXCEPTIONS is defined before including vulkan.hpp .
With C++17, all vk-functions returning something are declared with the attribute [[nodiscard]] . This can be removed by defining VULKAN_HPP_NO_NODISCARD_WARNINGS before including vulkan.hpp .
By defining VULKAN_HPP_NO_SETTERS before including vulkan.hpp , setter member functions will not be available within structs and unions. Modifying their data members will then only be possible via direct assignment.
By defining VULKAN_HPP_NO_SMART_HANDLE before including vulkan.hpp , the helper class vk::UniqueHandle and all the unique handle types are not available.
With C++20, the so-called spaceship-operator <=> is introduced. If that operator is supported, all the structs and classes in vulkan.hpp use the default implementation of it. As currently some implementations of this operator are very slow, and others seem to be incomplete, by defining VULKAN_HPP_NO_SPACESHIP_OPERATOR before including vulkan.hpp you can remove that operator from those structs and classes.
By default, if VULKAN_HPP_ENABLE_DYNAMIC_LOADER_TOOL is enabled on Win32, vulkan.hpp declares HINSTANCE , LoadLibraryA , and other required symbols. It could cause conflicts with the Windows.h alternatives, such as WindowsHModular . With this define, you can disable these declarations, but you will have to declare them before the vulkan.hpp is included.
If both, VULKAN_HPP_NO_EXCEPTIONS and VULKAN_HPP_EXPECTED are defined, the vk::raii-classes don't throw exceptions. That is, the actual constructors are not available, but the creation-functions must be used. For more details have a look at the vk_raii_ProgrammingGuide.md .
Even though vk::UniqueHandle and vk::SharedHandle are semantically close to pointers, an implicit cast operator to the underlying vk::Handle might be handy. You can add that implicit cast operator by defining VULKAN_HPP_SMART_HANDLE_IMPLICIT_CAST .
With this define you can specify whether the DispatchLoaderDynamic is imported or exported (see VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE ). If VULKAN_HPP_STORAGE_API is not defined externally, and VULKAN_HPP_STORAGE_SHARED is defined, depending on the VULKAN_HPP_STORAGE_SHARED_EXPORT being defined, VULKAN_HPP_STORAGE_API is either set to __declspec( dllexport ) (for MSVC) / __attribute__( ( visibility( "default" ) ) ) (for gcc or clang) or __declspec( dllimport ) (for MSVC), respectively. For other compilers, you might specify the corresponding storage by defining VULKAN_HPP_STORAGE_API on your own.
32-bit vulkan is not typesafe for non-dispatchable handles, so we don't allow copy constructors on this platform by default. To enable this feature on 32-bit platforms, #define VULKAN_HPP_TYPESAFE_CONVERSION 1 . To disable this feature on 64-bit platforms, #define VULKAN_HPP_TYPESAFE_CONVERSION 0 .
See VULKAN_HPP_EXPECTED .
With this define you can include a reflection mechanism on the vk-structures. It adds a function reflect that returns a tuple-version of the structure. That tuple then could easily be iterated. But at least for now, that feature takes lots of compile-time resources, so currently it is recommended to enable that feature only if you're willing to pay that price.
Feel free to submit a PR to add to this list.
Copyright 2015-2020 The Khronos Group Inc.
Apacheライセンス、バージョン2.0(「ライセンス」)に基づいてライセンスされています。ライセンスに準拠している場合を除き、このファイルを使用することはできません。ライセンスのコピーを取得できます
http://www.apache.org/licenses/LICENSE-2.0
適用法で要求されていないか、書面で合意されていない限り、ライセンスに基づいて配布されたソフトウェアは、明示または黙示のいずれかの保証または条件なしに、「現状のまま」に基づいて配布されます。ライセンスに基づく権限と制限を管理する特定の言語のライセンスを参照してください。