Skip to content

goki/vulkan

 
 

Repository files navigation

Golang Bindings for Vulkan API version-1.3.239 GoDoc

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.

Introduction

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.

Examples and usage

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.

How to use

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 os macOS

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!

MoltenVK on iOS

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 "rcoreilly@me.com" 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>

Validation Layers

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.

Useful links

License

MIT

About

Vulkan API bindings for Go programming language

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • C 60.7%
  • C++ 26.3%
  • Objective-C 10.2%
  • Go 2.5%
  • Other 0.3%