From 3749af2c5c0baf786bd73b84fe4d342b00180001 Mon Sep 17 00:00:00 2001 From: Florian RICHER Date: Sat, 24 May 2025 16:25:10 +0200 Subject: [PATCH] Refactor --- .../fr/mrdev023/vulkan_java/vk/Device.java | 65 +++++++------- .../vulkan_java/vk/PhysicalDevice.java | 47 ++++++---- .../fr/mrdev023/vulkan_java/vk/Queue.java | 24 ----- .../vulkan_java/vk/QueueFamilyIndices.java | 67 ++++++++++++++ .../vulkan_java/vk/QueuesCreator.java | 76 ++++++++++++++++ .../fr/mrdev023/vulkan_java/vk/Vulkan.java | 8 +- .../requirements/ComputeQueueRequirement.java | 26 ------ .../GraphicsQueueRequirement.java | 26 ------ .../requirements/IQueueFamilyRequirement.java | 13 --- .../SurfacePresentQueueRequirement.java | 40 --------- .../TransferQueueRequirement.java | 26 ------ .../PhysicalDeviceCompatibilityValidator.java | 77 ---------------- .../QueueFamilyRequirementsValidator.java | 70 --------------- .../loggers/DeviceExtensionsResultLogger.java | 2 +- .../PhysicalDeviceCompatibilityLogger.java | 4 +- .../QueueFamilyRequirementResultLogger.java | 31 ++++--- .../utils/SuitablePhysicalDeviceFinder.java | 12 +-- .../validators/DeviceExtensionsValidator.java | 8 +- .../PhysicalDeviceCompatibilityValidator.java | 54 ++++++++++++ .../QueueFamilyRequirementsValidator.java | 87 +++++++++++++++++++ 20 files changed, 385 insertions(+), 378 deletions(-) create mode 100644 src/main/java/fr/mrdev023/vulkan_java/vk/QueueFamilyIndices.java create mode 100644 src/main/java/fr/mrdev023/vulkan_java/vk/QueuesCreator.java delete mode 100644 src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/ComputeQueueRequirement.java delete mode 100644 src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/GraphicsQueueRequirement.java delete mode 100644 src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/IQueueFamilyRequirement.java delete mode 100644 src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/SurfacePresentQueueRequirement.java delete mode 100644 src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/TransferQueueRequirement.java delete mode 100644 src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/validators/PhysicalDeviceCompatibilityValidator.java delete mode 100644 src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/validators/QueueFamilyRequirementsValidator.java rename src/main/java/fr/mrdev023/vulkan_java/vk/{compatibilities => }/validators/DeviceExtensionsValidator.java (90%) create mode 100644 src/main/java/fr/mrdev023/vulkan_java/vk/validators/PhysicalDeviceCompatibilityValidator.java create mode 100644 src/main/java/fr/mrdev023/vulkan_java/vk/validators/QueueFamilyRequirementsValidator.java diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/Device.java b/src/main/java/fr/mrdev023/vulkan_java/vk/Device.java index a902b7d..afe6e29 100644 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/Device.java +++ b/src/main/java/fr/mrdev023/vulkan_java/vk/Device.java @@ -1,25 +1,30 @@ package fr.mrdev023.vulkan_java.vk; +import static fr.mrdev023.vulkan_java.vk.VulkanError.vkCheck; +import static org.lwjgl.vulkan.VK10.VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; +import static org.lwjgl.vulkan.VK10.vkCreateDevice; +import static org.lwjgl.vulkan.VK10.vkDestroyDevice; +import static org.lwjgl.vulkan.VK10.vkDeviceWaitIdle; + +import java.util.Optional; + import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; -import org.lwjgl.vulkan.*; +import org.lwjgl.vulkan.VkDevice; +import org.lwjgl.vulkan.VkDeviceCreateInfo; +import org.lwjgl.vulkan.VkPhysicalDeviceFeatures; import org.tinylog.Logger; import fr.mrdev023.vulkan_java.vk.utils.SuitablePhysicalDeviceFinder; -import java.nio.*; - -import static fr.mrdev023.vulkan_java.vk.VulkanError.vkCheck; -import static org.lwjgl.vulkan.VK11.*; - public class Device { private final PhysicalDevice physicalDevice; private final VkDevice vkDevice; - private final Queue.PresentQueue presentQueue; - private final Queue.GraphicsQueue graphicsQueue; - private final Queue.ComputeQueue computeQueue; - private final Queue.TransferQueue transferQueue; + private final Optional presentQueue; + private final Optional graphicsQueue; + private final Optional computeQueue; + private final Optional transferQueue; public Device(SuitablePhysicalDeviceFinder.MatchResult physicalDeviceMatch) throws VulkanError { this.physicalDevice = physicalDeviceMatch.physicalDevice; @@ -36,17 +41,9 @@ public class Device { VkPhysicalDeviceFeatures features = VkPhysicalDeviceFeatures.calloc(stack); // Enable all the queue families - VkQueueFamilyProperties.Buffer queuePropsBuff = physicalDevice.getVkQueueFamilyProps(); - int numQueuesFamilies = queuePropsBuff.capacity(); - VkDeviceQueueCreateInfo.Buffer queueCreationInfoBuf = VkDeviceQueueCreateInfo.calloc(numQueuesFamilies, - stack); - for (int i = 0; i < numQueuesFamilies; i++) { - FloatBuffer priorities = stack.callocFloat(queuePropsBuff.get(i).queueCount()); - queueCreationInfoBuf.get(i) - .sType(VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO) - .queueFamilyIndex(i) - .pQueuePriorities(priorities); - } + var queueFamilyIndices = physicalDeviceMatch.validatorResult.queueFamilyIndices.orElseThrow(); + var queuesCreator = new QueuesCreator(queueFamilyIndices); + var queueCreationInfoBuf = queuesCreator.createQueueCreateInfos(stack, physicalDevice); VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.calloc(stack) .sType(VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO) @@ -59,16 +56,14 @@ public class Device { "Failed to create device"); vkDevice = new VkDevice(pp.get(0), physicalDevice.getVkPhysicalDevice(), deviceCreateInfo); - // graphicsQueue = new Queue.GraphicsQueue(this, - // physicalDeviceMatch.graphicsQueueFamilyIndex, 0); - // computeQueue = new Queue.ComputeQueue(this, - // physicalDeviceMatch.computeQueueFamilyIndex, 1); - // transferQueue = new Queue.TransferQueue(this, - // physicalDeviceMatch.transferQueueFamilyIndex, 2); - presentQueue = null; - graphicsQueue = null; - computeQueue = null; - transferQueue = null; + graphicsQueue = queueFamilyIndices.getGraphicsQueueFamilyIndex() + .flatMap(queueFamilyIndex -> Optional.of(queuesCreator.createQueue(this, queueFamilyIndex))); + presentQueue = queueFamilyIndices.getPresentQueueFamilyIndex() + .flatMap(queueFamilyIndex -> Optional.of(queuesCreator.createQueue(this, queueFamilyIndex))); + computeQueue = queueFamilyIndices.getComputeQueueFamilyIndex() + .flatMap(queueFamilyIndex -> Optional.of(queuesCreator.createQueue(this, queueFamilyIndex))); + transferQueue = queueFamilyIndices.getTransferQueueFamilyIndex() + .flatMap(queueFamilyIndex -> Optional.of(queuesCreator.createQueue(this, queueFamilyIndex))); } Logger.debug("Vulkan device created"); @@ -91,19 +86,19 @@ public class Device { vkDeviceWaitIdle(vkDevice); } - public Queue.PresentQueue getPresentQueue() { + public Optional getPresentQueue() { return presentQueue; } - public Queue.GraphicsQueue getGraphicsQueue() { + public Optional getGraphicsQueue() { return graphicsQueue; } - public Queue.ComputeQueue getComputeQueue() { + public Optional getComputeQueue() { return computeQueue; } - public Queue.TransferQueue getTransferQueue() { + public Optional getTransferQueue() { return transferQueue; } } \ No newline at end of file diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/PhysicalDevice.java b/src/main/java/fr/mrdev023/vulkan_java/vk/PhysicalDevice.java index bd4425d..03404e7 100644 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/PhysicalDevice.java +++ b/src/main/java/fr/mrdev023/vulkan_java/vk/PhysicalDevice.java @@ -21,27 +21,15 @@ public class PhysicalDevice { private final VkQueueFamilyProperties.Buffer vkQueueFamilyProps; private PhysicalDevice(VkPhysicalDevice vkPhysicalDevice) throws VulkanError { + this.vkPhysicalDevice = vkPhysicalDevice; + try (MemoryStack stack = MemoryStack.stackPush()) { - this.vkPhysicalDevice = vkPhysicalDevice; - - IntBuffer intBuffer = stack.mallocInt(1); - // Get device properties vkPhysicalDeviceProperties = VkPhysicalDeviceProperties.calloc(); vkGetPhysicalDeviceProperties(vkPhysicalDevice, vkPhysicalDeviceProperties); - // Get device extensions - vkCheck(vkEnumerateDeviceExtensionProperties(vkPhysicalDevice, (String) null, intBuffer, null), - "Failed to get number of device extension properties"); - vkDeviceExtensions = VkExtensionProperties.calloc(intBuffer.get(0)); - vkCheck(vkEnumerateDeviceExtensionProperties(vkPhysicalDevice, (String) null, intBuffer, - vkDeviceExtensions), - "Failed to get extension properties"); - - // Get Queue family properties - vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, intBuffer, null); - vkQueueFamilyProps = VkQueueFamilyProperties.calloc(intBuffer.get(0)); - vkGetPhysicalDeviceQueueFamilyProperties(vkPhysicalDevice, intBuffer, vkQueueFamilyProps); + vkDeviceExtensions = getVulkanPhysicalDeviceExtensions(stack, vkPhysicalDevice); + vkQueueFamilyProps = getVulkanQueueFamilyProperties(stack, vkPhysicalDevice); vkPhysicalDeviceFeatures = VkPhysicalDeviceFeatures.calloc(); vkGetPhysicalDeviceFeatures(vkPhysicalDevice, vkPhysicalDeviceFeatures); @@ -113,4 +101,31 @@ public class PhysicalDevice { public VkExtensionProperties.Buffer getVkDeviceExtensions() { return vkDeviceExtensions; } + + private static VkExtensionProperties.Buffer getVulkanPhysicalDeviceExtensions(MemoryStack stack, + VkPhysicalDevice physicalDevice) + throws VulkanError { + IntBuffer numExtensions = stack.mallocInt(1); + vkCheck(vkEnumerateDeviceExtensionProperties(physicalDevice, (String) null, numExtensions, null), + "Failed to get number of device extension properties"); + + VkExtensionProperties.Buffer deviceExtensions = VkExtensionProperties.calloc(numExtensions.get(0)); + vkCheck(vkEnumerateDeviceExtensionProperties(physicalDevice, (String) null, numExtensions, + deviceExtensions), + "Failed to get extension properties"); + + return deviceExtensions; + } + + private static VkQueueFamilyProperties.Buffer getVulkanQueueFamilyProperties(MemoryStack stack, + VkPhysicalDevice physicalDevice) + throws VulkanError { + IntBuffer numQueueFamilies = stack.mallocInt(1); + vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, numQueueFamilies, null); + + VkQueueFamilyProperties.Buffer queueFamilyProps = VkQueueFamilyProperties.calloc(numQueueFamilies.get(0)); + vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, numQueueFamilies, queueFamilyProps); + + return queueFamilyProps; + } } \ No newline at end of file diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/Queue.java b/src/main/java/fr/mrdev023/vulkan_java/vk/Queue.java index c908278..0513710 100644 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/Queue.java +++ b/src/main/java/fr/mrdev023/vulkan_java/vk/Queue.java @@ -29,28 +29,4 @@ public class Queue { public void waitIdle() { vkQueueWaitIdle(vkQueue); } - - public static class GraphicsQueue extends Queue { - public GraphicsQueue(Device device, int queueFamilyIndex, int queueIndex) { - super(device, queueFamilyIndex, queueIndex); - } - } - - public static class PresentQueue extends Queue { - public PresentQueue(Device device, int queueFamilyIndex, int queueIndex) { - super(device, queueFamilyIndex, queueIndex); - } - } - - public static class ComputeQueue extends Queue { - public ComputeQueue(Device device, int queueFamilyIndex, int queueIndex) { - super(device, queueFamilyIndex, queueIndex); - } - } - - public static class TransferQueue extends Queue { - public TransferQueue(Device device, int queueFamilyIndex, int queueIndex) { - super(device, queueFamilyIndex, queueIndex); - } - } } \ No newline at end of file diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/QueueFamilyIndices.java b/src/main/java/fr/mrdev023/vulkan_java/vk/QueueFamilyIndices.java new file mode 100644 index 0000000..64bb61f --- /dev/null +++ b/src/main/java/fr/mrdev023/vulkan_java/vk/QueueFamilyIndices.java @@ -0,0 +1,67 @@ +package fr.mrdev023.vulkan_java.vk; + +import java.util.HashMap; +import java.util.Optional; + +public class QueueFamilyIndices { + private final Optional graphicsQueueFamilyIndex; + private final Optional computeQueueFamilyIndex; + private final Optional transferQueueFamilyIndex; + private final Optional presentQueueFamilyIndex; + + public QueueFamilyIndices(Optional graphicsQueueFamilyIndex, Optional computeQueueFamilyIndex, + Optional transferQueueFamilyIndex, Optional presentQueueFamilyIndex) { + this.graphicsQueueFamilyIndex = graphicsQueueFamilyIndex; + this.computeQueueFamilyIndex = computeQueueFamilyIndex; + this.transferQueueFamilyIndex = transferQueueFamilyIndex; + this.presentQueueFamilyIndex = presentQueueFamilyIndex; + } + + public Optional getGraphicsQueueFamilyIndex() { + return graphicsQueueFamilyIndex; + } + + public Optional getComputeQueueFamilyIndex() { + return computeQueueFamilyIndex; + } + + public Optional getTransferQueueFamilyIndex() { + return transferQueueFamilyIndex; + } + + public Optional getPresentQueueFamilyIndex() { + return presentQueueFamilyIndex; + } + + public static class Builder { + private Optional graphicsQueueFamilyIndex; + private Optional computeQueueFamilyIndex; + private Optional transferQueueFamilyIndex; + private Optional presentQueueFamilyIndex; + + public Builder withGraphicsQueueFamilyIndex(int graphicsQueueFamilyIndex) { + this.graphicsQueueFamilyIndex = Optional.of(graphicsQueueFamilyIndex); + return this; + } + + public Builder withComputeQueueFamilyIndex(int computeQueueFamilyIndex) { + this.computeQueueFamilyIndex = Optional.of(computeQueueFamilyIndex); + return this; + } + + public Builder withTransferQueueFamilyIndex(int transferQueueFamilyIndex) { + this.transferQueueFamilyIndex = Optional.of(transferQueueFamilyIndex); + return this; + } + + public Builder withPresentQueueFamilyIndex(int presentQueueFamilyIndex) { + this.presentQueueFamilyIndex = Optional.of(presentQueueFamilyIndex); + return this; + } + + public QueueFamilyIndices build() { + return new QueueFamilyIndices(graphicsQueueFamilyIndex, computeQueueFamilyIndex, transferQueueFamilyIndex, + presentQueueFamilyIndex); + } + } +} diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/QueuesCreator.java b/src/main/java/fr/mrdev023/vulkan_java/vk/QueuesCreator.java new file mode 100644 index 0000000..8505175 --- /dev/null +++ b/src/main/java/fr/mrdev023/vulkan_java/vk/QueuesCreator.java @@ -0,0 +1,76 @@ +package fr.mrdev023.vulkan_java.vk; + +import java.nio.FloatBuffer; +import java.util.HashMap; + +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.VK10; +import org.lwjgl.vulkan.VkDeviceQueueCreateInfo; + +public class QueuesCreator { + private final HashMap families; + private HashMap counters; + + public QueuesCreator(QueueFamilyIndices queueFamilyIndices) { + this.families = createFamilies(queueFamilyIndices); + this.counters = new HashMap<>(); + for (var family : families.keySet()) { + counters.put(family, 0); + } + } + + public VkDeviceQueueCreateInfo.Buffer createQueueCreateInfos(MemoryStack stack, + PhysicalDevice physicalDevice) { + + VkDeviceQueueCreateInfo.Buffer queueCreationInfoBuf = VkDeviceQueueCreateInfo.calloc(families.size(), + stack); + int i = 0; + for (var familyIndex : families.keySet()) { + FloatBuffer priorities = stack.callocFloat(families.get(familyIndex)); + queueCreationInfoBuf.get(i) + .sType(VK10.VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO) + .queueFamilyIndex(familyIndex) + .pQueuePriorities(priorities); + i++; + } + + return queueCreationInfoBuf; + } + + public Queue createQueue(Device device, int queueFamilyIndex) { + var queueIndex = getNextAvailableQueueIndexForFamilyIndex(queueFamilyIndex); + return new Queue(device, queueFamilyIndex, queueIndex); + } + + private int getNextAvailableQueueIndexForFamilyIndex(int queueFamilyIndex) { + var max = families.getOrDefault(queueFamilyIndex, 0); + var current = counters.getOrDefault(queueFamilyIndex, 0); + if (current >= max) { + throw new RuntimeException("No more queues available for family " + queueFamilyIndex); + } + + counters.put(queueFamilyIndex, current + 1); + return current + 1; + } + + private HashMap createFamilies(QueueFamilyIndices queueFamilyIndices) { + var families = new HashMap(); + if (queueFamilyIndices.getGraphicsQueueFamilyIndex().isPresent()) { + var familyIndex = queueFamilyIndices.getGraphicsQueueFamilyIndex().get(); + families.put(familyIndex, families.getOrDefault(familyIndex, 0) + 1); + } + if (queueFamilyIndices.getComputeQueueFamilyIndex().isPresent()) { + var familyIndex = queueFamilyIndices.getComputeQueueFamilyIndex().get(); + families.put(familyIndex, families.getOrDefault(familyIndex, 0) + 1); + } + if (queueFamilyIndices.getTransferQueueFamilyIndex().isPresent()) { + var familyIndex = queueFamilyIndices.getTransferQueueFamilyIndex().get(); + families.put(familyIndex, families.getOrDefault(familyIndex, 0) + 1); + } + if (queueFamilyIndices.getPresentQueueFamilyIndex().isPresent()) { + var familyIndex = queueFamilyIndices.getPresentQueueFamilyIndex().get(); + families.put(familyIndex, families.getOrDefault(familyIndex, 0) + 1); + } + return families; + } +} \ No newline at end of file diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/Vulkan.java b/src/main/java/fr/mrdev023/vulkan_java/vk/Vulkan.java index 038417b..8f9c91a 100644 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/Vulkan.java +++ b/src/main/java/fr/mrdev023/vulkan_java/vk/Vulkan.java @@ -1,8 +1,6 @@ package fr.mrdev023.vulkan_java.vk; -import fr.mrdev023.vulkan_java.vk.compatibilities.validators.PhysicalDeviceCompatibilityValidator; -import fr.mrdev023.vulkan_java.vk.utils.SuitablePhysicalDeviceFinder; -import fr.mrdev023.vulkan_java.window.Display; +import static org.lwjgl.glfw.GLFWVulkan.glfwVulkanSupported; import java.util.Optional; import java.util.Set; @@ -12,7 +10,9 @@ import org.lwjgl.vulkan.KHRPortabilitySubset; import org.lwjgl.vulkan.KHRSwapchain; import org.lwjgl.vulkan.VK10; -import static org.lwjgl.glfw.GLFWVulkan.glfwVulkanSupported; +import fr.mrdev023.vulkan_java.vk.utils.SuitablePhysicalDeviceFinder; +import fr.mrdev023.vulkan_java.vk.validators.PhysicalDeviceCompatibilityValidator; +import fr.mrdev023.vulkan_java.window.Display; public class Vulkan { diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/ComputeQueueRequirement.java b/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/ComputeQueueRequirement.java deleted file mode 100644 index de1f05b..0000000 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/ComputeQueueRequirement.java +++ /dev/null @@ -1,26 +0,0 @@ -package fr.mrdev023.vulkan_java.vk.compatibilities.requirements; - -import java.util.Optional; - -import org.lwjgl.vulkan.VK10; -import org.lwjgl.vulkan.VkQueueFamilyProperties; - -import fr.mrdev023.vulkan_java.vk.PhysicalDevice; - -public class ComputeQueueRequirement implements IQueueFamilyRequirement { - - @Override - public boolean isFamilySuitable(PhysicalDevice physicalDevice, VkQueueFamilyProperties queueFamilyProperties, int queueFamilyIndex) { - return (queueFamilyProperties.queueFlags() & VK10.VK_QUEUE_COMPUTE_BIT) != 0; - } - - @Override - public String getName() { - return "Compute Queue"; - } - - @Override - public Optional getQueueFlag() { - return Optional.of(VK10.VK_QUEUE_COMPUTE_BIT); - } -} diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/GraphicsQueueRequirement.java b/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/GraphicsQueueRequirement.java deleted file mode 100644 index f1505f0..0000000 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/GraphicsQueueRequirement.java +++ /dev/null @@ -1,26 +0,0 @@ -package fr.mrdev023.vulkan_java.vk.compatibilities.requirements; - -import java.util.Optional; - -import org.lwjgl.vulkan.VK10; -import org.lwjgl.vulkan.VkQueueFamilyProperties; - -import fr.mrdev023.vulkan_java.vk.PhysicalDevice; - -public class GraphicsQueueRequirement implements IQueueFamilyRequirement { - - @Override - public boolean isFamilySuitable(PhysicalDevice physicalDevice, VkQueueFamilyProperties queueFamilyProperties, int queueFamilyIndex) { - return (queueFamilyProperties.queueFlags() & VK10.VK_QUEUE_GRAPHICS_BIT) != 0; - } - - @Override - public String getName() { - return "Graphics Queue"; - } - - @Override - public Optional getQueueFlag() { - return Optional.of(VK10.VK_QUEUE_GRAPHICS_BIT); - } -} diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/IQueueFamilyRequirement.java b/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/IQueueFamilyRequirement.java deleted file mode 100644 index 6b5ee7a..0000000 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/IQueueFamilyRequirement.java +++ /dev/null @@ -1,13 +0,0 @@ -package fr.mrdev023.vulkan_java.vk.compatibilities.requirements; - -import java.util.Optional; - -import org.lwjgl.vulkan.VkQueueFamilyProperties; - -import fr.mrdev023.vulkan_java.vk.PhysicalDevice; - -public interface IQueueFamilyRequirement { - boolean isFamilySuitable(PhysicalDevice physicalDevice, VkQueueFamilyProperties queueFamilyProperties, int queueFamilyIndex); - String getName(); - Optional getQueueFlag(); -} diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/SurfacePresentQueueRequirement.java b/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/SurfacePresentQueueRequirement.java deleted file mode 100644 index ea05999..0000000 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/SurfacePresentQueueRequirement.java +++ /dev/null @@ -1,40 +0,0 @@ -package fr.mrdev023.vulkan_java.vk.compatibilities.requirements; - -import java.nio.IntBuffer; -import java.util.Optional; - -import org.lwjgl.system.MemoryStack; -import org.lwjgl.vulkan.KHRSurface; -import org.lwjgl.vulkan.VK10; -import org.lwjgl.vulkan.VkQueueFamilyProperties; - -import fr.mrdev023.vulkan_java.vk.PhysicalDevice; -import fr.mrdev023.vulkan_java.vk.Surface; - -public class SurfacePresentQueueRequirement implements IQueueFamilyRequirement { - - private final Surface surface; - - public SurfacePresentQueueRequirement(Surface surface) { - this.surface = surface; - } - - @Override - public boolean isFamilySuitable(PhysicalDevice physicalDevice, VkQueueFamilyProperties queueFamilyProperties, int queueFamilyIndex) { - try (MemoryStack stack = MemoryStack.stackPush()) { - IntBuffer presentSupport = stack.ints(VK10.VK_FALSE); - KHRSurface.vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice.getVkPhysicalDevice(), queueFamilyIndex, surface.getVkSurface(), presentSupport); - return presentSupport.get(0) == VK10.VK_TRUE; - } - } - - @Override - public String getName() { - return "Surface Present Queue"; - } - - @Override - public Optional getQueueFlag() { - return Optional.empty(); - } -} diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/TransferQueueRequirement.java b/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/TransferQueueRequirement.java deleted file mode 100644 index b318efc..0000000 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/requirements/TransferQueueRequirement.java +++ /dev/null @@ -1,26 +0,0 @@ -package fr.mrdev023.vulkan_java.vk.compatibilities.requirements; - -import java.util.Optional; - -import org.lwjgl.vulkan.VK10; -import org.lwjgl.vulkan.VkQueueFamilyProperties; - -import fr.mrdev023.vulkan_java.vk.PhysicalDevice; - -public class TransferQueueRequirement implements IQueueFamilyRequirement { - - @Override - public boolean isFamilySuitable(PhysicalDevice physicalDevice, VkQueueFamilyProperties queueFamilyProperties, int queueFamilyIndex) { - return (queueFamilyProperties.queueFlags() & VK10.VK_QUEUE_TRANSFER_BIT) != 0; - } - - @Override - public String getName() { - return "Transfer Queue"; - } - - @Override - public Optional getQueueFlag() { - return Optional.of(VK10.VK_QUEUE_TRANSFER_BIT); - } -} diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/validators/PhysicalDeviceCompatibilityValidator.java b/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/validators/PhysicalDeviceCompatibilityValidator.java deleted file mode 100644 index e16c2b8..0000000 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/validators/PhysicalDeviceCompatibilityValidator.java +++ /dev/null @@ -1,77 +0,0 @@ -package fr.mrdev023.vulkan_java.vk.compatibilities.validators; - -import java.util.ArrayList; -import java.util.Optional; -import java.util.Set; - -import org.lwjgl.vulkan.VK10; - -import fr.mrdev023.vulkan_java.vk.PhysicalDevice; -import fr.mrdev023.vulkan_java.vk.Surface; -import fr.mrdev023.vulkan_java.vk.compatibilities.requirements.ComputeQueueRequirement; -import fr.mrdev023.vulkan_java.vk.compatibilities.requirements.GraphicsQueueRequirement; -import fr.mrdev023.vulkan_java.vk.compatibilities.requirements.IQueueFamilyRequirement; -import fr.mrdev023.vulkan_java.vk.compatibilities.requirements.SurfacePresentQueueRequirement; -import fr.mrdev023.vulkan_java.vk.compatibilities.requirements.TransferQueueRequirement; - -public class PhysicalDeviceCompatibilityValidator { - private int requiredQueueFlags; - private Set requiredExtensions; - private final Optional surface; - - public PhysicalDeviceCompatibilityValidator(int requiredQueueFlags, Set requiredExtensions, Optional surface) { - this.requiredQueueFlags = requiredQueueFlags; - this.requiredExtensions = requiredExtensions; - this.surface = surface; - } - - public Result validate(PhysicalDevice physicalDevice) { - var queueFamilyRequirementsResult = validateQueueFamilyRequirements(physicalDevice); - var deviceExtensionsResult = validateDeviceExtensions(physicalDevice); - - return new Result(queueFamilyRequirementsResult, deviceExtensionsResult); - } - - private QueueFamilyRequirementsValidator.Result validateQueueFamilyRequirements(PhysicalDevice physicalDevice) { - var queueFamilyRequirements = new ArrayList(); - - if ((requiredQueueFlags & VK10.VK_QUEUE_GRAPHICS_BIT) != 0) { - queueFamilyRequirements.add(new GraphicsQueueRequirement()); - } - - if ((requiredQueueFlags & VK10.VK_QUEUE_COMPUTE_BIT) != 0) { - queueFamilyRequirements.add(new ComputeQueueRequirement()); - } - - if ((requiredQueueFlags & VK10.VK_QUEUE_TRANSFER_BIT) != 0) { - queueFamilyRequirements.add(new TransferQueueRequirement()); - } - - if (surface.isPresent()) { - queueFamilyRequirements.add(new SurfacePresentQueueRequirement(surface.get())); - } - - var queueFamilyRequirementsValidator = new QueueFamilyRequirementsValidator(queueFamilyRequirements); - var result = queueFamilyRequirementsValidator.validate(physicalDevice); - - return result; - } - - private DeviceExtensionsValidator.Result validateDeviceExtensions(PhysicalDevice physicalDevice) { - var deviceExtensionsValidator = new DeviceExtensionsValidator(requiredExtensions); - var result = deviceExtensionsValidator.validate(physicalDevice); - return result; - } - - public static class Result { - public final boolean isSuitable; - public final QueueFamilyRequirementsValidator.Result queueFamilyRequirementsResult; - public final DeviceExtensionsValidator.Result deviceExtensionsResult; - - public Result(QueueFamilyRequirementsValidator.Result queueFamilyRequirementsResult, DeviceExtensionsValidator.Result deviceExtensionsResult) { - this.isSuitable = queueFamilyRequirementsResult.isSuitable && deviceExtensionsResult.isSuitable; - this.queueFamilyRequirementsResult = queueFamilyRequirementsResult; - this.deviceExtensionsResult = deviceExtensionsResult; - } - } -} diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/validators/QueueFamilyRequirementsValidator.java b/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/validators/QueueFamilyRequirementsValidator.java deleted file mode 100644 index de12219..0000000 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/validators/QueueFamilyRequirementsValidator.java +++ /dev/null @@ -1,70 +0,0 @@ -package fr.mrdev023.vulkan_java.vk.compatibilities.validators; - -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -import fr.mrdev023.vulkan_java.vk.PhysicalDevice; -import fr.mrdev023.vulkan_java.vk.compatibilities.requirements.IQueueFamilyRequirement; - -public class QueueFamilyRequirementsValidator { - private List requirements; - - public QueueFamilyRequirementsValidator(List requirements) { - this.requirements = requirements; - } - - /** - * Validate the queue family requirements of the physical device. - * - * Note: This method return a Result to adapt the requirements to the - * physical device properties after the validation. - * - * @param physicalDevice The physical device to validate the requirements for. - * @return A result object containing the validation results and whether the - * physical device is suitable. - */ - public Result validate(PhysicalDevice physicalDevice) { - var vkQueueFamilyProps = physicalDevice.getVkQueueFamilyProps(); - - HashMap> result = requirements.stream() - .collect(Collectors.toMap( - requirement -> requirement, - requirement -> Optional.empty(), - (a, b) -> a, - HashMap::new)); - - for (int i = 0; i < vkQueueFamilyProps.capacity(); i++) { - var vkQueueFamilyProp = vkQueueFamilyProps.get(i); - - for (var requirement : requirements) { - if (result.get(requirement).isPresent()) { - continue; - } - - if (requirement.isFamilySuitable(physicalDevice, vkQueueFamilyProp, i)) { - result.put(requirement, Optional.of(i)); - } - } - - if (result.values().stream().allMatch(Optional::isPresent)) { - break; - } - } - - boolean isSuitable = result.values().stream().allMatch(Optional::isPresent); - - return new Result(result, isSuitable); - } - - public static class Result { - public final HashMap> queueFamilyIndices; - public final boolean isSuitable; - - public Result(HashMap> queueFamilyIndices, boolean isSuitable) { - this.queueFamilyIndices = queueFamilyIndices; - this.isSuitable = isSuitable; - } - } -} diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/loggers/DeviceExtensionsResultLogger.java b/src/main/java/fr/mrdev023/vulkan_java/vk/loggers/DeviceExtensionsResultLogger.java index 9a3fcec..91c742e 100644 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/loggers/DeviceExtensionsResultLogger.java +++ b/src/main/java/fr/mrdev023/vulkan_java/vk/loggers/DeviceExtensionsResultLogger.java @@ -1,6 +1,6 @@ package fr.mrdev023.vulkan_java.vk.loggers; -import fr.mrdev023.vulkan_java.vk.compatibilities.validators.DeviceExtensionsValidator; +import fr.mrdev023.vulkan_java.vk.validators.DeviceExtensionsValidator; public class DeviceExtensionsResultLogger { public static void log(DeviceExtensionsValidator.Result result) { diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/loggers/PhysicalDeviceCompatibilityLogger.java b/src/main/java/fr/mrdev023/vulkan_java/vk/loggers/PhysicalDeviceCompatibilityLogger.java index 94bf9bf..da134a3 100644 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/loggers/PhysicalDeviceCompatibilityLogger.java +++ b/src/main/java/fr/mrdev023/vulkan_java/vk/loggers/PhysicalDeviceCompatibilityLogger.java @@ -1,13 +1,13 @@ package fr.mrdev023.vulkan_java.vk.loggers; import fr.mrdev023.vulkan_java.vk.PhysicalDevice; -import fr.mrdev023.vulkan_java.vk.compatibilities.validators.PhysicalDeviceCompatibilityValidator; +import fr.mrdev023.vulkan_java.vk.validators.PhysicalDeviceCompatibilityValidator; public class PhysicalDeviceCompatibilityLogger { public static void log(PhysicalDevice physicalDevice, PhysicalDeviceCompatibilityValidator.Result result) { ScopedLogger.pushScope("Physical device support (Is suitable: {})", result.isSuitable); PhysicalDevicePropertiesLogger.log(physicalDevice); - QueueFamilyRequirementResultLogger.log(result.queueFamilyRequirementsResult); + QueueFamilyRequirementResultLogger.log(result.queueFamilyIndices); DeviceExtensionsResultLogger.log(result.deviceExtensionsResult); ScopedLogger.popScope(); } diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/loggers/QueueFamilyRequirementResultLogger.java b/src/main/java/fr/mrdev023/vulkan_java/vk/loggers/QueueFamilyRequirementResultLogger.java index 7fd5080..af8bff8 100644 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/loggers/QueueFamilyRequirementResultLogger.java +++ b/src/main/java/fr/mrdev023/vulkan_java/vk/loggers/QueueFamilyRequirementResultLogger.java @@ -1,17 +1,28 @@ package fr.mrdev023.vulkan_java.vk.loggers; -import fr.mrdev023.vulkan_java.vk.compatibilities.validators.QueueFamilyRequirementsValidator; +import java.util.Optional; + +import fr.mrdev023.vulkan_java.vk.QueueFamilyIndices; public class QueueFamilyRequirementResultLogger { - public static void log(QueueFamilyRequirementsValidator.Result result) { - ScopedLogger.pushScope("Queue Family Requirements (Is suitable: {})", result.isSuitable); - result.queueFamilyIndices.forEach((requirement, index) -> { - if (index.isPresent()) { - ScopedLogger.log("{}: [SUPPORTED]", requirement.getName()); - } else { - ScopedLogger.log("{}: [UNSUPPORTED]", requirement.getName(), requirement.getQueueFlag().orElse(null)); - } - }); + public static void log(Optional queueFamilyIndices) { + ScopedLogger.pushScope("Queue Family Requirements (Is suitable: {})", queueFamilyIndices.isPresent()); + logQueueFamilyResult("Graphics Queue", + queueFamilyIndices.flatMap(QueueFamilyIndices::getGraphicsQueueFamilyIndex)); + logQueueFamilyResult("Compute Queue", + queueFamilyIndices.flatMap(QueueFamilyIndices::getComputeQueueFamilyIndex)); + logQueueFamilyResult("Transfer Queue", + queueFamilyIndices.flatMap(QueueFamilyIndices::getTransferQueueFamilyIndex)); + logQueueFamilyResult("Present Queue", + queueFamilyIndices.flatMap(QueueFamilyIndices::getPresentQueueFamilyIndex)); ScopedLogger.popScope(); } + + private static void logQueueFamilyResult(String queueName, Optional queueFamilyIndex) { + if (queueFamilyIndex.isPresent()) { + ScopedLogger.log("{}: [SUPPORTED] (Index: {})", queueName, queueFamilyIndex.get()); + } else { + ScopedLogger.log("{}: [UNSUPPORTED]", queueName); + } + } } diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/utils/SuitablePhysicalDeviceFinder.java b/src/main/java/fr/mrdev023/vulkan_java/vk/utils/SuitablePhysicalDeviceFinder.java index d9830d7..829b424 100644 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/utils/SuitablePhysicalDeviceFinder.java +++ b/src/main/java/fr/mrdev023/vulkan_java/vk/utils/SuitablePhysicalDeviceFinder.java @@ -10,12 +10,13 @@ import org.lwjgl.vulkan.VK10; import fr.mrdev023.vulkan_java.vk.Instance; import fr.mrdev023.vulkan_java.vk.PhysicalDevice; import fr.mrdev023.vulkan_java.vk.VulkanError; -import fr.mrdev023.vulkan_java.vk.compatibilities.validators.PhysicalDeviceCompatibilityValidator; import fr.mrdev023.vulkan_java.vk.loggers.PhysicalDeviceCompatibilityLogger; +import fr.mrdev023.vulkan_java.vk.validators.PhysicalDeviceCompatibilityValidator; public class SuitablePhysicalDeviceFinder { - public static MatchResult findBestPhysicalDevice(Instance instance, PhysicalDeviceCompatibilityValidator validator) throws VulkanError { + public static MatchResult findBestPhysicalDevice(Instance instance, PhysicalDeviceCompatibilityValidator validator) + throws VulkanError { List matchedPhysicalDevices = new ArrayList<>(); try (MemoryStack stack = MemoryStack.stackPush()) { @@ -29,12 +30,13 @@ public class SuitablePhysicalDeviceFinder { } } - return matchedPhysicalDevices.stream().min(Comparator.comparingInt(matchResult -> getScore(matchResult))).orElse(null); + return matchedPhysicalDevices.stream().min(Comparator.comparingInt(matchResult -> getScore(matchResult))) + .orElse(null); } private static int getScore(MatchResult matchResult) { int deviceType = matchResult.physicalDevice.getVkPhysicalDeviceProperties().deviceType(); - + return switch (deviceType) { case VK10.VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU -> 0; case VK10.VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU -> 1; @@ -42,7 +44,7 @@ public class SuitablePhysicalDeviceFinder { case VK10.VK_PHYSICAL_DEVICE_TYPE_CPU -> 3; case VK10.VK_PHYSICAL_DEVICE_TYPE_OTHER -> 4; default -> 5; - }; + }; } public static class MatchResult { diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/validators/DeviceExtensionsValidator.java b/src/main/java/fr/mrdev023/vulkan_java/vk/validators/DeviceExtensionsValidator.java similarity index 90% rename from src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/validators/DeviceExtensionsValidator.java rename to src/main/java/fr/mrdev023/vulkan_java/vk/validators/DeviceExtensionsValidator.java index fd91b12..8c6d525 100644 --- a/src/main/java/fr/mrdev023/vulkan_java/vk/compatibilities/validators/DeviceExtensionsValidator.java +++ b/src/main/java/fr/mrdev023/vulkan_java/vk/validators/DeviceExtensionsValidator.java @@ -1,4 +1,4 @@ -package fr.mrdev023.vulkan_java.vk.compatibilities.validators; +package fr.mrdev023.vulkan_java.vk.validators; import java.util.HashSet; import java.util.Set; @@ -15,10 +15,12 @@ public class DeviceExtensionsValidator { /** * Validate the device extensions of the physical device. * - * Note: This method return a Result to adapt the extensions to the physical device properties after the validation. + * Note: This method return a Result to adapt the extensions to the physical + * device properties after the validation. * * @param physicalDevice The physical device to validate the extensions for. - * @return A result object containing the validation results and whether the physical device is suitable. + * @return A result object containing the validation results and whether the + * physical device is suitable. */ public Result validate(PhysicalDevice physicalDevice) { Set matchingExtensions = new HashSet<>(); diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/validators/PhysicalDeviceCompatibilityValidator.java b/src/main/java/fr/mrdev023/vulkan_java/vk/validators/PhysicalDeviceCompatibilityValidator.java new file mode 100644 index 0000000..d7a3ee2 --- /dev/null +++ b/src/main/java/fr/mrdev023/vulkan_java/vk/validators/PhysicalDeviceCompatibilityValidator.java @@ -0,0 +1,54 @@ +package fr.mrdev023.vulkan_java.vk.validators; + +import java.util.Optional; +import java.util.Set; + +import fr.mrdev023.vulkan_java.vk.PhysicalDevice; +import fr.mrdev023.vulkan_java.vk.QueueFamilyIndices; +import fr.mrdev023.vulkan_java.vk.Surface; + +public class PhysicalDeviceCompatibilityValidator { + private int requiredQueueFlags; + private Set requiredExtensions; + private final Optional surface; + + public PhysicalDeviceCompatibilityValidator(int requiredQueueFlags, Set requiredExtensions, + Optional surface) { + this.requiredQueueFlags = requiredQueueFlags; + this.requiredExtensions = requiredExtensions; + this.surface = surface; + } + + public Result validate(PhysicalDevice physicalDevice) { + var queueFamilyRequirementsResult = validateQueueFamilyRequirements(physicalDevice); + var deviceExtensionsResult = validateDeviceExtensions(physicalDevice); + + return new Result(queueFamilyRequirementsResult, deviceExtensionsResult); + } + + private Optional validateQueueFamilyRequirements(PhysicalDevice physicalDevice) { + var queueFamilyRequirementsValidator = new QueueFamilyRequirementsValidator(requiredQueueFlags, surface); + var result = queueFamilyRequirementsValidator.validate(physicalDevice); + + return result; + } + + private DeviceExtensionsValidator.Result validateDeviceExtensions(PhysicalDevice physicalDevice) { + var deviceExtensionsValidator = new DeviceExtensionsValidator(requiredExtensions); + var result = deviceExtensionsValidator.validate(physicalDevice); + return result; + } + + public static class Result { + public final boolean isSuitable; + public final Optional queueFamilyIndices; + public final DeviceExtensionsValidator.Result deviceExtensionsResult; + + public Result(Optional queueFamilyIndices, + DeviceExtensionsValidator.Result deviceExtensionsResult) { + this.isSuitable = queueFamilyIndices.isPresent() && deviceExtensionsResult.isSuitable; + this.queueFamilyIndices = queueFamilyIndices; + this.deviceExtensionsResult = deviceExtensionsResult; + } + } +} diff --git a/src/main/java/fr/mrdev023/vulkan_java/vk/validators/QueueFamilyRequirementsValidator.java b/src/main/java/fr/mrdev023/vulkan_java/vk/validators/QueueFamilyRequirementsValidator.java new file mode 100644 index 0000000..f9ffec7 --- /dev/null +++ b/src/main/java/fr/mrdev023/vulkan_java/vk/validators/QueueFamilyRequirementsValidator.java @@ -0,0 +1,87 @@ +package fr.mrdev023.vulkan_java.vk.validators; + +import java.nio.IntBuffer; +import java.util.Optional; + +import org.lwjgl.system.MemoryStack; +import org.lwjgl.vulkan.KHRSurface; +import org.lwjgl.vulkan.VK10; +import org.lwjgl.vulkan.VkQueueFamilyProperties; + +import fr.mrdev023.vulkan_java.vk.PhysicalDevice; +import fr.mrdev023.vulkan_java.vk.QueueFamilyIndices; +import fr.mrdev023.vulkan_java.vk.Surface; + +public class QueueFamilyRequirementsValidator { + private int requiredQueueFlags; + private Optional surface; + + public QueueFamilyRequirementsValidator(int requiredQueueFlags, Optional surface) { + this.requiredQueueFlags = requiredQueueFlags; + this.surface = surface; + } + + /** + * Validate the queue family requirements of the physical device. + * + * @param physicalDevice The physical device to validate the requirements for. + * @return The queue family indices if the requirements are met, otherwise an + * empty optional. + */ + public Optional validate(PhysicalDevice physicalDevice) { + var vkQueueFamilyProps = physicalDevice.getVkQueueFamilyProps(); + + var queueFamilyIndicesBuilder = new QueueFamilyIndices.Builder(); + + for (int i = 0; i < vkQueueFamilyProps.capacity(); i++) { + var vkQueueFamilyProp = vkQueueFamilyProps.get(i); + + if (hasRequiredFlag(VK10.VK_QUEUE_GRAPHICS_BIT) && queueFlagIsSupported(vkQueueFamilyProp)) { + queueFamilyIndicesBuilder.withGraphicsQueueFamilyIndex(i); + requiredQueueFlags &= ~VK10.VK_QUEUE_GRAPHICS_BIT; // Consume the flag + } + + if (hasRequiredFlag(VK10.VK_QUEUE_COMPUTE_BIT) && queueFlagIsSupported(vkQueueFamilyProp)) { + queueFamilyIndicesBuilder.withComputeQueueFamilyIndex(i); + requiredQueueFlags &= ~VK10.VK_QUEUE_COMPUTE_BIT; // Consume the flag + } + + if (hasRequiredFlag(VK10.VK_QUEUE_TRANSFER_BIT) && queueFlagIsSupported(vkQueueFamilyProp)) { + queueFamilyIndicesBuilder.withTransferQueueFamilyIndex(i); + requiredQueueFlags &= ~VK10.VK_QUEUE_TRANSFER_BIT; // Consume the flag + } + + if (surface.isPresent() && isSurfaceSupported(surface.get(), physicalDevice, i)) { + queueFamilyIndicesBuilder.withPresentQueueFamilyIndex(i); + surface = Optional.empty(); // Consume the surface + } + + if (requiredQueueFlags == 0 && surface.isEmpty()) { + break; + } + } + + if (requiredQueueFlags == 0 && surface.isEmpty()) { + return Optional.of(queueFamilyIndicesBuilder.build()); + } + + return Optional.empty(); + } + + private boolean queueFlagIsSupported(VkQueueFamilyProperties vkQueueFamilyProp) { + return (vkQueueFamilyProp.queueFlags() & requiredQueueFlags) != 0; + } + + private boolean isSurfaceSupported(Surface surface, PhysicalDevice physicalDevice, int queueFamilyIndex) { + try (MemoryStack stack = MemoryStack.stackPush()) { + IntBuffer presentSupport = stack.ints(VK10.VK_FALSE); + KHRSurface.vkGetPhysicalDeviceSurfaceSupportKHR(physicalDevice.getVkPhysicalDevice(), queueFamilyIndex, + surface.getVkSurface(), presentSupport); + return presentSupport.get(0) == VK10.VK_TRUE; + } + } + + private boolean hasRequiredFlag(int flag) { + return (requiredQueueFlags & flag) != 0; + } +}