diff --git a/src/main/java/net/vulkanmod/vulkan/Vulkan.java b/src/main/java/net/vulkanmod/vulkan/Vulkan.java index cec7af77e..447c640ac 100644 --- a/src/main/java/net/vulkanmod/vulkan/Vulkan.java +++ b/src/main/java/net/vulkanmod/vulkan/Vulkan.java @@ -137,6 +137,7 @@ public static long getAllocator() { private static final StagingBuffers stagingBuffers = new StagingBuffers(); public static boolean use24BitsDepthFormat = true; + public static boolean surfaceCapabilities2Supported = false; private static int DEFAULT_DEPTH_FORMAT = 0; public static void initVulkan(long window) { @@ -203,6 +204,7 @@ private static void createInstance() { } try (MemoryStack stack = stackPush()) { + checkSurfaceCapabilities2Support(stack); // Use calloc to initialize the structs with 0s. Otherwise, the program can crash due to random values @@ -357,18 +359,48 @@ private static void createCommandPool() { } } + private static void checkSurfaceCapabilities2Support(MemoryStack stack) { + if (org.lwjgl.system.Platform.get() != org.lwjgl.system.Platform.WINDOWS) { + return; + } + + IntBuffer propertyCount = stack.ints(0); + vkEnumerateInstanceExtensionProperties((String) null, propertyCount, null); + + if (propertyCount.get(0) == 0) { + return; + } + + VkExtensionProperties.Buffer availableExtensions = VkExtensionProperties.malloc(propertyCount.get(0), stack); + vkEnumerateInstanceExtensionProperties((String) null, propertyCount, availableExtensions); + + Set availableExtensionNames = availableExtensions.stream() + .map(VkExtensionProperties::extensionNameString) + .collect(toSet()); + + if (availableExtensionNames.contains(KHRGetSurfaceCapabilities2.VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME)) { + surfaceCapabilities2Supported = true; + } + } + private static PointerBuffer getRequiredInstanceExtensions() { PointerBuffer glfwExtensions = glfwGetRequiredInstanceExtensions(); - if (ENABLE_VALIDATION_LAYERS) { + int extraCount = (ENABLE_VALIDATION_LAYERS ? 1 : 0) + (surfaceCapabilities2Supported ? 1 : 0); + if (extraCount > 0) { MemoryStack stack = stackGet(); - PointerBuffer extensions = stack.mallocPointer(glfwExtensions.capacity() + 1); + PointerBuffer extensions = stack.mallocPointer(glfwExtensions.capacity() + extraCount); extensions.put(glfwExtensions); - extensions.put(stack.UTF8(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)); + if (ENABLE_VALIDATION_LAYERS) { + extensions.put(stack.UTF8(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)); + } + if (surfaceCapabilities2Supported) { + extensions.put(stack.UTF8(KHRGetSurfaceCapabilities2.VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME)); + } // Rewind the buffer before returning it to reset its position back to 0 return extensions.rewind(); diff --git a/src/main/java/net/vulkanmod/vulkan/device/DeviceManager.java b/src/main/java/net/vulkanmod/vulkan/device/DeviceManager.java index 39a8ccef8..6c0cc95f6 100644 --- a/src/main/java/net/vulkanmod/vulkan/device/DeviceManager.java +++ b/src/main/java/net/vulkanmod/vulkan/device/DeviceManager.java @@ -12,6 +12,7 @@ import java.nio.IntBuffer; import java.util.ArrayList; import java.util.List; +import java.util.Set; import static java.util.stream.Collectors.toSet; import static net.vulkanmod.vulkan.queue.Queue.findQueueFamilies; @@ -37,6 +38,7 @@ public abstract class DeviceManager { public static VkPhysicalDeviceMemoryProperties memoryProperties; public static SurfaceProperties surfaceProperties; + public static boolean fullScreenExclusiveControl = false; static GraphicsQueue graphicsQueue; static PresentQueue presentQueue; @@ -209,7 +211,21 @@ public static void createLogicalDevice() { // deviceVulkan13Features.pNext(deviceVulkan11Features.address()); } - createInfo.ppEnabledExtensionNames(asPointerBuffer(Vulkan.REQUIRED_EXTENSION)); + fullScreenExclusiveControl = false; + List enabledExtensions = new ArrayList<>(Vulkan.REQUIRED_EXTENSION); + if (Vulkan.surfaceCapabilities2Supported) { + Set availableExtensions = getAvailableExtension(stack, physicalDevice).stream() + .map(VkExtensionProperties::extensionNameString) + .collect(toSet()); + + if (availableExtensions.contains(EXTFullScreenExclusive.VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME)) { + enabledExtensions.add(EXTFullScreenExclusive.VK_EXT_FULL_SCREEN_EXCLUSIVE_EXTENSION_NAME); + fullScreenExclusiveControl = true; + Initializer.LOGGER.info("VK_EXT_full_screen_exclusive enabled: opting out of full screen exclusive control"); + } + } + + createInfo.ppEnabledExtensionNames(asPointerBuffer(enabledExtensions)); // Configuration.DEBUG_FUNCTIONS.set(true); diff --git a/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java b/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java index ef7191c1c..e0dab5173 100644 --- a/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java +++ b/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java @@ -127,6 +127,13 @@ private void createSwapChain() { createInfo.presentMode(presentMode); createInfo.clipped(true); + if (DeviceManager.fullScreenExclusiveControl) { + VkSurfaceFullScreenExclusiveInfoEXT fullScreenExclusiveInfo = VkSurfaceFullScreenExclusiveInfoEXT.calloc(stack); + fullScreenExclusiveInfo.sType(EXTFullScreenExclusive.VK_STRUCTURE_TYPE_SURFACE_FULL_SCREEN_EXCLUSIVE_INFO_EXT); + fullScreenExclusiveInfo.fullScreenExclusive(EXTFullScreenExclusive.VK_FULL_SCREEN_EXCLUSIVE_DISALLOWED_EXT); + createInfo.pNext(fullScreenExclusiveInfo.address()); + } + if (this.swapChainId != VK_NULL_HANDLE) { this.swapChainImages.forEach(image -> vkDestroyImageView(device, image.getImageView(), null)); vkDestroySwapchainKHR(device, this.swapChainId, null);