Support the VK_EXT_swapchain_colorspace extension.
Only some of the color spaces provided by this extension are supported.
macOS 10.12 supports a few more. macOS 10.14 (at least, according to the
*10.15* SDK) supports even more. (But that needs a change to the
Metal-3.0 branch.)
I've chosen to group by color space. That way, programs will find the
all the supported formats early on. Programs that are interested in
the color space can keep looking.
diff --git a/Docs/MoltenVK_Runtime_UserGuide.md b/Docs/MoltenVK_Runtime_UserGuide.md
index a0d5107..9e9149d 100644
--- a/Docs/MoltenVK_Runtime_UserGuide.md
+++ b/Docs/MoltenVK_Runtime_UserGuide.md
@@ -256,6 +256,7 @@
- `VK_EXT_metal_surface`
- `VK_EXT_shader_stencil_export` *(requires Mac GPU family 2 or iOS GPU family 5)*
- `VK_EXT_shader_viewport_index_layer`
+- `VK_EXT_swapchain_colorspace` *(macOS)*
- `VK_EXT_vertex_attribute_divisor`
- `VK_EXTX_portability_subset`
- `VK_MVK_ios_surface` *(iOS) (Obsolete. Use `VK_EXT_metal_surface` instead.)*
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
index 30c2a4a..2465667 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKDevice.mm
@@ -461,22 +461,42 @@
MTLPixelFormatRGBA16Float,
};
+ MVKVectorInline<VkColorSpaceKHR, 16> colorSpaces;
+ colorSpaces.push_back(VK_COLOR_SPACE_SRGB_NONLINEAR_KHR);
+#if MVK_MACOS
+ if (getInstance()->_enabledExtensions.vk_EXT_swapchain_colorspace.enabled) {
+ // 10.11 supports some but not all of the color spaces specified by VK_EXT_swapchain_colorspace.
+ colorSpaces.push_back(VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT);
+ colorSpaces.push_back(VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT);
+ colorSpaces.push_back(VK_COLOR_SPACE_BT709_NONLINEAR_EXT);
+ colorSpaces.push_back(VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT);
+ colorSpaces.push_back(VK_COLOR_SPACE_PASS_THROUGH_EXT);
+ if (mvkOSVersion() >= 10.12) {
+ colorSpaces.push_back(VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT);
+ colorSpaces.push_back(VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT);
+ }
+ }
+#endif
+
const uint mtlFmtsCnt = sizeof(mtlFormats) / sizeof(MTLPixelFormat);
+ const uint vkFmtsCnt = mtlFmtsCnt * (uint)colorSpaces.size();
// If properties aren't actually being requested yet, simply update the returned count
if ( !pSurfaceFormats ) {
- *pCount = mtlFmtsCnt;
+ *pCount = vkFmtsCnt;
return VK_SUCCESS;
}
// Determine how many results we'll return, and return that number
- VkResult result = (*pCount >= mtlFmtsCnt) ? VK_SUCCESS : VK_INCOMPLETE;
- *pCount = min(*pCount, mtlFmtsCnt);
+ VkResult result = (*pCount >= vkFmtsCnt) ? VK_SUCCESS : VK_INCOMPLETE;
+ *pCount = min(*pCount, vkFmtsCnt);
// Now populate the supplied array
- for (uint fmtIdx = 0; fmtIdx < *pCount; fmtIdx++) {
- pSurfaceFormats[fmtIdx].format = mvkVkFormatFromMTLPixelFormat(mtlFormats[fmtIdx]);
- pSurfaceFormats[fmtIdx].colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
+ for (uint csIdx = 0, idx = 0; idx < *pCount && csIdx < colorSpaces.size(); csIdx++) {
+ for (uint fmtIdx = 0; idx < *pCount && fmtIdx < mtlFmtsCnt; fmtIdx++, idx++) {
+ pSurfaceFormats[idx].format = mvkVkFormatFromMTLPixelFormat(mtlFormats[fmtIdx]);
+ pSurfaceFormats[idx].colorSpace = colorSpaces[csIdx];
+ }
}
return result;
diff --git a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm
index 992f1cb..e6f5ab0 100644
--- a/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm
+++ b/MoltenVK/MoltenVK/GPUObjects/MVKSwapchain.mm
@@ -224,12 +224,40 @@
VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_STORAGE_BIT));
+#if MVK_MACOS
+ switch (pCreateInfo->imageColorSpace) {
+ case VK_COLOR_SPACE_SRGB_NONLINEAR_KHR:
+ _mtlLayer.colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
+ break;
+ case VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT:
+ _mtlLayer.colorspace = CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3);
+ break;
+ case VK_COLOR_SPACE_EXTENDED_SRGB_LINEAR_EXT:
+ _mtlLayer.colorspace = CGColorSpaceCreateWithName(kCGColorSpaceExtendedLinearSRGB);
+ break;
+ case VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT:
+ _mtlLayer.colorspace = CGColorSpaceCreateWithName(kCGColorSpaceDCIP3);
+ break;
+ case VK_COLOR_SPACE_BT709_NONLINEAR_EXT:
+ _mtlLayer.colorspace = CGColorSpaceCreateWithName(kCGColorSpaceITUR_709);
+ break;
+ case VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT:
+ _mtlLayer.colorspace = CGColorSpaceCreateWithName(kCGColorSpaceAdobeRGB1998);
+ break;
+ case VK_COLOR_SPACE_EXTENDED_SRGB_NONLINEAR_EXT:
+ _mtlLayer.colorspace = CGColorSpaceCreateWithName(kCGColorSpaceExtendedSRGB);
+ break;
+ case VK_COLOR_SPACE_PASS_THROUGH_EXT:
+ default:
+ // Nothing - the default is not to do color matching.
+ break;
+ }
+#endif
_mtlLayerOrigDrawSize = _mtlLayer.updatedDrawableSizeMVK;
// TODO: set additional CAMetalLayer properties before extracting drawables:
// - presentsWithTransaction
// - drawsAsynchronously
- // - colorspace (macOS only) Vulkan only supports sRGB colorspace for now.
// - wantsExtendedDynamicRangeContent (macOS only)
if ( [_mtlLayer.delegate isKindOfClass: [PLATFORM_VIEW_CLASS class]] ) {
diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.def b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
index 2d9e0e1..e167ced 100644
--- a/MoltenVK/MoltenVK/Layers/MVKExtensions.def
+++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.def
@@ -60,6 +60,7 @@
MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE)
MVK_EXTENSION(EXT_shader_stencil_export, EXT_SHADER_STENCIL_EXPORT)
MVK_EXTENSION(EXT_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER)
+MVK_EXTENSION(EXT_swapchain_colorspace, EXT_SWAPCHAIN_COLOR_SPACE)
MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR)
MVK_EXTENSION(EXTX_portability_subset, EXTX_PORTABILITY_SUBSET)
MVK_EXTENSION(MVK_ios_surface, MVK_IOS_SURFACE)
diff --git a/MoltenVK/MoltenVK/Layers/MVKExtensions.mm b/MoltenVK/MoltenVK/Layers/MVKExtensions.mm
index e1580dc..61431ef 100644
--- a/MoltenVK/MoltenVK/Layers/MVKExtensions.mm
+++ b/MoltenVK/MoltenVK/Layers/MVKExtensions.mm
@@ -46,7 +46,7 @@
// Returns whether the specified properties are valid for this platform
static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) {
-#if !(MVK_IOS)
+#if MVK_MACOS
if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
return mvkOSVersion() >= 10.13;
}
@@ -56,7 +56,7 @@
if (pProperties == &kVkExtProps_MVK_IOS_SURFACE) { return false; }
if (pProperties == &kVkExtProps_IMG_FORMAT_PVRTC) { return false; }
#endif
-#if !(MVK_MACOS)
+#if MVK_IOS
if (pProperties == &kVkExtProps_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE) { return false; }
if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
return mvkOSVersion() >= 11.0;
@@ -64,6 +64,7 @@
if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) {
return mvkOSVersion() >= 12.0;
}
+ if (pProperties == &kVkExtProps_EXT_SWAPCHAIN_COLOR_SPACE) { return false; }
if (pProperties == &kVkExtProps_MVK_MACOS_SURFACE) { return false; }
#endif