go-gl/glfw

GLFW: An invalid error was not accepted by the caller: APIUnavailable: Win32: Vulkan instance missing VK_KHR_win32_surface extension GLFW: Please report this bug in the Go package immediately.

Matthias-Schwarz opened this issue · 2 comments

Trying to create a surface for vulkan I get this error.

Cannot create surface: vulkan: error creating window surface: -7
GLFW: An invalid error was not accepted by the caller: APIUnavailable: Win32: Vulkan instance missing VK_KHR_win32_surface extension
GLFW: Please report this bug in the Go package immediately.
panic: vulkan: error creating window surface: -7
panic: APIUnavailable: Win32: Vulkan instance missing VK_KHR_win32_surface extension

This is the most minimal program I could come up with that reproduces this error:

package main

import (
	"fmt"
	"runtime"
	"strings"
	"github.com/go-gl/glfw/v3.3/glfw"
	vk "github.com/vulkan-go/vulkan"
)

func init() {
	// This is needed to arrange that main() runs on main thread.
	// See documentation for functions that are only allowed to be called from the main thread.
	runtime.LockOSThread()
}


var go_window *glfw.Window

func initWindow() {
	err := glfw.Init()
	if err != nil {
		panic(err)
	}
	glfw.WindowHint(glfw.ClientAPI, glfw.NoAPI)
	go_window, err = glfw.CreateWindow(640, 480, "Vulkan", nil, nil)
	if err != nil {
		panic(err)
	}
}

func cleanup() {
	if go_window != nil {
		go_window.Destroy()
	}
	glfw.Terminate()
}

func createVkInstance() *vk.Instance {
	vk.SetGetInstanceProcAddr(glfw.GetVulkanGetInstanceProcAddress())

	if err := vk.Init(); err != nil {
		panic(err)
	}
	var appInfo vk.ApplicationInfo
	appInfo.SType = vk.StructureTypeApplicationInfo
	appInfo.PApplicationName = "Hello Triangle"
	appInfo.ApplicationVersion = vk.MakeVersion(1, 0, 0)
	appInfo.PEngineName = "No Engine"
	appInfo.EngineVersion = vk.MakeVersion(1, 0, 0)
	appInfo.ApiVersion = vk.MakeVersion(1, 0, 0)
	var createInfo vk.InstanceCreateInfo
	createInfo.SType = vk.StructureTypeInstanceCreateInfo
	createInfo.PApplicationInfo = &appInfo

	createInfo.PpEnabledExtensionNames = go_window.GetRequiredInstanceExtensions()
	createInfo.EnabledExtensionCount = uint32(len(createInfo.PpEnabledExtensionNames))

	createInfo.PpEnabledLayerNames = append(createInfo.PpEnabledLayerNames, "VK_LAYER_KHRONOS_validation\x00")
	createInfo.EnabledLayerCount = uint32(len(createInfo.PpEnabledLayerNames))

	fmt.Println("Supported: ", glfw.VulkanSupported())

	var vkInstance *vk.Instance
	vkInstance = new(vk.Instance)
	result := vk.CreateInstance(&createInfo, nil, vkInstance)
	fmt.Println("Create Result: ", result) // TODO: Error if not 0
	return vkInstance
}

func checkPropertiesAndLayers() {
	var extensionCount uint32
	result := vk.EnumerateInstanceExtensionProperties("", &extensionCount, nil)
	extensionProperties := make([]vk.ExtensionProperties, extensionCount)
	result = vk.EnumerateInstanceExtensionProperties("", &extensionCount, extensionProperties)
	for i := 0; i < len(extensionProperties); i++ {
		extensionProperties[i].Deref()
		extensionProperties[i].Free()
		fmt.Println("Property: ", strings.Replace(string(extensionProperties[i].ExtensionName[:]), "\x00", "", -1))
	}
	fmt.Println("ExtensionCount: ", extensionCount)
	fmt.Println("Result: ", result)
	var layerCount uint32
	var availableLayers []vk.LayerProperties
	vk.EnumerateInstanceLayerProperties(&layerCount, nil)
	availableLayers = make([]vk.LayerProperties, layerCount)
	vk.EnumerateInstanceLayerProperties(&layerCount, availableLayers)
	fmt.Println("LayerCount: ", layerCount, "/", len(availableLayers))
	for i := 0; i < int(layerCount); i++ {
		availableLayers[i].Deref()
		availableLayers[i].Free()
		fmt.Println("LayerGo: ", strings.Replace(string(availableLayers[i].LayerName[:]), "\x00", "", -1))

	}
}

func createSurface(vkInstance *vk.Instance) uintptr {
	fmt.Println(vkInstance)
	surface, err := go_window.CreateWindowSurface(vkInstance, nil)
	if err != nil {
		fmt.Println("Cannot create surface: ", err)
		panic(err)
	}
	return surface
}

func initVulkan() {
	vkInstance := createVkInstance()
	checkPropertiesAndLayers()
	createSurface(vkInstance)
}


func mainLoop() {
	for !go_window.ShouldClose() {
		glfw.PollEvents()
	}
}

func main() {
	defer cleanup()
	initWindow()
	initVulkan()
	mainLoop()
}

What baffels me about this error is, that I am querying all the extension properties. And VK_KHR_win32_surface which is reported missing by the error is listed as available.
The following extensions are listed as available for my card by the above program:

Property: VK_KHR_device_group_creation
Property: VK_KHR_external_fence_capabilities
Property: VK_KHR_external_memory_capabilities
Property: VK_KHR_external_semaphore_capabilities
Property: VK_KHR_get_physical_device_properties2
Property: VK_KHR_get_surface_capabilities2
Property: VK_KHR_surface
Property: VK_KHR_surface_protected_capabilities
Property: VK_KHR_win32_surface
Property: VK_EXT_debug_report
Property: VK_EXT_debug_utils
Property: VK_EXT_swapchain_colorspace
Property: VK_NV_external_memory_capabilities

@Matthias-Schwarz did u manage to fix the problem?
Try to pass a de-referenced vkInstance. Worked for me.

So instead of surface, err := go_window.CreateWindowSurface(vkInstance, nil)
Try doing surface, err := go_window.CreateWindowSurface(*vkInstance, nil)

This is because the first parameter to CreateWindowSurface is an interface{} which cannot distinguish between the two.

@einthusan Just went back to this - yes that fixes the issue.
I guess I was thrown off by the error message which made me suspect a deeper issue.
Thank you for your reply.