Refactor
This commit is contained in:
parent
0e181376b4
commit
3749af2c5c
20 changed files with 385 additions and 378 deletions
|
@ -1,25 +1,30 @@
|
||||||
package fr.mrdev023.vulkan_java.vk;
|
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.PointerBuffer;
|
||||||
import org.lwjgl.system.MemoryStack;
|
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 org.tinylog.Logger;
|
||||||
|
|
||||||
import fr.mrdev023.vulkan_java.vk.utils.SuitablePhysicalDeviceFinder;
|
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 {
|
public class Device {
|
||||||
|
|
||||||
private final PhysicalDevice physicalDevice;
|
private final PhysicalDevice physicalDevice;
|
||||||
private final VkDevice vkDevice;
|
private final VkDevice vkDevice;
|
||||||
private final Queue.PresentQueue presentQueue;
|
private final Optional<Queue> presentQueue;
|
||||||
private final Queue.GraphicsQueue graphicsQueue;
|
private final Optional<Queue> graphicsQueue;
|
||||||
private final Queue.ComputeQueue computeQueue;
|
private final Optional<Queue> computeQueue;
|
||||||
private final Queue.TransferQueue transferQueue;
|
private final Optional<Queue> transferQueue;
|
||||||
|
|
||||||
public Device(SuitablePhysicalDeviceFinder.MatchResult physicalDeviceMatch) throws VulkanError {
|
public Device(SuitablePhysicalDeviceFinder.MatchResult physicalDeviceMatch) throws VulkanError {
|
||||||
this.physicalDevice = physicalDeviceMatch.physicalDevice;
|
this.physicalDevice = physicalDeviceMatch.physicalDevice;
|
||||||
|
@ -36,17 +41,9 @@ public class Device {
|
||||||
VkPhysicalDeviceFeatures features = VkPhysicalDeviceFeatures.calloc(stack);
|
VkPhysicalDeviceFeatures features = VkPhysicalDeviceFeatures.calloc(stack);
|
||||||
|
|
||||||
// Enable all the queue families
|
// Enable all the queue families
|
||||||
VkQueueFamilyProperties.Buffer queuePropsBuff = physicalDevice.getVkQueueFamilyProps();
|
var queueFamilyIndices = physicalDeviceMatch.validatorResult.queueFamilyIndices.orElseThrow();
|
||||||
int numQueuesFamilies = queuePropsBuff.capacity();
|
var queuesCreator = new QueuesCreator(queueFamilyIndices);
|
||||||
VkDeviceQueueCreateInfo.Buffer queueCreationInfoBuf = VkDeviceQueueCreateInfo.calloc(numQueuesFamilies,
|
var queueCreationInfoBuf = queuesCreator.createQueueCreateInfos(stack, physicalDevice);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.calloc(stack)
|
VkDeviceCreateInfo deviceCreateInfo = VkDeviceCreateInfo.calloc(stack)
|
||||||
.sType(VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO)
|
.sType(VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO)
|
||||||
|
@ -59,16 +56,14 @@ public class Device {
|
||||||
"Failed to create device");
|
"Failed to create device");
|
||||||
vkDevice = new VkDevice(pp.get(0), physicalDevice.getVkPhysicalDevice(), deviceCreateInfo);
|
vkDevice = new VkDevice(pp.get(0), physicalDevice.getVkPhysicalDevice(), deviceCreateInfo);
|
||||||
|
|
||||||
// graphicsQueue = new Queue.GraphicsQueue(this,
|
graphicsQueue = queueFamilyIndices.getGraphicsQueueFamilyIndex()
|
||||||
// physicalDeviceMatch.graphicsQueueFamilyIndex, 0);
|
.flatMap(queueFamilyIndex -> Optional.of(queuesCreator.createQueue(this, queueFamilyIndex)));
|
||||||
// computeQueue = new Queue.ComputeQueue(this,
|
presentQueue = queueFamilyIndices.getPresentQueueFamilyIndex()
|
||||||
// physicalDeviceMatch.computeQueueFamilyIndex, 1);
|
.flatMap(queueFamilyIndex -> Optional.of(queuesCreator.createQueue(this, queueFamilyIndex)));
|
||||||
// transferQueue = new Queue.TransferQueue(this,
|
computeQueue = queueFamilyIndices.getComputeQueueFamilyIndex()
|
||||||
// physicalDeviceMatch.transferQueueFamilyIndex, 2);
|
.flatMap(queueFamilyIndex -> Optional.of(queuesCreator.createQueue(this, queueFamilyIndex)));
|
||||||
presentQueue = null;
|
transferQueue = queueFamilyIndices.getTransferQueueFamilyIndex()
|
||||||
graphicsQueue = null;
|
.flatMap(queueFamilyIndex -> Optional.of(queuesCreator.createQueue(this, queueFamilyIndex)));
|
||||||
computeQueue = null;
|
|
||||||
transferQueue = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.debug("Vulkan device created");
|
Logger.debug("Vulkan device created");
|
||||||
|
@ -91,19 +86,19 @@ public class Device {
|
||||||
vkDeviceWaitIdle(vkDevice);
|
vkDeviceWaitIdle(vkDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Queue.PresentQueue getPresentQueue() {
|
public Optional<Queue> getPresentQueue() {
|
||||||
return presentQueue;
|
return presentQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Queue.GraphicsQueue getGraphicsQueue() {
|
public Optional<Queue> getGraphicsQueue() {
|
||||||
return graphicsQueue;
|
return graphicsQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Queue.ComputeQueue getComputeQueue() {
|
public Optional<Queue> getComputeQueue() {
|
||||||
return computeQueue;
|
return computeQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Queue.TransferQueue getTransferQueue() {
|
public Optional<Queue> getTransferQueue() {
|
||||||
return transferQueue;
|
return transferQueue;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -21,27 +21,15 @@ public class PhysicalDevice {
|
||||||
private final VkQueueFamilyProperties.Buffer vkQueueFamilyProps;
|
private final VkQueueFamilyProperties.Buffer vkQueueFamilyProps;
|
||||||
|
|
||||||
private PhysicalDevice(VkPhysicalDevice vkPhysicalDevice) throws VulkanError {
|
private PhysicalDevice(VkPhysicalDevice vkPhysicalDevice) throws VulkanError {
|
||||||
|
this.vkPhysicalDevice = vkPhysicalDevice;
|
||||||
|
|
||||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||||
this.vkPhysicalDevice = vkPhysicalDevice;
|
|
||||||
|
|
||||||
IntBuffer intBuffer = stack.mallocInt(1);
|
|
||||||
|
|
||||||
// Get device properties
|
// Get device properties
|
||||||
vkPhysicalDeviceProperties = VkPhysicalDeviceProperties.calloc();
|
vkPhysicalDeviceProperties = VkPhysicalDeviceProperties.calloc();
|
||||||
vkGetPhysicalDeviceProperties(vkPhysicalDevice, vkPhysicalDeviceProperties);
|
vkGetPhysicalDeviceProperties(vkPhysicalDevice, vkPhysicalDeviceProperties);
|
||||||
|
|
||||||
// Get device extensions
|
vkDeviceExtensions = getVulkanPhysicalDeviceExtensions(stack, vkPhysicalDevice);
|
||||||
vkCheck(vkEnumerateDeviceExtensionProperties(vkPhysicalDevice, (String) null, intBuffer, null),
|
vkQueueFamilyProps = getVulkanQueueFamilyProperties(stack, vkPhysicalDevice);
|
||||||
"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);
|
|
||||||
|
|
||||||
vkPhysicalDeviceFeatures = VkPhysicalDeviceFeatures.calloc();
|
vkPhysicalDeviceFeatures = VkPhysicalDeviceFeatures.calloc();
|
||||||
vkGetPhysicalDeviceFeatures(vkPhysicalDevice, vkPhysicalDeviceFeatures);
|
vkGetPhysicalDeviceFeatures(vkPhysicalDevice, vkPhysicalDeviceFeatures);
|
||||||
|
@ -113,4 +101,31 @@ public class PhysicalDevice {
|
||||||
public VkExtensionProperties.Buffer getVkDeviceExtensions() {
|
public VkExtensionProperties.Buffer getVkDeviceExtensions() {
|
||||||
return vkDeviceExtensions;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -29,28 +29,4 @@ public class Queue {
|
||||||
public void waitIdle() {
|
public void waitIdle() {
|
||||||
vkQueueWaitIdle(vkQueue);
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package fr.mrdev023.vulkan_java.vk;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class QueueFamilyIndices {
|
||||||
|
private final Optional<Integer> graphicsQueueFamilyIndex;
|
||||||
|
private final Optional<Integer> computeQueueFamilyIndex;
|
||||||
|
private final Optional<Integer> transferQueueFamilyIndex;
|
||||||
|
private final Optional<Integer> presentQueueFamilyIndex;
|
||||||
|
|
||||||
|
public QueueFamilyIndices(Optional<Integer> graphicsQueueFamilyIndex, Optional<Integer> computeQueueFamilyIndex,
|
||||||
|
Optional<Integer> transferQueueFamilyIndex, Optional<Integer> presentQueueFamilyIndex) {
|
||||||
|
this.graphicsQueueFamilyIndex = graphicsQueueFamilyIndex;
|
||||||
|
this.computeQueueFamilyIndex = computeQueueFamilyIndex;
|
||||||
|
this.transferQueueFamilyIndex = transferQueueFamilyIndex;
|
||||||
|
this.presentQueueFamilyIndex = presentQueueFamilyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Integer> getGraphicsQueueFamilyIndex() {
|
||||||
|
return graphicsQueueFamilyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Integer> getComputeQueueFamilyIndex() {
|
||||||
|
return computeQueueFamilyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Integer> getTransferQueueFamilyIndex() {
|
||||||
|
return transferQueueFamilyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<Integer> getPresentQueueFamilyIndex() {
|
||||||
|
return presentQueueFamilyIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
private Optional<Integer> graphicsQueueFamilyIndex;
|
||||||
|
private Optional<Integer> computeQueueFamilyIndex;
|
||||||
|
private Optional<Integer> transferQueueFamilyIndex;
|
||||||
|
private Optional<Integer> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
76
src/main/java/fr/mrdev023/vulkan_java/vk/QueuesCreator.java
Normal file
76
src/main/java/fr/mrdev023/vulkan_java/vk/QueuesCreator.java
Normal file
|
@ -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<Integer, Integer> families;
|
||||||
|
private HashMap<Integer, Integer> 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<Integer, Integer> createFamilies(QueueFamilyIndices queueFamilyIndices) {
|
||||||
|
var families = new HashMap<Integer, Integer>();
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,8 +1,6 @@
|
||||||
package fr.mrdev023.vulkan_java.vk;
|
package fr.mrdev023.vulkan_java.vk;
|
||||||
|
|
||||||
import fr.mrdev023.vulkan_java.vk.compatibilities.validators.PhysicalDeviceCompatibilityValidator;
|
import static org.lwjgl.glfw.GLFWVulkan.glfwVulkanSupported;
|
||||||
import fr.mrdev023.vulkan_java.vk.utils.SuitablePhysicalDeviceFinder;
|
|
||||||
import fr.mrdev023.vulkan_java.window.Display;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -12,7 +10,9 @@ import org.lwjgl.vulkan.KHRPortabilitySubset;
|
||||||
import org.lwjgl.vulkan.KHRSwapchain;
|
import org.lwjgl.vulkan.KHRSwapchain;
|
||||||
import org.lwjgl.vulkan.VK10;
|
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 {
|
public class Vulkan {
|
||||||
|
|
||||||
|
|
|
@ -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<Integer> getQueueFlag() {
|
|
||||||
return Optional.of(VK10.VK_QUEUE_COMPUTE_BIT);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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<Integer> getQueueFlag() {
|
|
||||||
return Optional.of(VK10.VK_QUEUE_GRAPHICS_BIT);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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<Integer> getQueueFlag();
|
|
||||||
}
|
|
|
@ -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<Integer> getQueueFlag() {
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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<Integer> getQueueFlag() {
|
|
||||||
return Optional.of(VK10.VK_QUEUE_TRANSFER_BIT);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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<String> requiredExtensions;
|
|
||||||
private final Optional<Surface> surface;
|
|
||||||
|
|
||||||
public PhysicalDeviceCompatibilityValidator(int requiredQueueFlags, Set<String> requiredExtensions, Optional<Surface> 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<IQueueFamilyRequirement>();
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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<IQueueFamilyRequirement> requirements;
|
|
||||||
|
|
||||||
public QueueFamilyRequirementsValidator(List<IQueueFamilyRequirement> requirements) {
|
|
||||||
this.requirements = requirements;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validate the queue family requirements of the physical device.
|
|
||||||
*
|
|
||||||
* <i>Note: This method return a Result to adapt the requirements to the
|
|
||||||
* physical device properties after the validation.</i>
|
|
||||||
*
|
|
||||||
* @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<IQueueFamilyRequirement, Optional<Integer>> 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<IQueueFamilyRequirement, Optional<Integer>> queueFamilyIndices;
|
|
||||||
public final boolean isSuitable;
|
|
||||||
|
|
||||||
public Result(HashMap<IQueueFamilyRequirement, Optional<Integer>> queueFamilyIndices, boolean isSuitable) {
|
|
||||||
this.queueFamilyIndices = queueFamilyIndices;
|
|
||||||
this.isSuitable = isSuitable;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
package fr.mrdev023.vulkan_java.vk.loggers;
|
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 class DeviceExtensionsResultLogger {
|
||||||
public static void log(DeviceExtensionsValidator.Result result) {
|
public static void log(DeviceExtensionsValidator.Result result) {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
package fr.mrdev023.vulkan_java.vk.loggers;
|
package fr.mrdev023.vulkan_java.vk.loggers;
|
||||||
|
|
||||||
import fr.mrdev023.vulkan_java.vk.PhysicalDevice;
|
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 class PhysicalDeviceCompatibilityLogger {
|
||||||
public static void log(PhysicalDevice physicalDevice, PhysicalDeviceCompatibilityValidator.Result result) {
|
public static void log(PhysicalDevice physicalDevice, PhysicalDeviceCompatibilityValidator.Result result) {
|
||||||
ScopedLogger.pushScope("Physical device support (Is suitable: {})", result.isSuitable);
|
ScopedLogger.pushScope("Physical device support (Is suitable: {})", result.isSuitable);
|
||||||
PhysicalDevicePropertiesLogger.log(physicalDevice);
|
PhysicalDevicePropertiesLogger.log(physicalDevice);
|
||||||
QueueFamilyRequirementResultLogger.log(result.queueFamilyRequirementsResult);
|
QueueFamilyRequirementResultLogger.log(result.queueFamilyIndices);
|
||||||
DeviceExtensionsResultLogger.log(result.deviceExtensionsResult);
|
DeviceExtensionsResultLogger.log(result.deviceExtensionsResult);
|
||||||
ScopedLogger.popScope();
|
ScopedLogger.popScope();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,28 @@
|
||||||
package fr.mrdev023.vulkan_java.vk.loggers;
|
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 class QueueFamilyRequirementResultLogger {
|
||||||
public static void log(QueueFamilyRequirementsValidator.Result result) {
|
public static void log(Optional<QueueFamilyIndices> queueFamilyIndices) {
|
||||||
ScopedLogger.pushScope("Queue Family Requirements (Is suitable: {})", result.isSuitable);
|
ScopedLogger.pushScope("Queue Family Requirements (Is suitable: {})", queueFamilyIndices.isPresent());
|
||||||
result.queueFamilyIndices.forEach((requirement, index) -> {
|
logQueueFamilyResult("Graphics Queue",
|
||||||
if (index.isPresent()) {
|
queueFamilyIndices.flatMap(QueueFamilyIndices::getGraphicsQueueFamilyIndex));
|
||||||
ScopedLogger.log("{}: [SUPPORTED]", requirement.getName());
|
logQueueFamilyResult("Compute Queue",
|
||||||
} else {
|
queueFamilyIndices.flatMap(QueueFamilyIndices::getComputeQueueFamilyIndex));
|
||||||
ScopedLogger.log("{}: [UNSUPPORTED]", requirement.getName(), requirement.getQueueFlag().orElse(null));
|
logQueueFamilyResult("Transfer Queue",
|
||||||
}
|
queueFamilyIndices.flatMap(QueueFamilyIndices::getTransferQueueFamilyIndex));
|
||||||
});
|
logQueueFamilyResult("Present Queue",
|
||||||
|
queueFamilyIndices.flatMap(QueueFamilyIndices::getPresentQueueFamilyIndex));
|
||||||
ScopedLogger.popScope();
|
ScopedLogger.popScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void logQueueFamilyResult(String queueName, Optional<Integer> queueFamilyIndex) {
|
||||||
|
if (queueFamilyIndex.isPresent()) {
|
||||||
|
ScopedLogger.log("{}: [SUPPORTED] (Index: {})", queueName, queueFamilyIndex.get());
|
||||||
|
} else {
|
||||||
|
ScopedLogger.log("{}: [UNSUPPORTED]", queueName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,12 +10,13 @@ import org.lwjgl.vulkan.VK10;
|
||||||
import fr.mrdev023.vulkan_java.vk.Instance;
|
import fr.mrdev023.vulkan_java.vk.Instance;
|
||||||
import fr.mrdev023.vulkan_java.vk.PhysicalDevice;
|
import fr.mrdev023.vulkan_java.vk.PhysicalDevice;
|
||||||
import fr.mrdev023.vulkan_java.vk.VulkanError;
|
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.loggers.PhysicalDeviceCompatibilityLogger;
|
||||||
|
import fr.mrdev023.vulkan_java.vk.validators.PhysicalDeviceCompatibilityValidator;
|
||||||
|
|
||||||
public class SuitablePhysicalDeviceFinder {
|
public class SuitablePhysicalDeviceFinder {
|
||||||
|
|
||||||
public static MatchResult findBestPhysicalDevice(Instance instance, PhysicalDeviceCompatibilityValidator validator) throws VulkanError {
|
public static MatchResult findBestPhysicalDevice(Instance instance, PhysicalDeviceCompatibilityValidator validator)
|
||||||
|
throws VulkanError {
|
||||||
List<MatchResult> matchedPhysicalDevices = new ArrayList<>();
|
List<MatchResult> matchedPhysicalDevices = new ArrayList<>();
|
||||||
|
|
||||||
try (MemoryStack stack = MemoryStack.stackPush()) {
|
try (MemoryStack stack = MemoryStack.stackPush()) {
|
||||||
|
@ -29,7 +30,8 @@ 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) {
|
private static int getScore(MatchResult matchResult) {
|
||||||
|
|
|
@ -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.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -15,10 +15,12 @@ public class DeviceExtensionsValidator {
|
||||||
/**
|
/**
|
||||||
* Validate the device extensions of the physical device.
|
* Validate the device extensions of the physical device.
|
||||||
*
|
*
|
||||||
* <i>Note: This method return a Result to adapt the extensions to the physical device properties after the validation.</i>
|
* <i>Note: This method return a Result to adapt the extensions to the physical
|
||||||
|
* device properties after the validation.</i>
|
||||||
*
|
*
|
||||||
* @param physicalDevice The physical device to validate the extensions for.
|
* @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) {
|
public Result validate(PhysicalDevice physicalDevice) {
|
||||||
Set<String> matchingExtensions = new HashSet<>();
|
Set<String> matchingExtensions = new HashSet<>();
|
|
@ -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<String> requiredExtensions;
|
||||||
|
private final Optional<Surface> surface;
|
||||||
|
|
||||||
|
public PhysicalDeviceCompatibilityValidator(int requiredQueueFlags, Set<String> requiredExtensions,
|
||||||
|
Optional<Surface> 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<QueueFamilyIndices> 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> queueFamilyIndices;
|
||||||
|
public final DeviceExtensionsValidator.Result deviceExtensionsResult;
|
||||||
|
|
||||||
|
public Result(Optional<QueueFamilyIndices> queueFamilyIndices,
|
||||||
|
DeviceExtensionsValidator.Result deviceExtensionsResult) {
|
||||||
|
this.isSuitable = queueFamilyIndices.isPresent() && deviceExtensionsResult.isSuitable;
|
||||||
|
this.queueFamilyIndices = queueFamilyIndices;
|
||||||
|
this.deviceExtensionsResult = deviceExtensionsResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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> surface;
|
||||||
|
|
||||||
|
public QueueFamilyRequirementsValidator(int requiredQueueFlags, Optional<Surface> 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<QueueFamilyIndices> 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;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue