Skip to content

Commit e99472b

Browse files
committed
Reimplement feature and extension enablement
1 parent 68b2e22 commit e99472b

6 files changed

Lines changed: 324 additions & 208 deletions

File tree

src/main/java/git/artdeell/artvk/Vk11Backend.java

Lines changed: 13 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,8 @@
1010
import git.artdeell.ArtVK;
1111
import it.unimi.dsi.fastutil.ints.Int2IntMap;
1212
import it.unimi.dsi.fastutil.ints.Int2IntMap.Entry;
13-
import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
13+
1414
import java.nio.IntBuffer;
15-
import java.util.Collection;
16-
import java.util.HashSet;
17-
import java.util.List;
1815
import java.util.Locale;
1916
import java.util.Set;
2017
import net.fabricmc.api.EnvType;
@@ -25,9 +22,6 @@
2522
import org.lwjgl.glfw.GLFW;
2623
import org.lwjgl.glfw.GLFWVulkan;
2724
import org.lwjgl.system.MemoryStack;
28-
import org.lwjgl.util.vma.Vma;
29-
import org.lwjgl.util.vma.VmaAllocatorCreateInfo;
30-
import org.lwjgl.util.vma.VmaVulkanFunctions;
3125
import org.lwjgl.vulkan.*;
3226
import org.lwjgl.vulkan.VkDeviceQueueCreateInfo.Buffer;
3327

@@ -70,41 +64,18 @@ public void handleWindowCreationErrors(final GLFWErrorCapture.@Nullable Error er
7064
if (!GLFWVulkan.glfwVulkanSupported()) {
7165
throw new BackendCreationException("Vulkan is not supported", BackendCreationException.Reason.GLFW_ERROR);
7266
}
73-
74-
Set<String> deviceExtensions = new HashSet<>(REQUIRED_DEVICE_EXTENSIONS);
7567
Vk11Instance instance = null;
7668
Vk11PhysicalDevice physicalDevice = null;
7769
VkDevice device = null;
7870
IntVMA vma = null;
7971

8072
try {
8173
boolean renderdocAttached = "1".equals(System.getenv("ENABLE_VULKAN_RENDERDOC_CAPTURE"));
82-
boolean validation = "true".equalsIgnoreCase(System.getProperty("dogshitvk.validation", "false"));
74+
boolean validation = "true".equalsIgnoreCase(System.getProperty("artvk.validation", "false"));
8375
boolean useDebugLabels = debugOptions.useLabels() || renderdocAttached;
8476
instance = new Vk11Instance(debugOptions.logLevel(), useDebugLabels, validation);
8577
physicalDevice = findPhysicalDevice(instance);
86-
87-
if (physicalDevice.hasDeviceExtension("VK_KHR_portability_subset")) {
88-
deviceExtensions.add("VK_KHR_portability_subset");
89-
}
90-
91-
if(useDebugLabels) {
92-
if (physicalDevice.hasDeviceExtension("VK_AMD_buffer_marker")) {
93-
deviceExtensions.add("VK_AMD_buffer_marker");
94-
} else if (physicalDevice.hasDeviceExtension("VK_NV_device_diagnostic_checkpoints")) {
95-
deviceExtensions.add("VK_NV_device_diagnostic_checkpoints");
96-
}
97-
}
98-
99-
if (physicalDevice.hasDeviceExtension("VK_EXT_multi_draw")) {
100-
deviceExtensions.add("VK_EXT_multi_draw");
101-
}
102-
103-
if(physicalDevice.hasDeviceExtension("VK_EXT_vertex_attribute_divisor")) {
104-
deviceExtensions.add("VK_EXT_vertex_attribute_divisor");
105-
}
106-
107-
device = createVkDevice(deviceExtensions, physicalDevice);
78+
device = createVkDevice(physicalDevice);
10879
vma = new IntVMA(device);
10980
} catch (BackendCreationException e) {
11081
if(vma != null) vma.close();
@@ -119,7 +90,7 @@ public void handleWindowCreationErrors(final GLFWErrorCapture.@Nullable Error er
11990
}
12091

12192
return new GpuDevice(
122-
new Vk11Device(defaultShaderSource, instance, physicalDevice, deviceExtensions, device, vma), criticalShaderLoader
93+
new Vk11Device(defaultShaderSource, instance, physicalDevice, device, vma), criticalShaderLoader
12394
);
12495
}
12596

@@ -156,7 +127,7 @@ private static Vk11PhysicalDevice findPhysicalDevice(final Vk11Instance instance
156127
firstDevice = currentDevice;
157128
}
158129

159-
if (deviceMeetsFeatureQueryRequirements(currentDevice) && isDeviceSuitable(currentDevice)) {
130+
if (isDeviceSuitable(currentDevice)) {
160131
if (selectedDevice == null) {
161132
selectedDevice = currentDevice;
162133
} else if (isDeviceDiscrete(currentDevice) && !isDeviceDiscrete(selectedDevice)) {
@@ -174,32 +145,19 @@ private static Vk11PhysicalDevice findPhysicalDevice(final Vk11Instance instance
174145
}
175146

176147
if (selectedDevice == null) {
177-
throwForMissingRequirements(firstDevice);
178-
assert false;
148+
throw new BackendCreationException("No compatible devices found", BackendCreationException.Reason.VULKAN_NO_DEVICE);
179149
}
180150

181-
return new Vk11PhysicalDevice(selectedDevice);
182-
}
183-
184-
private static boolean deviceMeetsFeatureQueryRequirements(final VkPhysicalDevice vkPhysicalDevice) {
185-
try (MemoryStack stack = MemoryStack.stackPush()) {
186-
VkPhysicalDeviceProperties properties = VkPhysicalDeviceProperties.calloc(stack);
187-
VK10.vkGetPhysicalDeviceProperties(vkPhysicalDevice, properties);
188-
return properties.apiVersion() >= VK11.VK_API_VERSION_1_1;
189-
}
151+
return new Vk11PhysicalDevice(selectedDevice, instance.propertiesMode);
190152
}
191153

192154
private static boolean isDeviceSuitable(final VkPhysicalDevice vkPhysicalDevice) throws BackendCreationException {
193155
try (
194-
Vk11PhysicalDevice physicalDevice = new Vk11PhysicalDevice(vkPhysicalDevice);
156+
Vk11PhysicalDevice physicalDevice = new Vk11PhysicalDevice(vkPhysicalDevice, Vk11PhysicalDevice.PROPERTIES_VK11);
195157
) {
196-
String deviceName = physicalDevice.deviceName();
158+
String deviceName = physicalDevice.properties().deviceName();
197159
Set<String> missingExtensions = physicalDevice.getMissingExtensions(REQUIRED_DEVICE_EXTENSIONS);
198160
boolean isSuitableDevice = true;
199-
if (physicalDevice.vkPhysicalDeviceProperties().apiVersion() < VK11.VK_API_VERSION_1_1) {
200-
ArtVK.LOGGER.warn("Device [{}] does not support Vulkan 1.1", deviceName);
201-
isSuitableDevice = false;
202-
}
203161

204162
if (physicalDevice.graphicsQueueFamilyAndIndex() == null) {
205163
ArtVK.LOGGER.warn("Device [{}] does not have a graphics queue", deviceName);
@@ -235,61 +193,8 @@ private static String getDeviceName(final VkPhysicalDevice vkPhysicalDevice) {
235193
}
236194
}
237195

238-
private static void throwForMissingRequirements(final VkPhysicalDevice vkPhysicalDevice) throws BackendCreationException {
239-
List<String> missingCapabilities = new ReferenceArrayList<>();
240-
BackendCreationException.Reason mostProminentReason = BackendCreationException.Reason.OTHER;
241-
if (!deviceMeetsFeatureQueryRequirements(vkPhysicalDevice)) {
242-
throw new BackendCreationException("Device missing capabilities", BackendCreationException.Reason.VULKAN_DEVICE_VERSION_TOO_LOW, List.of("VULKAN_CORE_1_1"));
243-
}
244-
245-
try (
246-
Vk11PhysicalDevice physicalDevice = new Vk11PhysicalDevice(vkPhysicalDevice);
247-
MemoryStack stack = MemoryStack.stackPush();
248-
) {
249-
VkPhysicalDeviceFeatures2 deviceFeatures = VkPhysicalDeviceFeatures2.calloc(stack).sType$Default();
250-
VK11.vkGetPhysicalDeviceFeatures2(vkPhysicalDevice, deviceFeatures);
251-
252-
Set<String> missingExtensions = physicalDevice.getMissingExtensions(REQUIRED_DEVICE_EXTENSIONS);
253-
if (!missingExtensions.isEmpty()) {
254-
mostProminentReason = BackendCreationException.Reason.VULKAN_MISSING_EXTENSION;
255-
missingCapabilities.addAll(missingExtensions);
256-
}
257-
258-
if (physicalDevice.graphicsQueueFamilyAndIndex() == null) {
259-
mostProminentReason = BackendCreationException.Reason.VULKAN_NO_GRAPHICS_QUEUE;
260-
missingCapabilities.add("COMBINED_GRAPHICS_COMPUTE_PRESENT_QUEUE");
261-
}
262-
263-
if (physicalDevice.vkPhysicalDeviceProperties().apiVersion() < VK11.VK_API_VERSION_1_1) {
264-
mostProminentReason = BackendCreationException.Reason.VULKAN_DEVICE_VERSION_TOO_LOW;
265-
missingCapabilities.add("VULKAN_CORE_1_1");
266-
}
267-
}
268-
269-
throw new BackendCreationException("Device missing capabilities", mostProminentReason, missingCapabilities);
270-
}
271-
272-
private static VkDevice createVkDevice(
273-
final Collection<String> deviceExtensions, final Vk11PhysicalDevice physicalDevice
274-
) throws BackendCreationException {
196+
private static VkDevice createVkDevice(final Vk11PhysicalDevice physicalDevice) throws BackendCreationException {
275197
try (MemoryStack stack = MemoryStack.stackPush()) {
276-
VkPhysicalDeviceFeatures2 availableFeatures = physicalDevice.vkPhysicalDeviceFeatures();
277-
278-
VkPhysicalDeviceFeatures2 deviceFeatures = VkPhysicalDeviceFeatures2.calloc(stack).sType$Default();
279-
// Enable required VK10 features
280-
deviceFeatures.features().multiDrawIndirect(availableFeatures.features().multiDrawIndirect());
281-
deviceFeatures.features().fillModeNonSolid(availableFeatures.features().fillModeNonSolid());
282-
deviceFeatures.features().samplerAnisotropy(availableFeatures.features().samplerAnisotropy());
283-
284-
// Enable VK10 shaderDrawParameters via pNext chain
285-
VkPhysicalDeviceVulkan11Features vk11Features = VkPhysicalDeviceVulkan11Features.calloc(stack).sType$Default();
286-
vk11Features.shaderDrawParameters(true);
287-
deviceFeatures.pNext(vk11Features.address());
288-
289-
// Enable VK10 vertexAttributeDivisor via pNext chain (EXT extension)
290-
VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertexDivisorFeatures = VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT.calloc(stack).sType$Default();
291-
vertexDivisorFeatures.vertexAttributeInstanceRateDivisor(true);
292-
vk11Features.pNext(vertexDivisorFeatures.address());
293198

294199
Int2IntMap queuesToCreate = physicalDevice.queueFamilyCreateInfoMap();
295200
Buffer queueCreationInfo = VkDeviceQueueCreateInfo.calloc(queuesToCreate.size(), stack);
@@ -302,17 +207,12 @@ private static VkDevice createVkDevice(
302207
}
303208

304209
queueCreationInfo.position(0);
305-
PointerBuffer enabledExtensionsBuffer = stack.callocPointer(deviceExtensions.size());
306210

307-
for (String name : deviceExtensions) {
308-
enabledExtensionsBuffer.put(stack.UTF8(name));
309-
}
310-
311-
enabledExtensionsBuffer.flip();
312211
VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.calloc(stack).sType$Default();
313-
deviceCreateInfo.pNext(deviceFeatures.address());
314212
deviceCreateInfo.pQueueCreateInfos(queueCreationInfo);
315-
deviceCreateInfo.ppEnabledExtensionNames(enabledExtensionsBuffer);
213+
214+
physicalDevice.features().addFeaturesAndExtensions(stack, physicalDevice, deviceCreateInfo);
215+
316216
PointerBuffer pointer = stack.callocPointer(1);
317217
Vk11Utils.throwIfFailure(
318218
VK10.vkCreateDevice(physicalDevice.vkPhysicalDevice(), deviceCreateInfo, null, pointer),

src/main/java/git/artdeell/artvk/Vk11Device.java

Lines changed: 17 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public class Vk11Device implements GpuDeviceBackend {
5555
private final Vk11Queue computeQueue;
5656
private final Vk11Queue transferQueue;
5757
private final boolean isIntegratedIntelMoltenVK;
58-
public final boolean hasFillModeNonSolid, hasAnisotropy, hasAttributeDivisor;
58+
public final Vk11PhysicalDevice.Features features;
5959
private final Vk11CommandEncoder commandEncoder;
6060
private final Vk11RenderPassCache renderPassCache;
6161
private final Vk11FramebufferCache framebufferCache;
@@ -64,8 +64,7 @@ public Vk11Device(
6464
final ShaderSource defaultShaderSource,
6565
final Vk11Instance instance,
6666
final Vk11PhysicalDevice physicalDevice,
67-
final Set<String> enabledDeviceExtensions,
68-
final VkDevice vkDevice,
67+
final VkDevice vkDevice,
6968
final IntVMA vma
7069
) {
7170
this.defaultShaderSource = defaultShaderSource;
@@ -75,40 +74,27 @@ public Vk11Device(
7574
this.vma = vmaObj.ptr;
7675
Set<String> extensionNames = new HashSet<>();
7776

78-
for (String name : instance.getEnabledExtensions()) {
79-
extensionNames.add(name + " (I)");
80-
}
81-
82-
for (String name : enabledDeviceExtensions) {
83-
extensionNames.add(name + " (D)");
84-
}
85-
86-
VkPhysicalDeviceLimits limits = physicalDevice.vkPhysicalDeviceProperties().limits();
87-
VkPhysicalDeviceVulkan11Properties vk11Properties = physicalDevice.vkPhysicalDeviceVulkan11Properties();
88-
VkPhysicalDeviceFeatures features = physicalDevice.vkPhysicalDeviceFeatures().features();
89-
90-
hasFillModeNonSolid = features.fillModeNonSolid();
91-
hasAnisotropy = features.samplerAnisotropy();
92-
hasAttributeDivisor = enabledDeviceExtensions.contains("VK_EXT_vertex_attribute_divisor");
77+
Vk11PhysicalDevice.Properties properties = physicalDevice.properties();
78+
features = physicalDevice.features();
9379

94-
if(!hasFillModeNonSolid) ArtVK.LOGGER.warn("Device does not support fillModeNonSolid, wireframe rendering won't work");
80+
if(!features.fillModeNonSolid()) ArtVK.LOGGER.warn("Device does not support fillModeNonSolid, wireframe rendering won't work");
9581

9682
this.deviceInfo = new DeviceInfo(
97-
physicalDevice.deviceName(),
83+
properties.deviceName(),
9884
physicalDevice.vendorName(),
99-
physicalDevice.driverInfo(),
85+
properties.driverInfo(),
10086
true,
10187
"ArtVK",
102-
limits.timestampPeriod(),
88+
properties.timestampPeriod(),
10389
new DeviceLimits(
104-
hasAnisotropy ? (int)limits.maxSamplerAnisotropy() : 1,
105-
(int)limits.minUniformBufferOffsetAlignment(),
106-
limits.maxImageDimension2D(),
107-
vk11Properties.maxMemoryAllocationSize() <= 0L ? Long.MAX_VALUE : vk11Properties.maxMemoryAllocationSize(),
90+
features.samplerAnisotropy() ? properties.maxSamplerAnisotropy() : 1,
91+
properties.minUniformBufferOffsetAlignment(),
92+
properties.maxImageDimension2D(),
93+
properties.maxMemoryAllocationSize(),
10894
Integer.MAX_VALUE,
109-
limits.maxColorAttachments()
95+
properties.maxColorAttachments()
11096
),
111-
new DeviceFeatures(true, enabledDeviceExtensions.contains("VK_EXT_multi_draw"), false, features.multiDrawIndirect(), true, true, true),
97+
new DeviceFeatures(true, features.multiDraw(), false, features.multiDrawIndirect(), true, true, true),
11298
Collections.unmodifiableSet(extensionNames),
11399
new HintsAndWorkarounds(false, false),
114100
physicalDevice.deviceType()
@@ -131,9 +117,9 @@ public Vk11Device(
131117
this.transferQueue = this.computeQueue;
132118
}
133119

134-
this.isIntegratedIntelMoltenVK = physicalDevice.vkPhysicalDeviceProperties().deviceType() == VK10.VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
135-
&& physicalDevice.vkPhysicalDeviceProperties().vendorID() == 32902
136-
&& physicalDevice.vkPhysicalDeviceDriverProperties().driverID() == 14;
120+
this.isIntegratedIntelMoltenVK = properties.deviceType() == VK10.VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
121+
&& properties.vendorId() == 0x8086
122+
&& properties.driverId() == 14;
137123
physicalDevice.close();
138124
this.renderPassCache = new Vk11RenderPassCache(this);
139125
this.framebufferCache = new Vk11FramebufferCache(this);

src/main/java/git/artdeell/artvk/Vk11GpuSampler.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public Vk11GpuSampler(
3333
final int maxAnisotropy,
3434
final OptionalDouble maxLod
3535
) {
36-
boolean anisotropyEnable = maxAnisotropy > 1 && device.hasAnisotropy;
36+
boolean anisotropyEnable = maxAnisotropy > 1 && device.features.samplerAnisotropy();
3737

3838
this.device = device;
3939
this.addressModeU = addressModeU;

src/main/java/git/artdeell/artvk/Vk11Instance.java

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,19 +26,20 @@ public class Vk11Instance implements AutoCloseable {
2626
private static final int APPLICATION_VERSION = SharedConstants.getCurrentVersion().dataVersion().version();
2727
private static final String ENGINE_NAME = "MinecraftJE-ArtVK";
2828
private static final int ENGINE_VERSION = 0;
29-
private final Set<String> enabledExtensions = new HashSet<>();
30-
private final VkInstance vkInstance;
29+
private final VkInstance vkInstance;
3130
private final Vk11Debug debug;
31+
public final byte propertiesMode;
3232

3333
protected Vk11Instance(final int debugVerbosity, boolean wantsDebugLabels, final boolean validation) throws BackendCreationException {
3434
try (MemoryStack stack = MemoryStack.stackPush()) {
35+
boolean vk10 = isVk10Impl();
3536
VkApplicationInfo appInfo = VkApplicationInfo.calloc(stack)
3637
.sType$Default()
3738
.pApplicationName(stack.UTF8(APPLICATION_NAME))
3839
.applicationVersion(APPLICATION_VERSION)
3940
.pEngineName(stack.UTF8(ENGINE_NAME))
4041
.engineVersion(ENGINE_VERSION)
41-
.apiVersion(VK11.VK_API_VERSION_1_1);
42+
.apiVersion(vk10 ? VK10.VK_API_VERSION_1_0 : VK12.VK_API_VERSION_1_2);
4243
List<String> validationLayers = this.getSupportedValidationLayers();
4344
PointerBuffer requiredLayers = null;
4445
if (validation) {
@@ -58,23 +59,39 @@ protected Vk11Instance(final int debugVerbosity, boolean wantsDebugLabels, final
5859
throw new BackendCreationException("Failed to find the GLFW platform surface extensions", BackendCreationException.Reason.GLFW_ERROR);
5960
}
6061

61-
while (glfwExtensions.remaining() > 0) {
62-
this.enabledExtensions.add(MemoryUtil.memUTF8(glfwExtensions.get()));
62+
Set<String> enabledExtensions = new HashSet<>();
63+
while (glfwExtensions.remaining() > 0) {
64+
enabledExtensions.add(MemoryUtil.memUTF8(glfwExtensions.get()));
6365
}
6466

65-
this.debug = Vk11Debug.create(debugVerbosity, wantsDebugLabels, availableExtensions, this.enabledExtensions);
66-
boolean usePortability = availableExtensions.contains("VK_KHR_portability_enumeration") && Util.getPlatform() == Util.OS.OSX;
67+
this.debug = Vk11Debug.create(debugVerbosity, wantsDebugLabels, availableExtensions, enabledExtensions);
68+
boolean usePortability = availableExtensions.contains(KHRPortabilityEnumeration.VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME) && Util.getPlatform() == Util.OS.OSX;
69+
6770
if (usePortability) {
68-
this.enabledExtensions.add("VK_KHR_portability_enumeration");
71+
enabledExtensions.add(KHRPortabilityEnumeration.VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
6972
}
7073

71-
PointerBuffer enabledExtensionsBuffer = stack.callocPointer(this.enabledExtensions.size());
7274

73-
for (String name : this.enabledExtensions) {
75+
if(availableExtensions.contains(KHRGetPhysicalDeviceProperties2.VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
76+
propertiesMode = Vk11PhysicalDevice.PROPERTIES_KHR;
77+
enabledExtensions.add(KHRGetPhysicalDeviceProperties2.VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
78+
}else if(!vk10) {
79+
propertiesMode = Vk11PhysicalDevice.PROPERTIES_VK11;
80+
} else {
81+
propertiesMode = Vk11PhysicalDevice.PROPERTIES_VK10;
82+
}
83+
84+
PointerBuffer enabledExtensionsBuffer = stack.callocPointer(enabledExtensions.size());
85+
86+
StringBuilder logExtensions = new StringBuilder()
87+
.append("Enabled instance extensions:");
88+
for (String name : enabledExtensions) {
89+
logExtensions.append(' ').append(name);
7490
enabledExtensionsBuffer.put(stack.UTF8(name));
7591
}
92+
ArtVK.LOGGER.info(logExtensions.toString());
93+
enabledExtensionsBuffer.flip();
7694

77-
enabledExtensionsBuffer.flip();
7895
VkInstanceCreateInfo instanceInfo = VkInstanceCreateInfo.calloc(stack)
7996
.sType$Default()
8097
.pApplicationInfo(appInfo)
@@ -103,6 +120,11 @@ protected Vk11Instance(final int debugVerbosity, boolean wantsDebugLabels, final
103120
}
104121
}
105122

123+
private boolean isVk10Impl() {
124+
long addr = VK10.vkGetInstanceProcAddr(null, "vkEnumerateInstanceVersion");
125+
return addr == 0L;
126+
}
127+
106128
public VkInstance vkInstance() {
107129
return this.vkInstance;
108130
}
@@ -168,10 +190,6 @@ public void close() {
168190
VK10.vkDestroyInstance(this.vkInstance, null);
169191
}
170192

171-
public Set<String> getEnabledExtensions() {
172-
return this.enabledExtensions;
173-
}
174-
175193
public Vk11Debug debug() {
176194
return this.debug;
177195
}

0 commit comments

Comments
 (0)