From f409c8b649b6105f344d34782a8f97f763731039 Mon Sep 17 00:00:00 2001 From: TNTpower0v0 Date: Tue, 27 Jan 2026 21:12:54 +0300 Subject: [PATCH 1/2] Enable VK_EXT_swapchain_colorspace and fix Display P3 color space for macOS --- .../vulkanmod/mixin/window/WindowMixin.java | 9 +++++++++ src/main/java/net/vulkanmod/vulkan/Vulkan.java | 17 ++++++++--------- .../vulkan/framebuffer/SwapChain.java | 18 +++++++++++++++++- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/main/java/net/vulkanmod/mixin/window/WindowMixin.java b/src/main/java/net/vulkanmod/mixin/window/WindowMixin.java index 4827f9043..a10b949da 100644 --- a/src/main/java/net/vulkanmod/mixin/window/WindowMixin.java +++ b/src/main/java/net/vulkanmod/mixin/window/WindowMixin.java @@ -61,6 +61,15 @@ private void redirect(int hint, int value) { } private void vulkanHint(WindowEventHandler windowEventHandler, ScreenManager screenManager, DisplayData displayData, String string, String string2, CallbackInfo ci) { GLFW.glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); + // Enable 32bit P3 wide color gamut on macOS + if (Platform.isMacOS()) { + GLFW.glfwWindowHint(GLFW_COCOA_RETINA_FRAMEBUFFER, GLFW_TRUE); + GLFW.glfwWindowHint(GLFW_RED_BITS, 10); + GLFW.glfwWindowHint(GLFW_GREEN_BITS, 10); + GLFW.glfwWindowHint(GLFW_BLUE_BITS, 10); + GLFW.glfwWindowHint(GLFW_ALPHA_BITS, 2); + } + //Fix Gnome Client-Side Decorators boolean b = (Platform.isGnome() | Platform.isWeston() | Platform.isGeneric()) && Platform.isWayLand(); GLFW.glfwWindowHint(GLFW_DECORATED, (b ? GLFW_FALSE : GLFW_TRUE)); diff --git a/src/main/java/net/vulkanmod/vulkan/Vulkan.java b/src/main/java/net/vulkanmod/vulkan/Vulkan.java index f2f0a1646..a8bebc386 100644 --- a/src/main/java/net/vulkanmod/vulkan/Vulkan.java +++ b/src/main/java/net/vulkanmod/vulkan/Vulkan.java @@ -13,6 +13,7 @@ import net.vulkanmod.vulkan.util.VkResult; import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; +import static org.lwjgl.vulkan.EXTSwapchainColorspace.VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME; import org.lwjgl.util.vma.VmaAllocatorCreateInfo; import org.lwjgl.util.vma.VmaVulkanFunctions; import org.lwjgl.vulkan.*; @@ -361,23 +362,21 @@ private static void createCommandPool() { } private static PointerBuffer getRequiredInstanceExtensions() { - PointerBuffer glfwExtensions = glfwGetRequiredInstanceExtensions(); + MemoryStack stack = stackGet(); if (ENABLE_VALIDATION_LAYERS) { - - MemoryStack stack = stackGet(); - - PointerBuffer extensions = stack.mallocPointer(glfwExtensions.capacity() + 1); - + PointerBuffer extensions = stack.mallocPointer(glfwExtensions.capacity() + 2); extensions.put(glfwExtensions); extensions.put(stack.UTF8(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)); - - // Rewind the buffer before returning it to reset its position back to 0 + extensions.put(stack.UTF8(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME)); return extensions.rewind(); } - return glfwExtensions; + PointerBuffer extensions = stack.mallocPointer(glfwExtensions.capacity() + 1); + extensions.put(glfwExtensions); + extensions.put(stack.UTF8(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME)); + return extensions.rewind(); } public static void checkResult(int result, String errorMessage) { diff --git a/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java b/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java index 9fe29eec7..f1202c7a4 100644 --- a/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java +++ b/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java @@ -9,6 +9,7 @@ import net.vulkanmod.vulkan.queue.Queue; import net.vulkanmod.vulkan.texture.SamplerManager; import net.vulkanmod.vulkan.texture.VulkanImage; +import net.vulkanmod.config.Platform; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.*; @@ -24,6 +25,7 @@ import static org.lwjgl.glfw.GLFW.glfwGetFramebufferSize; import static org.lwjgl.system.MemoryStack.stackGet; import static org.lwjgl.system.MemoryStack.stackPush; +import static org.lwjgl.vulkan.EXTSwapchainColorspace.*; import static org.lwjgl.vulkan.KHRSurface.*; import static org.lwjgl.vulkan.KHRSwapchain.*; import static org.lwjgl.vulkan.VK10.*; @@ -243,12 +245,25 @@ public long getImageView(int i) { private VkSurfaceFormatKHR getFormat(VkSurfaceFormatKHR.Buffer availableFormats) { List list = availableFormats.stream().toList(); - VkSurfaceFormatKHR format = list.get(0); + // Extended sRGB (P3 gamut with sRGB gamma) on macOS + if (Platform.isMacOS()) { + for (VkSurfaceFormatKHR f : list) { + if (f.format() == VK_FORMAT_B8G8R8A8_UNORM && f.colorSpace() == VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT) { + isBGRAformat = true; + return f; + } + } + } + // If fail try RGBA format with standard sRGB for (VkSurfaceFormatKHR availableFormat : list) { if (availableFormat.format() == VK_FORMAT_R8G8B8A8_UNORM && availableFormat.colorSpace() == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) return availableFormat; + } + // Standard BGRA sRGB + VkSurfaceFormatKHR format = list.get(0); + for (VkSurfaceFormatKHR availableFormat : list) { if (availableFormat.format() == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace() == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { format = availableFormat; } @@ -256,6 +271,7 @@ private VkSurfaceFormatKHR getFormat(VkSurfaceFormatKHR.Buffer availableFormats) if (format.format() == VK_FORMAT_B8G8R8A8_UNORM) isBGRAformat = true; + return format; } From a479e87c69f34d576dbe27b31148276783aa6276 Mon Sep 17 00:00:00 2001 From: xCollateral <103696619+xCollateral@users.noreply.github.com> Date: Wed, 28 Jan 2026 16:47:13 +0100 Subject: [PATCH 2/2] Add check for VK_EXT_swapchain_colorspace extension support - refactor init --- .../java/net/vulkanmod/vulkan/Vulkan.java | 80 +++++++++------ .../net/vulkanmod/vulkan/device/Device.java | 97 +++++++++---------- .../vulkan/device/DeviceManager.java | 29 +++--- .../vulkan/framebuffer/SwapChain.java | 35 ++++--- 4 files changed, 126 insertions(+), 115 deletions(-) diff --git a/src/main/java/net/vulkanmod/vulkan/Vulkan.java b/src/main/java/net/vulkanmod/vulkan/Vulkan.java index a8bebc386..8d457a4bc 100644 --- a/src/main/java/net/vulkanmod/vulkan/Vulkan.java +++ b/src/main/java/net/vulkanmod/vulkan/Vulkan.java @@ -110,19 +110,11 @@ private static void destroyDebugUtilsMessengerEXT(VkInstance instance, long debu } - public static VkDevice getVkDevice() { - return DeviceManager.vkDevice; - } - - public static long getAllocator() { - return allocator; - } - public static long window; - private static VkInstance instance; private static long debugMessenger; private static long surface; + private static List supportedInstanceExtensions; private static long commandPool; private static VkCommandBuffer immediateCmdBuffer; @@ -132,6 +124,7 @@ public static long getAllocator() { private static StagingBuffer[] stagingBuffers; + private static boolean colorSpaceExtSupport; public static boolean use24BitsDepthFormat = true; private static int DEFAULT_DEPTH_FORMAT = 0; @@ -201,17 +194,16 @@ private static void freeStagingBuffers() { } private static void createInstance() { - if (ENABLE_VALIDATION_LAYERS && !checkValidationLayerSupport()) { throw new RuntimeException("Validation requested but not supported"); } - try (MemoryStack stack = stackPush()) { + supportedInstanceExtensions = getAvailableInstanceExtension(); + colorSpaceExtSupport = supportedInstanceExtensions.contains(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME); + try (MemoryStack stack = stackPush()) { // Use calloc to initialize the structs with 0s. Otherwise, the program can crash due to random values - VkApplicationInfo appInfo = VkApplicationInfo.calloc(stack); - appInfo.sType(VK_STRUCTURE_TYPE_APPLICATION_INFO); appInfo.pApplicationName(stack.UTF8Safe("VulkanMod")); appInfo.applicationVersion(VK_MAKE_VERSION(1, 0, 0)); @@ -220,13 +212,11 @@ private static void createInstance() { appInfo.apiVersion(VK_API_VERSION_1_2); VkInstanceCreateInfo createInfo = VkInstanceCreateInfo.calloc(stack); - createInfo.sType(VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO); createInfo.pApplicationInfo(appInfo); createInfo.ppEnabledExtensionNames(getRequiredInstanceExtensions()); if (ENABLE_VALIDATION_LAYERS) { - createInfo.ppEnabledLayerNames(asPointerBuffer(VALIDATION_LAYERS)); VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo = VkDebugUtilsMessengerCreateInfoEXT.calloc(stack); @@ -245,9 +235,7 @@ private static void createInstance() { } static boolean checkValidationLayerSupport() { - try (MemoryStack stack = stackPush()) { - IntBuffer layerCount = stack.ints(0); vkEnumerateInstanceLayerProperties(layerCount, null); @@ -274,13 +262,11 @@ private static void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreate } private static void setupDebugMessenger() { - if (!ENABLE_VALIDATION_LAYERS) { return; } try (MemoryStack stack = stackPush()) { - VkDebugUtilsMessengerCreateInfoEXT createInfo = VkDebugUtilsMessengerCreateInfoEXT.calloc(stack); populateDebugMessengerCreateInfo(createInfo); @@ -309,7 +295,6 @@ private static void createSurface(long handle) { window = handle; try (MemoryStack stack = stackPush()) { - LongBuffer pSurface = stack.longs(VK_NULL_HANDLE); checkResult(glfwCreateWindowSurface(instance, window, null, pSurface), @@ -321,7 +306,6 @@ private static void createSurface(long handle) { private static void createVma() { try (MemoryStack stack = stackPush()) { - VmaVulkanFunctions vulkanFunctions = VmaVulkanFunctions.calloc(stack); vulkanFunctions.set(instance, DeviceManager.vkDevice); @@ -342,9 +326,7 @@ private static void createVma() { } private static void createCommandPool() { - try (MemoryStack stack = stackPush()) { - Queue.QueueFamilyIndices queueFamilyIndices = getQueueFamilies(); VkCommandPoolCreateInfo poolInfo = VkCommandPoolCreateInfo.calloc(stack); @@ -361,21 +343,43 @@ private static void createCommandPool() { } } + private static List getAvailableInstanceExtension() { + try (MemoryStack stack = MemoryStack.stackPush()) { + // Query first for extension count + IntBuffer extensionCount = stack.ints(0); + vkEnumerateInstanceExtensionProperties((String) null, extensionCount, null); + + VkExtensionProperties.Buffer availableExtensions = VkExtensionProperties.malloc(extensionCount.get(0), stack); + vkEnumerateInstanceExtensionProperties((String) null, extensionCount, availableExtensions); + + return availableExtensions.stream() + .map(VkExtensionProperties::extensionNameString) + .toList(); + } + } + private static PointerBuffer getRequiredInstanceExtensions() { PointerBuffer glfwExtensions = glfwGetRequiredInstanceExtensions(); MemoryStack stack = stackGet(); + List requestedExtensions = new ArrayList<>(); + + // Check for VK_EXT_SWAPCHAIN_COLOR_SPACE support + if (supportedInstanceExtensions.contains(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME)) { + requestedExtensions.add(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME); + } + if (ENABLE_VALIDATION_LAYERS) { - PointerBuffer extensions = stack.mallocPointer(glfwExtensions.capacity() + 2); - extensions.put(glfwExtensions); - extensions.put(stack.UTF8(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)); - extensions.put(stack.UTF8(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME)); - return extensions.rewind(); + requestedExtensions.add(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); } - PointerBuffer extensions = stack.mallocPointer(glfwExtensions.capacity() + 1); + PointerBuffer extensions = stack.mallocPointer(glfwExtensions.capacity() + requestedExtensions.size()); extensions.put(glfwExtensions); - extensions.put(stack.UTF8(VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME)); + + for (String extName : requestedExtensions) { + extensions.put(stack.UTF8(extName)); + } + return extensions.rewind(); } @@ -393,8 +397,12 @@ public static void setVsync(boolean b) { } } - public static int getDefaultDepthFormat() { - return DEFAULT_DEPTH_FORMAT; + public static VkDevice getVkDevice() { + return DeviceManager.vkDevice; + } + + public static long getAllocator() { + return allocator; } public static long getSurface() { @@ -412,5 +420,13 @@ public static StagingBuffer getStagingBuffer() { public static Device getDevice() { return DeviceManager.device; } + + public static boolean colorSpaceExtSupport() { + return colorSpaceExtSupport; + } + + public static int getDefaultDepthFormat() { + return DEFAULT_DEPTH_FORMAT; + } } diff --git a/src/main/java/net/vulkanmod/vulkan/device/Device.java b/src/main/java/net/vulkanmod/vulkan/device/Device.java index da850d3b9..94768dfb6 100644 --- a/src/main/java/net/vulkanmod/vulkan/device/Device.java +++ b/src/main/java/net/vulkanmod/vulkan/device/Device.java @@ -1,19 +1,15 @@ package net.vulkanmod.vulkan.device; -import org.lwjgl.PointerBuffer; import org.lwjgl.system.MemoryStack; import org.lwjgl.vulkan.*; -import oshi.SystemInfo; -import oshi.hardware.CentralProcessor; import java.nio.IntBuffer; import java.util.HashSet; +import java.util.List; import java.util.Set; -import static java.util.stream.Collectors.toSet; import static org.lwjgl.glfw.GLFW.GLFW_PLATFORM_WIN32; import static org.lwjgl.glfw.GLFW.glfwGetPlatform; -import static org.lwjgl.system.MemoryStack.stackPush; import static org.lwjgl.vulkan.VK10.*; import static org.lwjgl.vulkan.VK11.vkEnumerateInstanceVersion; import static org.lwjgl.vulkan.VK11.vkGetPhysicalDeviceFeatures2; @@ -31,15 +27,13 @@ public class Device { public final VkPhysicalDeviceFeatures2 availableFeatures; public final VkPhysicalDeviceVulkan11Features availableFeatures11; -// public final VkPhysicalDeviceVulkan13Features availableFeatures13; -// public final boolean vulkan13Support; - - private boolean drawIndirectSupported; + public final List supportedExtensions; + public final boolean drawIndirectSupported; public Device(VkPhysicalDevice device) { this.physicalDevice = device; - properties = VkPhysicalDeviceProperties.malloc(); + this.properties = VkPhysicalDeviceProperties.malloc(); vkGetPhysicalDeviceProperties(physicalDevice, properties); this.vendorId = properties.vendorID(); @@ -55,18 +49,40 @@ public Device(VkPhysicalDevice device) { this.availableFeatures11.sType$Default(); this.availableFeatures.pNext(this.availableFeatures11); - //Vulkan 1.3 -// this.availableFeatures13 = VkPhysicalDeviceVulkan13Features.malloc(); -// this.availableFeatures13.sType$Default(); -// this.availableFeatures11.pNext(this.availableFeatures13.address()); -// -// this.vulkan13Support = this.device.getCapabilities().apiVersion == VK_API_VERSION_1_3; - vkGetPhysicalDeviceFeatures2(this.physicalDevice, this.availableFeatures); - if (this.availableFeatures.features().multiDrawIndirect() && this.availableFeatures11.shaderDrawParameters()) - this.drawIndirectSupported = true; + this.drawIndirectSupported = this.availableFeatures.features().multiDrawIndirect(); + + this.supportedExtensions = getAvailableExtension(device); + } + + public List getSupportedExtensions() { + return supportedExtensions; + } + + public Set getUnsupportedExtensions(Set requiredExtensions) { + Set unsupportedExtensions = new HashSet<>(requiredExtensions); + supportedExtensions.forEach(unsupportedExtensions::remove); + + return unsupportedExtensions; + } + + public boolean isDrawIndirectSupported() { + return drawIndirectSupported; + } + + // Added these to allow detecting GPU vendor, to allow handling vendor specific circumstances: + // (e.g. such as in case we encounter a vendor specific driver bug) + public boolean isAMD() { + return vendorId == 0x1022; + } + public boolean isNvidia() { + return vendorId == 0x10DE; + } + + public boolean isIntel() { + return vendorId == 0x8086; } private static String decodeVendor(int i) { @@ -108,7 +124,7 @@ private static String decodeNvidia(int v) { return (v >>> 22 & 0x3FF) + "." + (v >>> 14 & 0xff) + "." + (v >>> 6 & 0xff) + "." + (v & 0xff); } - static int getVkVer() { + private static int getVkVer() { try (MemoryStack stack = MemoryStack.stackPush()) { var a = stack.mallocInt(1); vkEnumerateInstanceVersion(a); @@ -120,43 +136,18 @@ static int getVkVer() { } } - public Set getUnsupportedExtensions(Set requiredExtensions) { - try (MemoryStack stack = stackPush()) { - + private static List getAvailableExtension(VkPhysicalDevice device) { + try (MemoryStack stack = MemoryStack.stackPush()) { + // Query first for extension count IntBuffer extensionCount = stack.ints(0); - - vkEnumerateDeviceExtensionProperties(physicalDevice, (String) null, extensionCount, null); + vkEnumerateDeviceExtensionProperties(device, (String) null, extensionCount, null); VkExtensionProperties.Buffer availableExtensions = VkExtensionProperties.malloc(extensionCount.get(0), stack); + vkEnumerateDeviceExtensionProperties(device, (String) null, extensionCount, availableExtensions); - vkEnumerateDeviceExtensionProperties(physicalDevice, (String) null, extensionCount, availableExtensions); - - Set extensions = availableExtensions.stream() - .map(VkExtensionProperties::extensionNameString) - .collect(toSet()); - - Set unsupportedExtensions = new HashSet<>(requiredExtensions); - unsupportedExtensions.removeAll(extensions); - - return unsupportedExtensions; + return availableExtensions.stream() + .map(VkExtensionProperties::extensionNameString) + .toList(); } } - - public boolean isDrawIndirectSupported() { - return drawIndirectSupported; - } - - // Added these to allow detecting GPU vendor, to allow handling vendor specific circumstances: - // (e.g. such as in case we encounter a vendor specific driver bug) - public boolean isAMD() { - return vendorId == 0x1022; - } - - public boolean isNvidia() { - return vendorId == 0x10DE; - } - - public boolean isIntel() { - return vendorId == 0x8086; - } } diff --git a/src/main/java/net/vulkanmod/vulkan/device/DeviceManager.java b/src/main/java/net/vulkanmod/vulkan/device/DeviceManager.java index 18fd202a0..58489b9d0 100644 --- a/src/main/java/net/vulkanmod/vulkan/device/DeviceManager.java +++ b/src/main/java/net/vulkanmod/vulkan/device/DeviceManager.java @@ -11,9 +11,9 @@ import java.nio.IntBuffer; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; -import static java.util.stream.Collectors.toSet; import static net.vulkanmod.vulkan.queue.Queue.findQueueFamilies; import static net.vulkanmod.vulkan.util.VUtil.asPointerBuffer; import static org.lwjgl.glfw.GLFWVulkan.glfwGetRequiredInstanceExtensions; @@ -87,7 +87,7 @@ static void getSuitableDevices(VkInstance instance) { List devices = new ObjectArrayList<>(); for (Device device : availableDevices) { - if (isDeviceSuitable(device.physicalDevice)) { + if (isDeviceSuitable(device)) { devices.add(device); } } @@ -154,7 +154,7 @@ else if (!otherDevices.isEmpty()) public static void createLogicalDevice() { try (MemoryStack stack = stackPush()) { - net.vulkanmod.vulkan.queue.Queue.QueueFamilyIndices indices = findQueueFamilies(physicalDevice); + Queue.QueueFamilyIndices indices = findQueueFamilies(physicalDevice); int[] uniqueQueueFamilies = indices.unique(); @@ -248,39 +248,38 @@ private static PointerBuffer getRequiredExtensions() { return glfwExtensions; } - private static boolean isDeviceSuitable(VkPhysicalDevice device) { + private static boolean isDeviceSuitable(Device device) { try (MemoryStack stack = stackPush()) { - Queue.QueueFamilyIndices indices = findQueueFamilies(device); - - VkExtensionProperties.Buffer availableExtensions = getAvailableExtension(stack, device); - boolean extensionsSupported = availableExtensions.stream() - .map(VkExtensionProperties::extensionNameString) - .collect(toSet()) - .containsAll(Vulkan.REQUIRED_EXTENSION); + var supportedExtension = device.getSupportedExtensions(); + boolean extensionsSupported = new HashSet<>(supportedExtension).containsAll(Vulkan.REQUIRED_EXTENSION); boolean swapChainAdequate = false; if (extensionsSupported) { - SurfaceProperties surfaceProperties = querySurfaceProperties(device, stack); + SurfaceProperties surfaceProperties = querySurfaceProperties(device.physicalDevice, stack); swapChainAdequate = surfaceProperties.formats.hasRemaining() && surfaceProperties.presentModes.hasRemaining(); } VkPhysicalDeviceFeatures supportedFeatures = VkPhysicalDeviceFeatures.malloc(stack); - vkGetPhysicalDeviceFeatures(device, supportedFeatures); + vkGetPhysicalDeviceFeatures(device.physicalDevice, supportedFeatures); boolean anisotropicFilterSupported = supportedFeatures.samplerAnisotropy(); + Queue.QueueFamilyIndices indices = findQueueFamilies(device.physicalDevice); + return indices.isSuitable() && extensionsSupported && swapChainAdequate; } } - private static VkExtensionProperties.Buffer getAvailableExtension(MemoryStack stack, VkPhysicalDevice device) { + private static List getAvailableExtension(MemoryStack stack, VkPhysicalDevice device) { IntBuffer extensionCount = stack.ints(0); vkEnumerateDeviceExtensionProperties(device, (String) null, extensionCount, null); VkExtensionProperties.Buffer availableExtensions = VkExtensionProperties.malloc(extensionCount.get(0), stack); vkEnumerateDeviceExtensionProperties(device, (String) null, extensionCount, availableExtensions); - return availableExtensions; + return availableExtensions.stream() + .map(VkExtensionProperties::extensionNameString) + .toList(); } // Use the optimal most performant depth format for the specific GPU diff --git a/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java b/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java index f1202c7a4..1120a0a30 100644 --- a/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java +++ b/src/main/java/net/vulkanmod/vulkan/framebuffer/SwapChain.java @@ -163,9 +163,7 @@ private void createSwapChain() { } private long[] createFramebuffers(RenderPass renderPass) { - try (MemoryStack stack = MemoryStack.stackPush()) { - long[] framebuffers = new long[this.swapChainImages.size()]; for (int i = 0; i < this.swapChainImages.size(); ++i) { @@ -245,28 +243,35 @@ public long getImageView(int i) { private VkSurfaceFormatKHR getFormat(VkSurfaceFormatKHR.Buffer availableFormats) { List list = availableFormats.stream().toList(); - // Extended sRGB (P3 gamut with sRGB gamma) on macOS - if (Platform.isMacOS()) { - for (VkSurfaceFormatKHR f : list) { - if (f.format() == VK_FORMAT_B8G8R8A8_UNORM && f.colorSpace() == VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT) { - isBGRAformat = true; - return f; - } - } + int colorSpace; + if (Platform.isMacOS() && colorSpaceExtSupport()) { + colorSpace = VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT; + } else { + colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; } - // If fail try RGBA format with standard sRGB + // Try RGBA format first + VkSurfaceFormatKHR format = null; for (VkSurfaceFormatKHR availableFormat : list) { - if (availableFormat.format() == VK_FORMAT_R8G8B8A8_UNORM && availableFormat.colorSpace() == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + if (availableFormat.format() == VK_FORMAT_R8G8B8A8_UNORM && availableFormat.colorSpace() == colorSpace) return availableFormat; + + // Fallback to RGBA sRBG in case of no match + if (availableFormat.format() == VK_FORMAT_R8G8B8A8_UNORM && availableFormat.colorSpace() == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + format = availableFormat; } - // Standard BGRA sRGB - VkSurfaceFormatKHR format = list.get(0); for (VkSurfaceFormatKHR availableFormat : list) { - if (availableFormat.format() == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace() == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { + if (availableFormat.format() == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace() == colorSpace) { format = availableFormat; } + + if (format == null && availableFormat.format() == VK_FORMAT_B8G8R8A8_UNORM && availableFormat.colorSpace() == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + format = availableFormat; + } + + if (format == null) { + format = list.get(0); } if (format.format() == VK_FORMAT_B8G8R8A8_UNORM)