diff --git a/src/rendering/vulkan/system/vk_device.cpp b/src/rendering/vulkan/system/vk_device.cpp index a8b54ed48..57877ac0a 100644 --- a/src/rendering/vulkan/system/vk_device.cpp +++ b/src/rendering/vulkan/system/vk_device.cpp @@ -184,6 +184,18 @@ void VulkanDevice::SelectPhysicalDevice() if (selected >= SupportedDevices.size()) selected = 0; + // Enable optional extensions we are interested in, if they are available on this device + for (const auto &ext : SupportedDevices[selected].device->Extensions) + { + for (const auto &opt : OptionalDeviceExtensions) + { + if (strcmp(ext.extensionName, opt) == 0) + { + EnabledDeviceExtensions.push_back(opt); + } + } + } + PhysicalDevice = *SupportedDevices[selected].device; graphicsFamily = SupportedDevices[selected].graphicsFamily; presentFamily = SupportedDevices[selected].presentFamily; @@ -313,6 +325,18 @@ void VulkanDevice::CreateInstance() } } + // Enable optional instance extensions we are interested in + for (const auto &ext : Extensions) + { + for (const auto &opt : OptionalExtensions) + { + if (strcmp(ext.extensionName, opt) == 0) + { + EnabledExtensions.push_back(opt); + } + } + } + VkApplicationInfo appInfo = {}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "GZDoom"; diff --git a/src/rendering/vulkan/system/vk_device.h b/src/rendering/vulkan/system/vk_device.h index 9432c700a..9f880d33e 100644 --- a/src/rendering/vulkan/system/vk_device.h +++ b/src/rendering/vulkan/system/vk_device.h @@ -62,11 +62,13 @@ public: std::vector AvailableLayers; std::vector Extensions; std::vector EnabledExtensions; + std::vector OptionalExtensions = { VK_EXT_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME }; std::vector EnabledValidationLayers; // Device setup VkPhysicalDeviceFeatures UsedDeviceFeatures = {}; std::vector EnabledDeviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; + std::vector OptionalDeviceExtensions = { VK_EXT_HDR_METADATA_EXTENSION_NAME }; VulkanPhysicalDevice PhysicalDevice; bool DebugLayerActive = false; diff --git a/src/rendering/vulkan/system/vk_swapchain.cpp b/src/rendering/vulkan/system/vk_swapchain.cpp index 4bd46d8f1..1b10cfdc9 100644 --- a/src/rendering/vulkan/system/vk_swapchain.cpp +++ b/src/rendering/vulkan/system/vk_swapchain.cpp @@ -1,5 +1,12 @@ #include "vk_swapchain.h" +#include "c_cvars.h" +#include "version.h" + +CUSTOM_CVAR(Bool, vk_hdr, false, /*CVAR_ARCHIVE | CVAR_GLOBALCONFIG |*/ CVAR_NOINITCALL) +{ + Printf("This won't take effect until " GAMENAME " is restarted.\n"); +} VulkanSwapChain::VulkanSwapChain(VulkanDevice *device, int width, int height, bool vsync) : vsync(vsync), device(device) { @@ -40,12 +47,30 @@ VulkanSwapChain::VulkanSwapChain(VulkanDevice *device, int width, int height, bo else { swapChainFormat = surfaceFormats.front(); - for (const auto &format : surfaceFormats) + + bool found = false; + if (vk_hdr) { - if (format.format == VK_FORMAT_B8G8R8A8_UNORM && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + for (const auto &format : surfaceFormats) { - swapChainFormat = format; - break; + if (format.format == VK_FORMAT_R16G16B16A16_SFLOAT && format.colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT) + { + swapChainFormat = format; + found = true; + break; + } + } + } + + if (!found) + { + for (const auto &format : surfaceFormats) + { + if (format.format == VK_FORMAT_B8G8R8A8_UNORM && format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) + { + swapChainFormat = format; + break; + } } } } @@ -85,7 +110,7 @@ VulkanSwapChain::VulkanSwapChain(VulkanDevice *device, int width, int height, bo swapChainCreateInfo.imageColorSpace = swapChainFormat.colorSpace; swapChainCreateInfo.imageExtent = actualExtent; swapChainCreateInfo.imageArrayLayers = 1; - swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT; + swapChainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; uint32_t queueFamilyIndices[] = { (uint32_t)device->graphicsFamily, (uint32_t)device->presentFamily }; if (device->graphicsFamily != device->presentFamily) @@ -143,6 +168,30 @@ VulkanSwapChain::VulkanSwapChain(VulkanDevice *device, int width, int height, bo device->SetDebugObjectName("SwapChainImageView", (uint64_t)swapChainImageViews[i], VK_OBJECT_TYPE_IMAGE_VIEW); } + + if (swapChainFormat.colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT) + { + // Mastering display with DCI-P3 color primaries and D65 white point, + // maximum luminance of 1000 nits and minimum luminance of 0.001 nits; + // content has maximum luminance of 2000 nits and maximum frame average light level (MaxFALL) of 500 nits. + + VkHdrMetadataEXT metadata = {}; + metadata.sType = VK_STRUCTURE_TYPE_HDR_METADATA_EXT; + metadata.displayPrimaryRed.x = 0.680f; + metadata.displayPrimaryRed.y = 0.320f; + metadata.displayPrimaryGreen.x = 0.265f; + metadata.displayPrimaryGreen.y = 0.690f; + metadata.displayPrimaryBlue.x = 0.150f; + metadata.displayPrimaryBlue.y = 0.060f; + metadata.whitePoint.x = 0.3127f; + metadata.whitePoint.y = 0.3290f; + metadata.maxLuminance = 1000.0f; + metadata.minLuminance = 0.001f; + metadata.maxContentLightLevel = 2000.0f; + metadata.maxFrameAverageLightLevel = 500.0f; + + vkSetHdrMetadataEXT(device->device, 1, &swapChain, &metadata); + } } catch (...) {