VkInstance: Refactor Validation and Extensions selection
This commit is contained in:
parent
c09b04dc81
commit
9ecf98a26d
4 changed files with 315 additions and 167 deletions
|
@ -1,19 +1,17 @@
|
|||
package fr.mrdev023.vulkan_java.vk;
|
||||
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.glfw.GLFWVulkan;
|
||||
import org.lwjgl.system.*;
|
||||
import org.lwjgl.vulkan.*;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import fr.mrdev023.vulkan_java.vk.utils.InstanceValidationLayersSelector;
|
||||
import fr.mrdev023.vulkan_java.vk.utils.InstanceExtensions;
|
||||
import fr.mrdev023.vulkan_java.vk.utils.InstanceValidationLayers;
|
||||
|
||||
import java.nio.*;
|
||||
import java.util.*;
|
||||
|
||||
import static fr.mrdev023.vulkan_java.vk.VulkanError.vkCheck;
|
||||
import static org.lwjgl.vulkan.EXTDebugUtils.*;
|
||||
import static org.lwjgl.vulkan.KHRPortabilityEnumeration.VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
|
||||
import static org.lwjgl.vulkan.VK11.*;
|
||||
|
||||
public class Instance {
|
||||
|
@ -23,7 +21,6 @@ public class Instance {
|
|||
public static final int MESSAGE_TYPE_BITMASK = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||
private static final String PORTABILITY_EXTENSION = "VK_KHR_portability_enumeration";
|
||||
|
||||
private final VkInstance vkInstance;
|
||||
|
||||
|
@ -31,7 +28,6 @@ public class Instance {
|
|||
private long vkDebugHandle;
|
||||
|
||||
public Instance(boolean validate) throws VulkanError {
|
||||
Logger.debug("Creating Vulkan instance");
|
||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||
// Create application information
|
||||
ByteBuffer appShortName = stack.UTF8("VulkanBook");
|
||||
|
@ -43,52 +39,19 @@ public class Instance {
|
|||
.engineVersion(0)
|
||||
.apiVersion(VK_API_VERSION_1_1);
|
||||
|
||||
// Validation layers
|
||||
var validationLayers = new InstanceValidationLayersSelector()
|
||||
.withValidationLayers(validate)
|
||||
InstanceValidationLayers validationLayers = new InstanceValidationLayers.Selector()
|
||||
.includeValidationLayers(validate)
|
||||
.selectValidationLayers();
|
||||
|
||||
// Set required layers
|
||||
PointerBuffer requiredLayers = null;
|
||||
if (!validationLayers.isEmpty()) {
|
||||
requiredLayers = stack.mallocPointer(validationLayers.size());
|
||||
for (String layer : validationLayers) {
|
||||
requiredLayers.put(stack.ASCII(layer));
|
||||
}
|
||||
}
|
||||
InstanceExtensions instanceExtensions = new InstanceExtensions.Selector()
|
||||
.withValidationLayers(validationLayers)
|
||||
.selectInstanceExtensions();
|
||||
|
||||
Set<String> instanceExtensions = getInstanceExtensions();
|
||||
|
||||
// GLFW Extension
|
||||
PointerBuffer glfwExtensions = GLFWVulkan.glfwGetRequiredInstanceExtensions();
|
||||
if (glfwExtensions == null) {
|
||||
throw new RuntimeException("Failed to find the GLFW platform surface extensions");
|
||||
}
|
||||
|
||||
PointerBuffer requiredExtensions;
|
||||
|
||||
boolean usePortability = instanceExtensions.contains(PORTABILITY_EXTENSION) &&
|
||||
VulkanUtils.getOS() == VulkanUtils.OSType.MACOS;
|
||||
if (!validationLayers.isEmpty()) {
|
||||
ByteBuffer vkDebugUtilsExtension = stack.UTF8(EXTDebugUtils.VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
int numExtensions = usePortability ? glfwExtensions.remaining() + 2 : glfwExtensions.remaining() + 1;
|
||||
requiredExtensions = stack.mallocPointer(numExtensions);
|
||||
requiredExtensions.put(glfwExtensions).put(vkDebugUtilsExtension);
|
||||
if (usePortability) {
|
||||
requiredExtensions.put(stack.UTF8(PORTABILITY_EXTENSION));
|
||||
}
|
||||
} else {
|
||||
int numExtensions = usePortability ? glfwExtensions.remaining() + 1 : glfwExtensions.remaining();
|
||||
requiredExtensions = stack.mallocPointer(numExtensions);
|
||||
requiredExtensions.put(glfwExtensions);
|
||||
if (usePortability) {
|
||||
requiredExtensions.put(stack.UTF8(KHRPortabilitySubset.VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME));
|
||||
}
|
||||
}
|
||||
requiredExtensions.flip();
|
||||
PointerBuffer instanceExtensionsBuffer = instanceExtensions.writeToStack(stack);
|
||||
PointerBuffer validationLayersBuffer = validationLayers.writeToStack(stack);
|
||||
|
||||
long extension = MemoryUtil.NULL;
|
||||
if (!validationLayers.isEmpty()) {
|
||||
if (validationLayers.hasValidationLayers()) {
|
||||
debugUtils = createDebugCallBack();
|
||||
extension = debugUtils.address();
|
||||
}
|
||||
|
@ -98,24 +61,23 @@ public class Instance {
|
|||
.sType(VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO)
|
||||
.pNext(extension)
|
||||
.pApplicationInfo(appInfo)
|
||||
.ppEnabledLayerNames(requiredLayers)
|
||||
.ppEnabledExtensionNames(requiredExtensions);
|
||||
if (usePortability) {
|
||||
instanceInfo.flags(VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR);
|
||||
}
|
||||
.ppEnabledLayerNames(validationLayersBuffer)
|
||||
.ppEnabledExtensionNames(instanceExtensionsBuffer);
|
||||
instanceExtensions.writeInstanceCreateInfoFlags(instanceInfo);
|
||||
|
||||
PointerBuffer pInstance = stack.mallocPointer(1);
|
||||
vkCheck(vkCreateInstance(instanceInfo, null, pInstance), "Error creating instance");
|
||||
vkInstance = new VkInstance(pInstance.get(0), instanceInfo);
|
||||
|
||||
vkDebugHandle = VK_NULL_HANDLE;
|
||||
if (!validationLayers.isEmpty()) {
|
||||
if (validationLayers.hasValidationLayers()) {
|
||||
LongBuffer longBuff = stack.mallocLong(1);
|
||||
vkCheck(vkCreateDebugUtilsMessengerEXT(vkInstance, debugUtils, null, longBuff),
|
||||
"Error creating debug utils");
|
||||
vkDebugHandle = longBuff.get(0);
|
||||
}
|
||||
}
|
||||
Logger.debug("Vulkan instance created");
|
||||
}
|
||||
|
||||
private static VkDebugUtilsMessengerCreateInfoEXT createDebugCallBack() {
|
||||
|
@ -152,26 +114,6 @@ public class Instance {
|
|||
}
|
||||
}
|
||||
|
||||
private Set<String> getInstanceExtensions() {
|
||||
Set<String> instanceExtensions = new HashSet<>();
|
||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||
IntBuffer numExtensionsBuf = stack.callocInt(1);
|
||||
vkEnumerateInstanceExtensionProperties((String) null, numExtensionsBuf, null);
|
||||
int numExtensions = numExtensionsBuf.get(0);
|
||||
Logger.debug("Instance supports [{}] extensions", numExtensions);
|
||||
|
||||
VkExtensionProperties.Buffer instanceExtensionsProps = VkExtensionProperties.calloc(numExtensions, stack);
|
||||
vkEnumerateInstanceExtensionProperties((String) null, numExtensionsBuf, instanceExtensionsProps);
|
||||
for (int i = 0; i < numExtensions; i++) {
|
||||
VkExtensionProperties props = instanceExtensionsProps.get(i);
|
||||
String extensionName = props.extensionNameString();
|
||||
instanceExtensions.add(extensionName);
|
||||
Logger.debug("Supported instance extension [{}]", extensionName);
|
||||
}
|
||||
}
|
||||
return instanceExtensions;
|
||||
}
|
||||
|
||||
public VkInstance getVkInstance() {
|
||||
return vkInstance;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
package fr.mrdev023.vulkan_java.vk.utils;
|
||||
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.glfw.GLFWVulkan;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
import org.lwjgl.vulkan.EXTDebugUtils;
|
||||
import org.lwjgl.vulkan.KHRPortabilityEnumeration;
|
||||
import org.lwjgl.vulkan.VK10;
|
||||
import org.lwjgl.vulkan.VkExtensionProperties;
|
||||
import org.lwjgl.vulkan.VkInstanceCreateInfo;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
import fr.mrdev023.vulkan_java.vk.VulkanUtils;
|
||||
|
||||
/**
|
||||
* This class is used to store the instance extensions to use to create the Vulkan instance.
|
||||
*
|
||||
* @see InstanceExtensions.Selector to select the instance extensions
|
||||
*/
|
||||
public class InstanceExtensions {
|
||||
private Set<String> instanceExtensions;
|
||||
private PointerBuffer glfwRequiredExtensions;
|
||||
|
||||
private InstanceExtensions(Set<String> instanceExtensions, PointerBuffer glfwRequiredExtensions) {
|
||||
this.instanceExtensions = instanceExtensions;
|
||||
this.glfwRequiredExtensions = glfwRequiredExtensions;
|
||||
}
|
||||
|
||||
public boolean hasInstanceExtensions() {
|
||||
return !instanceExtensions.isEmpty();
|
||||
}
|
||||
|
||||
public Set<String> getInstanceExtensions() {
|
||||
return instanceExtensions;
|
||||
}
|
||||
|
||||
public PointerBuffer writeToStack(MemoryStack stack) {
|
||||
int numExtensions = instanceExtensions.size() + glfwRequiredExtensions.remaining();
|
||||
PointerBuffer requiredExtensions = stack.mallocPointer(numExtensions);
|
||||
|
||||
requiredExtensions.put(glfwRequiredExtensions);
|
||||
for (String extension : instanceExtensions) {
|
||||
requiredExtensions.put(stack.UTF8(extension));
|
||||
}
|
||||
requiredExtensions.flip();
|
||||
|
||||
return requiredExtensions;
|
||||
}
|
||||
|
||||
public void writeInstanceCreateInfoFlags(VkInstanceCreateInfo instanceInfo) {
|
||||
if (instanceExtensions.contains(KHRPortabilityEnumeration.VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) {
|
||||
instanceInfo.flags(KHRPortabilityEnumeration.VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used to automatically select the instance extensions
|
||||
*
|
||||
* <h5>Specification</h5>
|
||||
* <ul>
|
||||
* <li>Get the GLFW required extensions to create the Window Surface</li>
|
||||
* <li>Get the portability extensions if the OS needs it</li>
|
||||
* <li>Add Debug Utils extension if validation layers are enabled</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h5>See Also</h5>
|
||||
* <ul>
|
||||
* <li>{@link #selectInstanceExtensions()}</li>
|
||||
* <li>{@link #withValidationLayers(InstanceValidationLayers)}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static class Selector {
|
||||
private InstanceValidationLayers validationLayers;
|
||||
|
||||
public Selector withValidationLayers(InstanceValidationLayers validationLayers) {
|
||||
this.validationLayers = validationLayers;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the instance extensions.
|
||||
*
|
||||
* @return the set of instance extensions
|
||||
*/
|
||||
public InstanceExtensions selectInstanceExtensions() {
|
||||
Set<String> instanceExtensions = getInstanceExtensions();
|
||||
log("Supported instance extensions", instanceExtensions);
|
||||
|
||||
// GLFW Extension
|
||||
PointerBuffer glfwExtensions = GLFWVulkan.glfwGetRequiredInstanceExtensions();
|
||||
if (glfwExtensions == null) {
|
||||
throw new RuntimeException("Failed to find the GLFW platform surface extensions");
|
||||
}
|
||||
|
||||
Set<String> portabilityExtensions = getPortabilityExtensions(instanceExtensions);
|
||||
log("Portability extensions used", portabilityExtensions);
|
||||
|
||||
Set<String> selectedExtensions = new HashSet<>();
|
||||
selectedExtensions.addAll(portabilityExtensions);
|
||||
|
||||
if (validationLayers != null && validationLayers.hasValidationLayers()) {
|
||||
selectedExtensions.add(EXTDebugUtils.VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
}
|
||||
log("Selected instance extensions", selectedExtensions);
|
||||
|
||||
return new InstanceExtensions(selectedExtensions, glfwExtensions);
|
||||
}
|
||||
|
||||
private Set<String> getInstanceExtensions() {
|
||||
Set<String> instanceExtensions = new HashSet<>();
|
||||
|
||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||
IntBuffer numExtensionsBuf = stack.callocInt(1);
|
||||
VK10.vkEnumerateInstanceExtensionProperties((String) null, numExtensionsBuf, null);
|
||||
int numExtensions = numExtensionsBuf.get(0);
|
||||
|
||||
VkExtensionProperties.Buffer instanceExtensionsProps = VkExtensionProperties.calloc(numExtensions, stack);
|
||||
VK10.vkEnumerateInstanceExtensionProperties((String) null, numExtensionsBuf, instanceExtensionsProps);
|
||||
for (int i = 0; i < numExtensions; i++) {
|
||||
VkExtensionProperties props = instanceExtensionsProps.get(i);
|
||||
String extensionName = props.extensionNameString();
|
||||
instanceExtensions.add(extensionName);
|
||||
}
|
||||
}
|
||||
|
||||
return instanceExtensions;
|
||||
}
|
||||
|
||||
private Set<String> getPortabilityExtensions(Set<String> instanceExtensions) {
|
||||
Set<String> portabilityExtensions = new HashSet<>();
|
||||
|
||||
var osType = VulkanUtils.getOS();
|
||||
if (osType == VulkanUtils.OSType.MACOS) {
|
||||
if (!instanceExtensions.contains(KHRPortabilityEnumeration.VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME)) {
|
||||
throw new RuntimeException("Vulkan instance does not support portability enumeration extension but it's required for MacOS");
|
||||
}
|
||||
portabilityExtensions.add(KHRPortabilityEnumeration.VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
|
||||
}
|
||||
|
||||
return portabilityExtensions;
|
||||
}
|
||||
|
||||
private void log(String title, Set<String> layers) {
|
||||
Logger.debug("{} ({})", title, layers.size());
|
||||
for (String layer : layers) {
|
||||
Logger.debug(" - {}", layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
package fr.mrdev023.vulkan_java.vk.utils;
|
||||
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.lwjgl.PointerBuffer;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
import org.lwjgl.vulkan.VK10;
|
||||
import org.lwjgl.vulkan.VkLayerProperties;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
public class InstanceValidationLayers {
|
||||
private Set<String> validationLayers;
|
||||
|
||||
private InstanceValidationLayers(Set<String> validationLayers) {
|
||||
this.validationLayers = validationLayers;
|
||||
}
|
||||
|
||||
public boolean hasValidationLayers() {
|
||||
return !validationLayers.isEmpty();
|
||||
}
|
||||
|
||||
public Set<String> getValidationLayers() {
|
||||
return validationLayers;
|
||||
}
|
||||
|
||||
public PointerBuffer writeToStack(MemoryStack stack) {
|
||||
if (validationLayers.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PointerBuffer requiredLayers = stack.mallocPointer(validationLayers.size());
|
||||
for (String layer : validationLayers) {
|
||||
requiredLayers.put(stack.UTF8(layer));
|
||||
}
|
||||
requiredLayers.flip();
|
||||
|
||||
return requiredLayers;
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is used to select the validation layers and create an InstanceValidationLayers object.
|
||||
*
|
||||
* <h5>Specification</h5>
|
||||
* <ul>
|
||||
* <li>Include the validation layers if the user wants them</li>
|
||||
* <li>Select the validation layers from the supported validation layers</li>
|
||||
* <li>Return an InstanceValidationLayers object with the selected validation layers</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h5>See Also</h5>
|
||||
* <ul>
|
||||
* <li>{@link #includeValidationLayers(boolean)}</li>
|
||||
* <li>{@link #selectValidationLayers()}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public static class Selector {
|
||||
private boolean includeValidationLayers = false;
|
||||
|
||||
public Selector includeValidationLayers(boolean includeValidationLayers) {
|
||||
this.includeValidationLayers = includeValidationLayers;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the validation layers.
|
||||
*
|
||||
* @return the set of validation layers
|
||||
*/
|
||||
public InstanceValidationLayers selectValidationLayers() {
|
||||
var supportedLayers = getSupportedValidationLayers();
|
||||
log("Supported validation layers", supportedLayers);
|
||||
|
||||
Set<String> layersToUse = includeValidationLayers
|
||||
? selectValidationLayersFromSupportedLayers(supportedLayers)
|
||||
: Collections.emptySet();
|
||||
log("Selected validation layers", layersToUse);
|
||||
|
||||
if (layersToUse.isEmpty() && includeValidationLayers) {
|
||||
Logger.warn("Request validation but no supported validation layers found. Falling back to no validation");
|
||||
}
|
||||
|
||||
return new InstanceValidationLayers(layersToUse);
|
||||
}
|
||||
|
||||
private Set<String> getSupportedValidationLayers() {
|
||||
Set<String> supportedLayers = new HashSet<>();
|
||||
|
||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||
// Get the number of supported validation layers by the current vulkan instance
|
||||
IntBuffer numLayersArr = stack.callocInt(1);
|
||||
VK10.vkEnumerateInstanceLayerProperties(numLayersArr, null);
|
||||
int numLayers = numLayersArr.get(0);
|
||||
|
||||
// Get the supported validation layers by the current vulkan instance
|
||||
VkLayerProperties.Buffer propsBuf = VkLayerProperties.calloc(numLayers, stack);
|
||||
VK10.vkEnumerateInstanceLayerProperties(numLayersArr, propsBuf);
|
||||
|
||||
// Convert the supported validation layers to a list of strings
|
||||
for (int i = 0; i < numLayers; i++) {
|
||||
VkLayerProperties props = propsBuf.get(i);
|
||||
String layerName = props.layerNameString();
|
||||
supportedLayers.add(layerName);
|
||||
}
|
||||
}
|
||||
|
||||
return supportedLayers;
|
||||
}
|
||||
|
||||
private Set<String> selectValidationLayersFromSupportedLayers(Set<String> supportedLayers) {
|
||||
Set<String> layersToUse = new HashSet<>();
|
||||
|
||||
// Main validation layer
|
||||
if (supportedLayers.contains("VK_LAYER_KHRONOS_validation")) {
|
||||
layersToUse.add("VK_LAYER_KHRONOS_validation");
|
||||
return layersToUse;
|
||||
}
|
||||
|
||||
// Fallback 1
|
||||
if (supportedLayers.contains("VK_LAYER_LUNARG_standard_validation")) {
|
||||
layersToUse.add("VK_LAYER_LUNARG_standard_validation");
|
||||
return layersToUse;
|
||||
}
|
||||
|
||||
// Fallback 2 (set)
|
||||
Set<String> requestedLayers = new HashSet<>();
|
||||
requestedLayers.add("VK_LAYER_GOOGLE_threading");
|
||||
requestedLayers.add("VK_LAYER_LUNARG_parameter_validation");
|
||||
requestedLayers.add("VK_LAYER_LUNARG_object_tracker");
|
||||
requestedLayers.add("VK_LAYER_LUNARG_core_validation");
|
||||
requestedLayers.add("VK_LAYER_GOOGLE_unique_objects");
|
||||
|
||||
return requestedLayers.stream().filter(supportedLayers::contains).collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
private void log(String title, Set<String> layers) {
|
||||
Logger.debug("{} ({})", title, layers.size());
|
||||
for (String layer : layers) {
|
||||
Logger.debug(" - {}", layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
package fr.mrdev023.vulkan_java.vk.utils;
|
||||
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
import org.lwjgl.vulkan.VK10;
|
||||
import org.lwjgl.vulkan.VkLayerProperties;
|
||||
import org.tinylog.Logger;
|
||||
|
||||
public class InstanceValidationLayersSelector {
|
||||
private boolean withValidationLayers = false;
|
||||
|
||||
public InstanceValidationLayersSelector withValidationLayers(boolean withValidationLayers) {
|
||||
this.withValidationLayers = withValidationLayers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<String> selectValidationLayers() {
|
||||
if (!withValidationLayers) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
var supportedLayers = getSupportedValidationLayers();
|
||||
log("Supported validation layers", supportedLayers);
|
||||
|
||||
var layersToUse = selectValidationLayersFromSupportedLayers(supportedLayers);
|
||||
log("Selected validation layers", layersToUse);
|
||||
|
||||
if (layersToUse.isEmpty() && withValidationLayers) {
|
||||
Logger.warn("Request validation but no supported validation layers found. Falling back to no validation");
|
||||
}
|
||||
|
||||
return layersToUse;
|
||||
}
|
||||
|
||||
private List<String> getSupportedValidationLayers() {
|
||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||
// Get the number of supported validation layers by the current vulkan instance
|
||||
IntBuffer numLayersArr = stack.callocInt(1);
|
||||
VK10.vkEnumerateInstanceLayerProperties(numLayersArr, null);
|
||||
int numLayers = numLayersArr.get(0);
|
||||
|
||||
// Get the supported validation layers by the current vulkan instance
|
||||
VkLayerProperties.Buffer propsBuf = VkLayerProperties.calloc(numLayers, stack);
|
||||
VK10.vkEnumerateInstanceLayerProperties(numLayersArr, propsBuf);
|
||||
|
||||
// Convert the supported validation layers to a list of strings
|
||||
List<String> supportedLayers = new ArrayList<>();
|
||||
for (int i = 0; i < numLayers; i++) {
|
||||
VkLayerProperties props = propsBuf.get(i);
|
||||
String layerName = props.layerNameString();
|
||||
supportedLayers.add(layerName);
|
||||
}
|
||||
|
||||
return supportedLayers;
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> selectValidationLayersFromSupportedLayers(List<String> supportedLayers) {
|
||||
List<String> layersToUse = new ArrayList<>();
|
||||
|
||||
// Main validation layer
|
||||
if (supportedLayers.contains("VK_LAYER_KHRONOS_validation")) {
|
||||
layersToUse.add("VK_LAYER_KHRONOS_validation");
|
||||
return layersToUse;
|
||||
}
|
||||
|
||||
// Fallback 1
|
||||
if (supportedLayers.contains("VK_LAYER_LUNARG_standard_validation")) {
|
||||
layersToUse.add("VK_LAYER_LUNARG_standard_validation");
|
||||
return layersToUse;
|
||||
}
|
||||
|
||||
// Fallback 2 (set)
|
||||
List<String> requestedLayers = new ArrayList<>();
|
||||
requestedLayers.add("VK_LAYER_GOOGLE_threading");
|
||||
requestedLayers.add("VK_LAYER_LUNARG_parameter_validation");
|
||||
requestedLayers.add("VK_LAYER_LUNARG_object_tracker");
|
||||
requestedLayers.add("VK_LAYER_LUNARG_core_validation");
|
||||
requestedLayers.add("VK_LAYER_GOOGLE_unique_objects");
|
||||
|
||||
return requestedLayers.stream().filter(supportedLayers::contains).toList();
|
||||
}
|
||||
|
||||
private void log(String title, List<String> layers) {
|
||||
Logger.debug("{} ({})", title, layers.size());
|
||||
for (String layer : layers) {
|
||||
Logger.debug(" - {}", layer);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue