Package vulkan provides Go bindings for Vulkan — a low-overhead, cross-platform 3D graphics and compute API. Updated February 9, 2023 — Vulkan 1.3.239.
The Vulkan API is a cross-platform industry standard enabling developers to target a wide range of devices with the same graphics API.
This Go binding allows one to use Vulkan API directly within Go code, avoiding adding lots of C/C++ in the projects. The original version is at https://github.com/vulkan-go/vulkan (still on 1.1.88 from 2018) and a fork at https://github.com/goki/vulkan is being more actively maintained at this point.
See UPDATING for extensive notes on how to update to newer vulkan versions as they are released.
The original author, xlab
, has examples at: https://github.com/vulkan-go/demos and the beginnings of a toolkit at: https://github.com/vulkan-go/asche.
The updated version is being used extensively in the goki framework, powering the GoGi 2D and 3D GUI framework, based on the VGPU toolkit that manages the considerable complexity of dealing with Vulkan. VGPU is also used as a GPU compute engine framework in the emergent neural network modeling framework axon.
Usage of this project is straightforward due to the stateless nature of Vulkan API. Just import the package like this:
import vk "github.com/goki/vulkan"
Set the GetProcAddress pointer (used to look up Vulkan functions) using SetGetInstanceProcAddr or SetDefaultGetInstanceProcAddr. After that you can call Init to initialise the library. For example:
// Using SDL2:
vk.SetGetInstanceProcAddr(sdl.VulkanGetVkGetInstanceProcAddr())
// OR using GLFW:
vk.SetGetInstanceProcAddr(glfw.GetVulkanGetInstanceProcAddress())
// OR without using a windowing library (Linux only, recommended for compute-only tasks)
if err := vk.SetDefaultGetInstanceProcAddr(); err != nil {
panic(err)
}
if err := vk.Init(); err != nil {
panic(err)
}
And you're set. I must warn you that using the API properly is not an easy task at all, so beware and follow the official documentation: https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html
In order to simplify development, I created a high-level framework that manages Vulkan platform state and initialization. It is called asche because when you throw a gopher into volcano you get a pile of ash. Currently it's used in VulkanCube demo app.
MoltenVK provides a MoltenVK.xcframework
which contains static libraries for all Apple platforms. Unfortuantely, linking with a xcframework outside of XCode is not possible.
Instead vulkan-go expects the dylibs to be present in the library search path.
Follow the build instructions, but instead of make install
manually copy ./Package/Latest/MoltenVK/dylib/macOS/libMoltenVK.dylib
to /usr/local/lib
IMPORTANT: be sure to remove any existing libMoltenVK.dylib
file before copying a new one, otherwise you'll have to reboot your computer due to the way the gatekeeper mechanism works!
The following steps are needed when developing for iOS and not using the goki
tool. When using the goki
tool, it will do all of these steps for you; you just need to run goki setup ios
once to create the framework and then goki build
will always copy the framework and set the environment variables for you. This information only exists for reference if you are not using the goki
tool, and should not be relevant for most people.
Download the MoltenVK iOS asset from the MoltenVK GitHub releases. Then, copy it to your ~/Library/goki
directory, and make a .framework
by running:
install_name_tool -id @executable_path/MoltenVK.framework/MoltenVK libMoltenVK.dylib
lipo -create libMoltenVK.dylib -output MoltenVK
mkdir MoltenVK.framework
mv MoltenVK MoltenVK.framework
# now copy the Info.plist for MoltenVK.framework below into MoltenVK.framework/Info.plist
codesign --force --deep --verbose=2 --sign "[email protected]" MoltenVK.framework
codesign -vvvv MoltenVK.framework
When building apps, build the app with the environment variable CGO_LDFLAGS=-F/Users/{{you}}/Library/goki
. Then, after you build the app, run:
cp -r ~/Library/goki/MoltenVK.framework {{appname}}.app
For example:
cp -r ~/Library/goki/MoltenVK.framework drawtri.app
Info.plist for MoltenVK.framework
(needs to be copied when making a framework above)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>22F82</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>MoltenVK</string>
<key>CFBundleIdentifier</key>
<string>com.goki.MoltenVK</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>MoltenVK</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>iPhoneOS</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
main Info.plist for reference:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>22F82</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>main</string>
<key>CFBundleIdentifier</key>
<string>com.example.test.widgets</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Widgets</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>iPhoneOS</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>20E238</string>
<key>DTPlatformName</key>
<string>iphoneos</string>
<key>DTPlatformVersion</key>
<string>16.4</string>
<key>DTSDKBuild</key>
<string>20E238</string>
<key>DTSDKName</key>
<string>iphoneos16.4</string>
<key>DTXcode</key>
<string>1431</string>
<key>DTXcodeBuild</key>
<string>14E300c</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>MinimumOSVersion</key>
<string>16.4</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>arm64</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
A good brief of the current state of Vulkan validation layers: Explore the Vulkan Loader and Validation Layers (PDF).
There is a full support of validation layers with custom callbacks in Go. For my Android experiments I got the standard pack of layers from https://github.com/LunarG/VulkanTools and built them like this:
$ cd build-android
$ ./update_external_sources_android.sh
$ ./android-generate.sh
$ ndk-build
After that you'd copy the files to android/jni/libs
in your project and activate the ValidationLayers.mk
in your Android.mk
so when building APK they will be copied alongside with your shared library. It just works then:
[INFO] Instance extensions: [VK_KHR_surface VK_KHR_android_surface]
[INFO] Instance layers: [VK_LAYER_LUNARG_screenshot VK_LAYER_GOOGLE_unique_objects VK_LAYER_LUNARG_api_dump VK_LAYER_LUNARG_image VK_LAYER_LUNARG_core_validation VK_LAYER_LUNARG_object_tracker VK_LAYER_GOOGLE_threading VK_LAYER_LUNARG_parameter_validation VK_LAYER_LUNARG_swapchain]
[Layer Swapchain][ERROR 4] The surface in pCreateInfo->surface, that was given to vkCreateSwapchainKHR(), must be a surface that is supported by the device as determined by vkGetPhysicalDeviceSurfaceSupportKHR(). However, vkGetPhysicalDeviceSurfaceSupportKHR() was never called with this surface.
[Layer Swapchain][ERROR 10] vkCreateSwapchainKHR() called with a non-supported pCreateInfo->compositeAlpha (i.e. VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR). Supported values are:
VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
[Layer DS][ERROR 8] Attempt to set lineWidth to 0.000000 but physical device wideLines feature not supported/enabled so lineWidth must be 1.0f!
[Layer DS][ERROR 22] Unable to allocate 2 descriptors of type VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER from pool 0x1c. This pool only has 1 descriptors of this type remaining.
- vulkanGo.com
- SaschaWillems Demos (C++)
- LunarG Vulkan Samples (archived)
- Vulkan Samples from Khronos Group
- Official list of Vulkan resources
- API description
- Vulkan API quick reference
MIT