Vulkan-Samples Documentation

One stop solution for all Vulkan samples

RAW Doc

Technical Documentation: KhronosGroup/Vulkan-Samples

โ„น๏ธ Provenance: Multi-Tier Ingestion ยท CodeWiki Reference

README (`docs/README.adoc`)

////

  • Copyright (c) 2024, Sascha Willems
  • SPDX-License-Identifier: Apache-2.0
  • Licensed under the Apache License, Version 2.0 the "License";
  • you may not use this file except in compliance with the License.
  • You may obtain a copy of the License at
  • text
    http://www.apache.org/licenses/LICENSE-2.0
  • Unless required by applicable law or agreed to in writing, software
  • distributed under the License is distributed on an "AS IS" BASIS,
  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  • See the License for the specific language governing permissions and
  • limitations under the License.

////
= General documentation

This folder contains documentation on general usage of the samples.


Build (`docs/build.adoc`)

////

  • Copyright (c) 2019-2025, Arm Limited and Contributors
  • SPDX-License-Identifier: Apache-2.0
  • Licensed under the Apache License, Version 2.0 the "License";
  • you may not use this file except in compliance with the License.
  • You may obtain a copy of the License at
  • text
    http://www.apache.org/licenses/LICENSE-2.0
  • Unless required by applicable law or agreed to in writing, software
  • distributed under the License is distributed on an "AS IS" BASIS,
  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  • See the License for the specific language governing permissions and
  • limitations under the License.

////
= Build Guides
// omit in toc
:pp: {plus}{plus}
ifndef::site-gen-antora[]
:toc:
endif::[]

== CMake Options

The following options are used to change the build configuration

=== VKB_++++++++++++

Choose whether to include a sample at build time.

  • ON - Build Sample
  • OFF - Exclude Sample

Default: ON

=== VKB_BUILD_SAMPLES

Choose whether to build the samples.

  • ON - Build All Samples
  • OFF - Skip building Samples

Default: ON

=== VKB_BUILD_TESTS

Choose whether to build the tests

  • ON - Build All Tests
  • OFF - Skip building Tests

Default: OFF

=== VKB_VALIDATION_LAYERS

Enable Validation Layers

Default: OFF

=== VKB_VALIDATION_LAYERS_GPU_ASSISTED

Enable https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/main/docs/gpu_validation.md[GPU assisted validation layers], used primarily for VK_EXT_descriptor_indexing.

Default: OFF

=== VKB_VALIDATION_LAYERS_BEST_PRACTICES

Enable https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/main/docs/best_practices.md[best practices validation layers].

Default: OFF

=== VKB_VALIDATION_LAYERS_SYNCHRONIZATION

Enable https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/main/docs/synchronization_usage.md[synchronization validation layers].

Default: OFF

=== VKB_VULKAN_DEBUG

Enable VK_EXT_debug_utils or VK_EXT_debug_marker, if supported.
This enables debug names for Vulkan objects, and markers/labels in command buffers.

  • See the xref:../samples/extensions/debug_utils/README.adoc[debug utils sample] for more information.

Default: ON

=== VKB_WARNINGS_AS_ERRORS

Treat all warnings as errors

Default: ON

=== VKB_PROFILING

Enable profiling using the https://github.com/wolfpld/tracy[Tracy profiler].

We currently use Tracy v0.10.0 if you do not use the correct Tracy Profiler version as the Tracy Client version used in Sample you will get a protocol mismatch error.

Windows users can download the profiler from the https://github.com/wolfpld/tracy/releases/tag/v0.10[Tracy v0.10.0 release page]
Other platforms require the user to build the profiler from source see the https://github.com/wolfpld/tracy/releases/download/v0.10/tracy.pdf[Tracy documentation (pdf)] for more information on how to build for your platform.

Tracy is not currently enabled for Android builds. In the future, we may add support for this.

Default: OFF

=== VKB_SKIP_SLANG_SHADER_COMPILATION

By default, Slang shaders are compiled if a Slang compiler is found on the system. In cases where this is undesirable, set this to OFF to disable Slang shader compilation.

You can still select Slang as a shading language target for the samples since Slang shaders are included as precompiled SPIR-V files.

Default: OFF

== Quality Assurance

We use a small set of tools to provide a level of quality to the project.
These tools are part of our CI/CD process.
If your local environment does not have the same versions of the tools we use in the CI you may see some errors or warnings pop-up when pushing.

For up-to date version information please see the repositories for the individual tools

== 3D models

Most of the samples require 3D models downloaded from https://github.com/KhronosGroup/Vulkan-Samples-Assets.
That repository is referenced as a git submodule by this project so if you followed the clone instructions in the xref:../README.adoc[project readme] you will already have the models locally under ./assets/.

On Android, Gradle will run CMake which will sync assets to the device if there has been a change.

However, to sync them manually you may run the following command to ensure up to date assets are on the device:


adb push --sync assets /sdcard/Android/data/com.khronos.vulkan_samples/files/ adb push --sync shaders /sdcard/Android/data/com.khronos.vulkan_samples/files/

== Performance data

In order for performance data to be displayed, profiling needs to be enabled on the device.
Some devices may disable it by default.

Profiling can be enabled via adb:


adb shell setprop security.perf_harden 0


Performance data is captured using HWCPipe.
For details on this project and how to integrate it in your pipeline, visit: https://github.com/ARM-software/HWCPipe


== Windows

=== Dependencies

  • CMake v3.12+
  • Python 3
  • Visual Studio 2017 or above
  • <<cmake-options,CMake Options>>
  • <<3d-models,3D models>>

=== Clang Format and Visual Studio

It is recommended to use clang-format-15, which is compatible with the styles in our .clang-format file.
It is also used by CI and is a basic version installed with Visual Studio 2022.

Go to the http://releases.llvm.org/download.html[LLVM downloads page] to get clang.

=== Build with CMake and Visual Studio


Please make sure, when running any sample, that you either:


Step 1. Generate the VS solution from the root of the repository

(For other VS versions please refer to https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html#id15[CMake Generators])

cmake -G "Visual Studio 17 2022" -A x64 -S . -Bbuild/windows

Open the vulkan_samples.sln or vulkan_samples.slnx VS solution inside build/windows and build with Ctrl-Shift-B. To run Vulkan Samples, use Visual Studio's Debug Properties selection and set the Debugging Command Arguments to --help. Click the "Local Windows Debugger" button and you should see the help output in the terminal. For convenience, the default setting is to run the hello_triangle sample; just edit that to your desired sample to run.

Alternatively, for command line builds use the steps below:

Step 2. Build the Visual Studio project


cmake --build build/windows --config Release --target vulkan_samples

Step 3. Run the Vulkan Samples application by specifying the name of the sample


build\windows\app\bin\Release\AMD64\vulkan_samples.exe sample

== Linux

=== Dependencies

  • CMake v3.12+
  • C{pp}20 Compiler
  • <<cmake-options,CMake Options>>
  • <<3d-models,3D models>>

sudo apt-get install cmake g++ xorg-dev libglu1-mesa-dev libwayland-dev libxkbcommon-dev

=== Selecting the window system

On Linux, the samples support different window systems. If not explicitly set, default is X11 Xcb. If you want to build with another window system, use the VKB_WSI_SELECTION CMake option like this:


cmake -G "Unix Makefiles" -Bbuild/linux -DCMAKE_BUILD_TYPE=Release -DVKB_WSI_SELECTION=WAYLAND

Available Linux window systems:

[cols="1,1"]
|===
| VKB_WSI_SELECTION | Window system

| XCB | X11 Xcb (Default)
| XLIB | X11 Xlib
| WAYLAND | Wayland
| D2D | Direct to Display (VK_KHR_DISPLAY)
|===

=== Build with CMake

Step 1. The following command will generate the project


cmake -G "Unix Makefiles" -Bbuild/linux -DCMAKE_BUILD_TYPE=Release

Step 2. Build the project


cmake --build build/linux --config Release --target vulkan_samples -j$(nproc)

Step 3. Run the Vulkan Samples application to display the help message


./build/linux/app/bin/Release/x86_64/vulkan_samples --help

== macOS

=== Dependencies

=== Set your environment variables


source /PATH/TO/VULKAN/SDK/setup-env.sh

=== Build with CMake and Xcode

Step 1. The following command will generate the project


cmake -G Xcode -Bbuild/mac-xcode -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_SYSROOT=macosx -DCMAKE_OSX_DEPLOYMENT_TARGET=13.3

Open the vulkan_samples Xcode project inside build/mac-xcode and build with command-B. To run Vulkan Samples, use Xcode's edit-scheme selection and set the arguments to --help. Click the "Play" button and you should see the help output in the terminal. For convenience, the default setting is to run the hello_triangle sample; just edit that to your desired sample to run.

Alternatively, for command line builds use the steps below:


cmake -Bbuild/mac -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_SYSROOT=macosx -DCMAKE_OSX_DEPLOYMENT_TARGET=13.3

Step 2. Build the project


cmake --build build/mac --config Release --target vulkan_samples -j$(sysctl -n hw.ncpu)

Step 3. Run the Vulkan Samples application to display the help message


./build/mac/app/bin/Release//vulkan_samples --help

== iOS
=== Dependencies

  • CMake v3.28+ (Apple xcframeworks require at least 3.28)
  • Xcode v12 for Apple Silicon
  • Command Line Tools (CLT) for Xcode xcode-select --install
  • https://sdk.lunarg.com/sdk/download/latest/mac/vulkan_sdk.dmg[Vulkan SDK] - Download and Install the Vulkan SDK making sure "Development libraries for iOS" is selected
  • Vulkan at least version 1.3.278 to get the frameworks
  • <<cmake-options,CMake Options>>
  • <<3d-models,3D models>>

=== Set your environment variables

NB: For iOS you must run the setup-env.sh located inside the Vulkan SDK's iOS directory


source /PATH/TO/VULKAN/SDK/iOS/setup-env.sh

=== Build with CMake and Xcode

Step 1. The following command will generate the project


cmake -G Xcode -Bbuild/ios -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphoneos -DCMAKE_OSX_DEPLOYMENT_TARGET=16.3 -DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=YES -DCMAKE_OSX_ARCHITECTURES=arm64 -DCMAKE_IOS_INSTALL_COMBINED=NO -DCMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM="XXXX" -DMACOSX_BUNDLE_GUI_IDENTIFIER="com.YYYY.vulkansamples"

NB: You MUST change the XXXX in the above to your TeamID (or Organizational Unit identifier in your Apple Development certificate) for code signing, and YYYY to your bundle identifier. iOS will NOT allow the application to run without code signing and bundle identifier setup.

Alternatively, you can build for the iOS Simulator (requires Vulkan SDK 1.4.321.0 or later) without code signing or specifying a bundle identifier (a default bundle id will be used). However, depending on your host architecture, you MUST select either arm64 (Apple Silicon) or x86_64 in the command below. Note: On arm64 (Apple Silicon) hosts the Vulkan library may not load on iOS Simulator without specifying your TeamID and bundle identifier as shown above.


cmake -G Xcode -Bbuild/ios-sim -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_NAME=iOS -DCMAKE_OSX_SYSROOT=iphonesimulator -DCMAKE_OSX_DEPLOYMENT_TARGET=16.3 -DCMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH=YES -DCMAKE_OSX_ARCHITECTURES= -DCMAKE_IOS_INSTALL_COMBINED=NO

Step 2. Build the project

It's recommended to open the vulkan_samples Xcode project that is generated inside build/ios or build/ios-sim and build with command-B.

Alternatively, you can build with cmake as shown here


cmake --build build/ios --config Release --target vulkan_samples -j$(sysctl -n hw.ncpu) -- -allowProvisioningUpdates

Step 3. Run the Vulkan Samples application

To run Vulkan Samples, one must have an iOS physical or simulator device provisioned and working with Xcode. Open the Xcode project and ensure that can build/install to a device through Xcode normally.
Once the bundle is created from the build command in Step 2, use the edit-scheme selection in Xcode and set the arguments to --help.
Click the "Play" button and you should see the help output in the terminal.
For convenience, the default setting is to run the hello_triangle sample; just edit that to your desired sample to run.

== Android

=== Dependencies

For all dependencies set the following environment variables:

  • JDK 8+ JAVA_HOME=<SYSTEM_DIR>/java
  • Android SDK ANDROID_HOME=<WORK_DIR>/android-sdk
  • CMake v3.16+
  • Android NDK r23+ ANDROID_NDK_HOME=<WORK_DIR>/android-ndk
  • <<cmake-options,CMake Options>>
  • <<3d-models,3D models>>
  • <>

We use this environment in the CI https://github.com/KhronosGroupActions/android-ndk-build[Android NDK Repository]


=== Android Studio (Recommended)

It is highly recommended to install https://d.android.com/studio[Android Studio] to build, run and trace the sample project. Building via Android Studio requires at least Ladybug 2024.2.1.

Android Studio uses the following plugins/tools to build samples:

  • Android Gradle Plugin
  • CMake Plugin, which installs and uses Ninja
  • NDK

Their versions are configured in the https://github.com/KhronosGroup/Vulkan-Samples/blob/main/bldsys/cmake/template/gradle/build.gradle.in[build.gradle.in] and https://github.com/KhronosGroup/Vulkan-Samples/blob/main/bldsys/cmake/template/gradle/app.build.gradle.in[app.build.gradle.in files];
when updating these versions, refer to https://developer.android.com/studio/projects/install-ndk#default-ndk-per-agp[the official documentation for the recommended combinations].

=== Build with Gradle

==== Generate the gradle project

To generate the gradle project, run the following command:


./scripts/generate.py android

A new folder will be created in the root directory at build\android_gradle

==== Install dependencies

https://d.android.com/reference/tools/gradle-api[Android Gradle Plugin] (used by Android Studio) may not auto install dependencies.
You will need to install them if they have not been installed:


yes | ${your-sdk}/cmdline-tools/latest/bin/sdkmanager --licenses ${your-sdk}/cmdline-tools/latest/bin/sdkmanager --install "ndk;25.1.8937393" --channel=3 ${your-sdk}/cmdline-tools/latest/bin/sdkmanager --install "cmake;3.22.1" --channel=3

==== Build the project


cd build/android_gradle


Prefer a release build for better performance unless you want to actively debug the application.


For a release build:


gradle assembleRelease

For a debug build:


gradle assembleDebug

==== Install the apk on the device

You can now install the apk on a connected device using the Android Debug Bridge:

For a release build:


adb install app/build/outputs/apk/release/vulkan_samples-release.apk

For a debug build:


adb install app/build/outputs/apk/debug/vulkan_samples-debug.apk

=== Build with Android Studio

With https://d.android.com/studio[Android Studio] you can open the build/android_gradle/build.gradle project, compile and run the project from here.
The lastest Android Studio release is recommended.

If you have agreed with the licenses previously on your development system, Android Studio will automatically install, at the start up time, CMake and NDK with the version configured in your build/android-gradle/build.gradle.
Otherwise (or if the installation failed), you need to install the required CMake and NDK manually, refer to https://d.android.com/studio/projects/install-ndk[the official instructions] for the detailed steps.
The default installed locations are:

  • $SDK-ROOT-DIR/ndk/$ndkVersion for NDK.
  • $SDK-ROOT-DIR/cmake/$cmake-version for CMake.

Android Studio will use the above default locations without any environment variable requirement;
if you want to use the same NDK and CMake versions for other purpose, you can simply configure your environment variables to these locations.
If you do set up the NDK and CMake environment variables, Android Studio will use them instead of the default locations.


Memory Limits (`docs/memory_limits.adoc`)

////

  • Copyright (c) 2019-2023, Arm Limited and Contributors
  • SPDX-License-Identifier: Apache-2.0
  • Licensed under the Apache License, Version 2.0 the "License";
  • you may not use this file except in compliance with the License.
  • You may obtain a copy of the License at
  • text
    http://www.apache.org/licenses/LICENSE-2.0
  • Unless required by applicable law or agreed to in writing, software
  • distributed under the License is distributed on an "AS IS" BASIS,
  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  • See the License for the specific language governing permissions and
  • limitations under the License.

////
= Memory limits with Vulkan
// omit in toc

== Contents
// omit in toc

  • <<mali-gpus,Mali GPUs>>

== Mali GPUs

This article covers situations in which a Vulkan application might trigger an out of memory (OOM) condition on Mali GPUs, resulting in a DEVICE_LOST error, even if the API usage is correct.
The OOM condition that developers hit most often is due to a very high vertex load, which might be relatively common when porting Vulkan applications from desktop to mobile.

Mali GPUs have a memory region which is available to store the intermediate geometry output from a render pass.
This memory is used to store all of the varying data generated by vertex, tessellation, and geometry shading prior to fragment shading.
Exceeding the size of this region may result in a VK_ERROR_DEVICE_LOST.
The limit is fixed to 180 MB on current Mali GPUs, but it may be increases or lifted altogether in future GPUs.

The reasoning behind this limit is that tile-based renderers need to write out and then read back intermediate geometry output, thus vertex load is directly correlated to memory bandwidth.
For a typical program using 64 bytes of varying data per vertex the 180 MB of intermediate storage can contain over 2 million vertices, which we expect to be enough for normal mobile application usage.
We will now cover the reasons why such a vertex load is unlikely to be sustainable and possible mitigations if your application is hitting it.

Let us consider a vertex-heavy application with a single render pass that reaches the 180 MB limit.
Since the GPU has to write the data out and read it back from memory, this results in 2 x 180 = 360 MB/render pass, which at 30 FPS brings memory bandwidth up to 30 x 360 = 10.8 GB/s.
Memory bandwidth has a direct correlation with power consumption, which can be estimated as 100 mW/(GB/s).
This means that an application using 180 MB of varying data will consume at least 1.08 W, and this does not consider further contributions to memory bandwidth and general GPU power consumption.
A mobile GPU cannot sustain such a power usage without overheating, which would further cause a reduction of GPU frequency and a performance drop.

The only real solution to the issue is to keep the application's vertex count below approximately 2 million, as derived above for an average of 64 bytes of varying data per vertex.
In scenarios where the memory storage is exceeded and reducing the vertex load is not feasible, we recommend that the application splits the render pass into multiple render passes, each using a safe amount of intermediate storage.
Later render passes can use a loadOp=LOAD to restore the content of the framebuffer and continue rendering on top of earlier rendering.
This form of incremental rendering might impact performance, due to the write-out and further read-back of the color image.

If your vertex load is unpredictable and you are hitting DEVICE_LOST issues in the field, you can set up a scheme for estimating memory consumption for each draw call in a render pass, then performing incremental rendering if the limit is reached.
You should keep in mind that memory is allocated for all vertex indices between the min and max index referenced by a draw call, and for all generated vertices for tessellation and geometry shading, even if they are subsequently culled by the clipping and culling pass.
Such an estimate will be conservative, as the actual amount of memory allocated might be lower, so we don't recommend adding a further safety margin to the 180 MB limit.


Misc (`docs/misc.adoc`)

////

  • Copyright (c) 2019-2025, Arm Limited and Contributors
  • SPDX-License-Identifier: Apache-2.0
  • Licensed under the Apache License, Version 2.0 the "License";
  • you may not use this file except in compliance with the License.
  • You may obtain a copy of the License at
  • text
    http://www.apache.org/licenses/LICENSE-2.0
  • Unless required by applicable law or agreed to in writing, software
  • distributed under the License is distributed on an "AS IS" BASIS,
  • WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  • See the License for the specific language governing permissions and
  • limitations under the License.

////
= Miscellaneous

== Controls

[cols="<,^,^"]
|===
| Action | Desktop | Mobile

| Move around the scene
| ++++++WASD++++++
| ++++++press++++++ + ++++++hold++++++

| Rotate camera
| ++++++right mouse button++++++ + ++++++drag++++++
| ++++++press++++++ + ++++++move++++++

| Pan

++++++left mouse button++++++ + ++++++drag++++++

| Movement speed reduced

++++++shift++++++

| Movement speed increased

++++++ctrl++++++

| toggle GUI
| ++++++left click++++++
| ++++++tap++++++

| toggle Debug Window
| ++++++right click++++++
| 2 finger ++++++tap++++++
|===

== Debug Window

The Debug Window shows information about the current application.

image::./images/debug-window.png[Debug Window]

== Driver version

The debug window shows the driver version of the GPU, which follows the https://registry.khronos.org/vulkan/specs/latest/html/chap44.html#extendingvulkan-coreversions-versionnumbers[Vulkan semantics], with a major, minor, and patch number.
New versions of the driver will increment these numbers.

The framework is able to get these values by calling vkGetPhysicalDeviceProperties(physical_device, &properties).
This will set all attributes of properties, which type is struct VkPhysicalDeviceProperties.
Then it extracts the relevant bits from properties.driverVersion using the following Vulkan macros:

[,c]

VK_VERSION_MAJOR(properties.driverVersion); VK_VERSION_MINOR(properties.driverVersion); VK_VERSION_PATCH(properties.driverVersion);

It is important to note that old Arm Mali drivers (before Bifrost r14 and Midgard r26) may not implement this feature, therefore the values returned will be undefined.


Pull Request Template (`docs/pull_request_template.md`)

Description

Please include a summary of the change, new sample or fixed issue. Please also include relevant motivation and context.
Please read the contribution guidelines

Fixes #

General Checklist:

Please ensure the following points are checked:

  • My code follows the coding style
  • I have reviewed file licenses
  • I have commented any added functions (in line with Doxygen)
  • I have commented any code that could be hard to understand
  • My changes do not add any new compiler warnings
  • My changes do not add any new validation layer errors or warnings
  • I have used existing framework/helper functions where possible
  • My changes do not add any regressions
  • I have tested every sample to ensure everything runs correctly
  • This PR describes the scope and expected impact of the changes I am making

Note: The Samples CI runs a number of checks including:

  • I have updated the header Copyright to reflect the current year (CI build will fail if Copyright is out of date)
  • My changes build on Windows, Linux, macOS and Android. Otherwise I have documented any exceptions

If this PR contains framework changes:

  • I did a full batch run using the batch command line argument to make sure all samples still work properly

Sample Checklist

If your PR contains a new or modified sample, these further checks must be carried out in addition to the General Checklist:

  • I have tested the sample on at least one compliant Vulkan implementation
  • If the sample is vendor-specific, I have tagged it appropriately
  • I have stated on what implementation the sample has been tested so that others can test on different implementations and platforms
  • Any dependent assets have been merged and published in downstream modules
  • For new samples, I have added a paragraph with a summary to the appropriate chapter in the readme of the folder that the sample belongs to e.g. api samples readme
  • For new samples, I have added a tutorial README.md file to guide users through what they need to know to implement code using this feature. For example, see conditional_rendering
  • For new samples, I have added a link to the Antora navigation so that the sample will be listed at the Vulkan documentation site

--- METRICS ---