1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
#!/usr/bin/env python3
# vk_probe2.py - Vulkan probe stage 2: create a logical device + queue on the
# NVIDIA physical device. Prints the queue-family table and the create
# result. ctypes only, no dev headers.
import ctypes
import sys
VK_SUCCESS = 0
VK_STRUCTURE_TYPE_APPLICATION_INFO = 0
VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO = 1
VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO = 2
VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO = 3
VK_API_VERSION_1_2 = (1 << 22) | (2 << 12)
vulkan = ctypes.CDLL("libvulkan.so.1")
class VkApplicationInfo(ctypes.Structure):
_fields_ = [
("sType", ctypes.c_int),
("pNext", ctypes.c_void_p),
("pApplicationName", ctypes.c_char_p),
("applicationVersion", ctypes.c_uint32),
("pEngineName", ctypes.c_char_p),
("engineVersion", ctypes.c_uint32),
("apiVersion", ctypes.c_uint32),
]
class VkInstanceCreateInfo(ctypes.Structure):
_fields_ = [
("sType", ctypes.c_int),
("pNext", ctypes.c_void_p),
("flags", ctypes.c_uint32),
("pApplicationInfo", ctypes.POINTER(VkApplicationInfo)),
("enabledLayerCount", ctypes.c_uint32),
("ppEnabledLayerNames", ctypes.c_void_p),
("enabledExtensionCount", ctypes.c_uint32),
("ppEnabledExtensionNames", ctypes.c_void_p),
]
class VkQueueFamilyProperties(ctypes.Structure):
_fields_ = [
("queueFlags", ctypes.c_uint32),
("queueCount", ctypes.c_uint32),
("timestampValidBits", ctypes.c_uint32),
("minImageTransferGranularity", ctypes.c_uint8 * 12),
]
class VkDeviceQueueCreateInfo(ctypes.Structure):
_fields_ = [
("sType", ctypes.c_int),
("pNext", ctypes.c_void_p),
("flags", ctypes.c_uint32),
("queueFamilyIndex", ctypes.c_uint32),
("queueCount", ctypes.c_uint32),
("pQueuePriorities", ctypes.POINTER(ctypes.c_float)),
]
class VkDeviceCreateInfo(ctypes.Structure):
_fields_ = [
("sType", ctypes.c_int),
("pNext", ctypes.c_void_p),
("flags", ctypes.c_uint32),
("queueCreateInfoCount", ctypes.c_uint32),
("pQueueCreateInfos", ctypes.POINTER(VkDeviceQueueCreateInfo)),
("enabledLayerCount", ctypes.c_uint32),
("ppEnabledLayerNames", ctypes.c_void_p),
("enabledExtensionCount", ctypes.c_uint32),
("ppEnabledExtensionNames", ctypes.c_void_p),
("pEnabledFeatures", ctypes.c_void_p),
]
app = VkApplicationInfo(VK_STRUCTURE_TYPE_APPLICATION_INFO, None, b"vk_probe2",
1, b"vk_probe2", 1, VK_API_VERSION_1_2)
ci = VkInstanceCreateInfo(VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, None, 0,
ctypes.pointer(app), 0, None, 0, None)
inst = ctypes.c_void_p()
r = vulkan.vkCreateInstance(ctypes.byref(ci), None, ctypes.byref(inst))
print("INSTANCE rc=%d" % r)
if r != 0:
sys.exit(1)
n = ctypes.c_uint32(0)
vulkan.vkEnumeratePhysicalDevices(inst, ctypes.byref(n), None)
devs = (ctypes.c_void_p * n.value)()
vulkan.vkEnumeratePhysicalDevices(inst, ctypes.byref(n), devs)
# pick the NVIDIA device by name
best = None
for i in range(n.value):
buf = ctypes.create_string_buffer(4096)
vulkan.vkGetPhysicalDeviceProperties(devs[i], buf)
raw = buf.raw
name = raw[20:276].split(b"\x00")[0].decode("utf-8", "replace")
print("PROPS dev=%d head=%s name=%r" % (i, raw[:40].hex(), name))
if "NVIDIA" in name or "llvmpipe" in name:
if "NVIDIA" in name:
best = devs[i]
print("PICK NVIDIA dev=%d name=%s" % (i, name))
break
if best is None:
print("NO_NVIDIA")
sys.exit(2)
nfam = ctypes.c_uint32(0)
vulkan.vkGetPhysicalDeviceQueueFamilyProperties(best, ctypes.byref(nfam),
None)
fams = (VkQueueFamilyProperties * nfam.value)()
vulkan.vkGetPhysicalDeviceQueueFamilyProperties(best, ctypes.byref(nfam),
fams)
gfam = None
for j in range(nfam.value):
print("QFAM %d flags=0x%x count=%d" % (j, fams[j].queueFlags,
fams[j].queueCount))
if (fams[j].queueFlags & 0x1) and fams[j].queueCount > 0 and gfam is None:
gfam = j
if gfam is None:
print("NO_GRAPHICS_QUEUE")
sys.exit(3)
prio = ctypes.c_float(1.0)
qci = VkDeviceQueueCreateInfo(VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
None, 0, gfam, 1, ctypes.pointer(prio))
dci = VkDeviceCreateInfo(VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, None, 0, 1,
ctypes.pointer(qci), 0, None, 0, None, None)
dev = ctypes.c_void_p()
r = vulkan.vkCreateDevice(best, ctypes.byref(dci), None, ctypes.byref(dev))
print("vkCreateDevice rc=%d (0x%x)" % (r, r if r < 0 else 0))
if r != 0:
sys.exit(4)
queue = ctypes.c_void_p()
vulkan.vkGetDeviceQueue(dev, gfam, 0, ctypes.byref(queue))
print("QUEUE device=%s queue=%s" % (bool(dev), bool(queue)))
# optional: wait-idle (exercises the queue)
vulkan.vkDeviceWaitIdle(dev)
print("VK2_DEVICE_OK")
sys.exit(0)
|