-
Notifications
You must be signed in to change notification settings - Fork 294
Expand file tree
/
Copy pathDevice.java
More file actions
153 lines (120 loc) · 5.8 KB
/
Device.java
File metadata and controls
153 lines (120 loc) · 5.8 KB
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
142
143
144
145
146
147
148
149
150
151
152
153
package net.vulkanmod.vulkan.device;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.vulkan.*;
import java.nio.IntBuffer;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import static org.lwjgl.glfw.GLFW.GLFW_PLATFORM_WIN32;
import static org.lwjgl.glfw.GLFW.glfwGetPlatform;
import static org.lwjgl.vulkan.VK10.*;
import static org.lwjgl.vulkan.VK11.vkEnumerateInstanceVersion;
import static org.lwjgl.vulkan.VK11.vkGetPhysicalDeviceFeatures2;
public class Device {
final VkPhysicalDevice physicalDevice;
final VkPhysicalDeviceProperties properties;
private final int vendorId;
public final String vendorIdString;
public final String deviceName;
public final String driverVersion;
public final String vkVersion;
public final VkPhysicalDeviceFeatures2 availableFeatures;
public final VkPhysicalDeviceVulkan11Features availableFeatures11;
public final List<String> supportedExtensions;
public final boolean drawIndirectSupported;
public Device(VkPhysicalDevice device) {
this.physicalDevice = device;
this.properties = VkPhysicalDeviceProperties.malloc();
vkGetPhysicalDeviceProperties(physicalDevice, properties);
this.vendorId = properties.vendorID();
this.vendorIdString = decodeVendor(properties.vendorID());
this.deviceName = properties.deviceNameString();
this.driverVersion = decodeDvrVersion(properties.driverVersion(), properties.vendorID());
this.vkVersion = decDefVersion(getVkVer());
this.availableFeatures = VkPhysicalDeviceFeatures2.calloc();
this.availableFeatures.sType$Default();
this.availableFeatures11 = VkPhysicalDeviceVulkan11Features.malloc();
this.availableFeatures11.sType$Default();
this.availableFeatures.pNext(this.availableFeatures11);
vkGetPhysicalDeviceFeatures2(this.physicalDevice, this.availableFeatures);
this.drawIndirectSupported = this.availableFeatures.features().multiDrawIndirect();
this.supportedExtensions = getAvailableExtension(device);
}
public List<String> getSupportedExtensions() {
return supportedExtensions;
}
public Set<String> getUnsupportedExtensions(Set<String> requiredExtensions) {
Set<String> unsupportedExtensions = new HashSet<>(requiredExtensions);
supportedExtensions.forEach(unsupportedExtensions::remove);
return unsupportedExtensions;
}
public boolean isDrawIndirectSupported() {
return drawIndirectSupported;
}
// Added these to allow detecting GPU vendor, to allow handling vendor specific circumstances:
// (e.g. such as in case we encounter a vendor specific driver bug)
public boolean isAMD() {
return vendorId == 0x1022;
}
public boolean isNvidia() {
return vendorId == 0x10DE;
}
public boolean isIntel() {
return vendorId == 0x8086;
}
private static String decodeVendor(int i) {
return switch (i) {
case (0x10DE) -> "Nvidia";
case (0x1022) -> "AMD";
case (0x8086) -> "Intel";
default -> "undef"; //Either AMD or Unknown Driver version/vendor and.or Encoding Scheme
};
}
// Should Work with AMD: https://gpuopen.com/learn/decoding-radeon-vulkan-versions/
static String decDefVersion(int v) {
return VK_VERSION_MAJOR(v) + "." + VK_VERSION_MINOR(v) + "." + VK_VERSION_PATCH(v);
}
// 0x10DE = Nvidia: https://pcisig.com/membership/member-companies?combine=Nvidia
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkPhysicalDeviceProperties.html
// this should work with Nvidia + AMD but is not guaranteed to work with intel drivers in Windows and more obscure/Exotic Drivers/vendors
private static String decodeDvrVersion(int v, int i) {
return switch (i) {
case (0x10DE) -> decodeNvidia(v); //Nvidia
case (0x1022) -> decDefVersion(v); //AMD
case (0x8086) -> decIntelVersion(v); //Intel
default -> decDefVersion(v); //Either AMD or Unknown Driver Encoding Scheme
};
}
// Source: https://www.intel.com/content/www/us/en/support/articles/000005654/graphics.html
// Won't Work with older Drivers (15.45 And.or older)
// May not work as this uses Guess work+Assumptions
private static String decIntelVersion(int v) {
return (glfwGetPlatform() == GLFW_PLATFORM_WIN32) ? (v >>> 14) + "." + (v & 0x3fff) : decDefVersion(v);
}
private static String decodeNvidia(int v) {
return (v >>> 22 & 0x3FF) + "." + (v >>> 14 & 0xff) + "." + (v >>> 6 & 0xff) + "." + (v & 0xff);
}
private static int getVkVer() {
try (MemoryStack stack = MemoryStack.stackPush()) {
var a = stack.mallocInt(1);
vkEnumerateInstanceVersion(a);
int vkVer1 = a.get(0);
if (VK_VERSION_MINOR(vkVer1) < 2) {
throw new RuntimeException("Vulkan 1.2 not supported: Only Has: %s".formatted(decDefVersion(vkVer1)));
}
return vkVer1;
}
}
private static List<String> getAvailableExtension(VkPhysicalDevice device) {
try (MemoryStack stack = MemoryStack.stackPush()) {
// Query first for extension count
IntBuffer extensionCount = stack.ints(0);
vkEnumerateDeviceExtensionProperties(device, (String) null, extensionCount, null);
VkExtensionProperties.Buffer availableExtensions = VkExtensionProperties.malloc(extensionCount.get(0), stack);
vkEnumerateDeviceExtensionProperties(device, (String) null, extensionCount, availableExtensions);
return availableExtensions.stream()
.map(VkExtensionProperties::extensionNameString)
.toList();
}
}
}