This commit is contained in:
Bill Hollings 2019-07-16 22:48:46 -04:00
commit de29ba9318
10 changed files with 195 additions and 26 deletions

View File

@ -253,11 +253,13 @@ In addition to the core *Vulkan* API, **MoltenVK** also supports the following
- `VK_EXT_debug_report` - `VK_EXT_debug_report`
- `VK_EXT_debug_utils` - `VK_EXT_debug_utils`
- `VK_EXT_host_query_reset` - `VK_EXT_host_query_reset`
- `VK_EXT_memory_budget` - `VK_EXT_memory_budget` *(requires Metal 2.0)*
- `VK_EXT_metal_surface` - `VK_EXT_metal_surface`
- `VK_EXT_shader_stencil_export` *(requires Mac GPU family 2 or iOS GPU family 5)* - `VK_EXT_shader_stencil_export` *(requires Mac GPU family 2 or iOS GPU family 5)*
- `VK_EXT_shader_viewport_index_layer` - `VK_EXT_shader_viewport_index_layer`
- `VK_EXT_swapchain_colorspace` *(macOS)*
- `VK_EXT_vertex_attribute_divisor` - `VK_EXT_vertex_attribute_divisor`
- `VK_EXT_texel_buffer_alignment` *(requires Metal 2.0)*
- `VK_EXTX_portability_subset` - `VK_EXTX_portability_subset`
- `VK_MVK_ios_surface` *(iOS) (Obsolete. Use `VK_EXT_metal_surface` instead.)* - `VK_MVK_ios_surface` *(iOS) (Obsolete. Use `VK_EXT_metal_surface` instead.)*
- `VK_MVK_macos_surface` *(macOS) (Obsolete. Use `VK_EXT_metal_surface` instead.)* - `VK_MVK_macos_surface` *(macOS) (Obsolete. Use `VK_EXT_metal_surface` instead.)*

View File

@ -1 +1 @@
097a1045098213919fd56442f52c716fc78eeb27 737f4c1cd96283747967c2024a0108b742214455

View File

@ -223,6 +223,7 @@ MVKBufferView::MVKBufferView(MVKDevice* device, const VkBufferViewCreateInfo* pC
// We can just use a simple 1D texel array. // We can just use a simple 1D texel array.
_textureSize.width = uint32_t(blockCount * fmtBlockSize.width); _textureSize.width = uint32_t(blockCount * fmtBlockSize.width);
_textureSize.height = 1; _textureSize.height = 1;
_mtlBytesPerRow = byteCount;
} }
if ( !_device->_pMetalFeatures->texelBuffers ) { if ( !_device->_pMetalFeatures->texelBuffers ) {

View File

@ -336,6 +336,7 @@ protected:
VkPhysicalDeviceFeatures _features; VkPhysicalDeviceFeatures _features;
MVKPhysicalDeviceMetalFeatures _metalFeatures; MVKPhysicalDeviceMetalFeatures _metalFeatures;
VkPhysicalDeviceProperties _properties; VkPhysicalDeviceProperties _properties;
VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT _texelBuffAlignProperties;
VkPhysicalDeviceMemoryProperties _memoryProperties; VkPhysicalDeviceMemoryProperties _memoryProperties;
std::vector<MVKQueueFamily*> _queueFamilies; std::vector<MVKQueueFamily*> _queueFamilies;
uint32_t _allMemoryTypes; uint32_t _allMemoryTypes;

View File

@ -69,8 +69,7 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
if (features) { if (features) {
features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; features->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
features->features = _features; features->features = _features;
auto* next = (VkBaseOutStructure*)features->pNext; for (auto* next = (VkBaseOutStructure*)features->pNext; next; next = next->pNext) {
while (next) {
switch ((uint32_t)next->sType) { switch ((uint32_t)next->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES: {
auto* storageFeatures = (VkPhysicalDevice16BitStorageFeatures*)next; auto* storageFeatures = (VkPhysicalDevice16BitStorageFeatures*)next;
@ -109,6 +108,11 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
hostQueryResetFeatures->hostQueryReset = true; hostQueryResetFeatures->hostQueryReset = true;
break; break;
} }
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_FEATURES_EXT: {
auto* texelBuffAlignFeatures = (VkPhysicalDeviceTexelBufferAlignmentFeaturesEXT*)next;
texelBuffAlignFeatures->texelBufferAlignment = _metalFeatures.texelBuffers && [_mtlDevice respondsToSelector: @selector(minimumLinearTextureAlignmentForPixelFormat:)];
break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT: {
auto* divisorFeatures = (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT*)next; auto* divisorFeatures = (VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT*)next;
divisorFeatures->vertexAttributeInstanceRateDivisor = true; divisorFeatures->vertexAttributeInstanceRateDivisor = true;
@ -127,7 +131,6 @@ void MVKPhysicalDevice::getFeatures(VkPhysicalDeviceFeatures2* features) {
default: default:
break; break;
} }
next = next->pNext;
} }
} }
} }
@ -140,42 +143,44 @@ void MVKPhysicalDevice::getProperties(VkPhysicalDeviceProperties2* properties) {
if (properties) { if (properties) {
properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2; properties->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
properties->properties = _properties; properties->properties = _properties;
auto* next = (MVKVkAPIStructHeader*)properties->pNext; for (auto* next = (VkBaseOutStructure*)properties->pNext; next; next = next->pNext) {
while (next) {
switch ((uint32_t)next->sType) { switch ((uint32_t)next->sType) {
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES: {
auto* pointClipProps = (VkPhysicalDevicePointClippingProperties*)next; auto* pointClipProps = (VkPhysicalDevicePointClippingProperties*)next;
pointClipProps->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES; pointClipProps->pointClippingBehavior = VK_POINT_CLIPPING_BEHAVIOR_ALL_CLIP_PLANES;
next = (MVKVkAPIStructHeader*)pointClipProps->pNext;
break; break;
} }
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES: {
auto* maint3Props = (VkPhysicalDeviceMaintenance3Properties*)next; auto* maint3Props = (VkPhysicalDeviceMaintenance3Properties*)next;
maint3Props->maxPerSetDescriptors = (_metalFeatures.maxPerStageBufferCount + _metalFeatures.maxPerStageTextureCount + _metalFeatures.maxPerStageSamplerCount) * 2; maint3Props->maxPerSetDescriptors = (_metalFeatures.maxPerStageBufferCount + _metalFeatures.maxPerStageTextureCount + _metalFeatures.maxPerStageSamplerCount) * 4;
maint3Props->maxMemoryAllocationSize = _metalFeatures.maxMTLBufferSize; maint3Props->maxMemoryAllocationSize = _metalFeatures.maxMTLBufferSize;
next = (MVKVkAPIStructHeader*)maint3Props->pNext;
break; break;
} }
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR: {
auto* pushDescProps = (VkPhysicalDevicePushDescriptorPropertiesKHR*)next; auto* pushDescProps = (VkPhysicalDevicePushDescriptorPropertiesKHR*)next;
pushDescProps->maxPushDescriptors = _properties.limits.maxPerStageResources; pushDescProps->maxPushDescriptors = _properties.limits.maxPerStageResources;
next = (MVKVkAPIStructHeader*)pushDescProps->pNext; break;
}
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES_EXT: {
auto* texelBuffAlignProps = (VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT*)next;
// Save the 'next' pointer; we'll unintentionally overwrite it
// on the next line. Put it back when we're done.
void* savedNext = texelBuffAlignProps->pNext;
*texelBuffAlignProps = _texelBuffAlignProperties;
texelBuffAlignProps->pNext = savedNext;
break; break;
} }
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT: {
auto* divisorProps = (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT*)next; auto* divisorProps = (VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT*)next;
divisorProps->maxVertexAttribDivisor = kMVKUndefinedLargeUInt32; divisorProps->maxVertexAttribDivisor = kMVKUndefinedLargeUInt32;
next = (MVKVkAPIStructHeader*)divisorProps->pNext;
break; break;
} }
case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_EXTX: { case VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_EXTX: {
auto* portabilityProps = (VkPhysicalDevicePortabilitySubsetPropertiesEXTX*)next; auto* portabilityProps = (VkPhysicalDevicePortabilitySubsetPropertiesEXTX*)next;
portabilityProps->minVertexInputBindingStrideAlignment = 4; portabilityProps->minVertexInputBindingStrideAlignment = 4;
next = (MVKVkAPIStructHeader*)portabilityProps->pNext;
break; break;
} }
default: default:
next = (MVKVkAPIStructHeader*)next->pNext;
break; break;
} }
} }
@ -466,22 +471,42 @@ VkResult MVKPhysicalDevice::getSurfaceFormats(MVKSurface* surface,
MTLPixelFormatRGBA16Float, 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 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 properties aren't actually being requested yet, simply update the returned count
if ( !pSurfaceFormats ) { if ( !pSurfaceFormats ) {
*pCount = mtlFmtsCnt; *pCount = vkFmtsCnt;
return VK_SUCCESS; return VK_SUCCESS;
} }
// Determine how many results we'll return, and return that number // Determine how many results we'll return, and return that number
VkResult result = (*pCount >= mtlFmtsCnt) ? VK_SUCCESS : VK_INCOMPLETE; VkResult result = (*pCount >= vkFmtsCnt) ? VK_SUCCESS : VK_INCOMPLETE;
*pCount = min(*pCount, mtlFmtsCnt); *pCount = min(*pCount, vkFmtsCnt);
// Now populate the supplied array // Now populate the supplied array
for (uint fmtIdx = 0; fmtIdx < *pCount; fmtIdx++) { for (uint csIdx = 0, idx = 0; idx < *pCount && csIdx < colorSpaces.size(); csIdx++) {
pSurfaceFormats[fmtIdx].format = mvkVkFormatFromMTLPixelFormat(mtlFormats[fmtIdx]); for (uint fmtIdx = 0; idx < *pCount && fmtIdx < mtlFmtsCnt; fmtIdx++, idx++) {
pSurfaceFormats[fmtIdx].colorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR; pSurfaceFormats[idx].format = mvkVkFormatFromMTLPixelFormat(mtlFormats[fmtIdx]);
pSurfaceFormats[idx].colorSpace = colorSpaces[csIdx];
}
} }
return result; return result;
@ -1093,14 +1118,86 @@ void MVKPhysicalDevice::initProperties() {
_properties.limits.bufferImageGranularity = _metalFeatures.mtlBufferAlignment; _properties.limits.bufferImageGranularity = _metalFeatures.mtlBufferAlignment;
_properties.limits.nonCoherentAtomSize = _metalFeatures.mtlBufferAlignment; _properties.limits.nonCoherentAtomSize = _metalFeatures.mtlBufferAlignment;
if ([_mtlDevice respondsToSelector: @selector(minimumLinearTextureAlignmentForPixelFormat:)]) {
// Figure out the greatest alignment required by all supported formats, and
// whether or not they only require alignment to a single texel. We'll use this
// information to fill out the VkPhysicalDeviceTexelBufferAlignmentPropertiesEXT
// struct.
uint32_t maxStorage = 0, maxUniform = 0;
bool singleTexelStorage = true, singleTexelUniform = true;
mvkEnumerateSupportedFormats({0, 0, VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT}, true, [&](VkFormat vk) {
NSUInteger alignment;
if ([_mtlDevice respondsToSelector: @selector(minimumTextureBufferAlignmentForPixelFormat:)]) {
alignment = [_mtlDevice minimumTextureBufferAlignmentForPixelFormat: mvkMTLPixelFormatFromVkFormat(vk)];
} else {
alignment = [_mtlDevice minimumLinearTextureAlignmentForPixelFormat: mvkMTLPixelFormatFromVkFormat(vk)];
}
VkFormatProperties props = mvkVkFormatProperties(vk, getFormatIsSupported(vk));
// For uncompressed formats, this is the size of a single texel.
// Note that no implementations of Metal support compressed formats
// in a linear texture (including texture buffers). It's likely that even
// if they did, this would be the absolute minimum alignment.
uint32_t texelSize = mvkVkFormatBytesPerBlock(vk);
// From the spec:
// "If the size of a single texel is a multiple of three bytes, then
// the size of a single component of the format is used instead."
if (texelSize % 3 == 0) {
switch (mvkFormatTypeFromVkFormat(vk)) {
case kMVKFormatColorInt8:
case kMVKFormatColorUInt8:
texelSize = 1;
break;
case kMVKFormatColorHalf:
case kMVKFormatColorInt16:
case kMVKFormatColorUInt16:
texelSize = 2;
break;
case kMVKFormatColorFloat:
case kMVKFormatColorInt32:
case kMVKFormatColorUInt32:
default:
texelSize = 4;
break;
}
}
if (mvkAreAllFlagsEnabled(props.bufferFeatures, VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)) {
maxStorage = max(maxStorage, uint32_t(alignment));
if (alignment % texelSize != 0) { singleTexelStorage = false; }
}
if (mvkAreAllFlagsEnabled(props.bufferFeatures, VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT)) {
maxUniform = max(maxUniform, uint32_t(alignment));
if (alignment % texelSize != 0) { singleTexelUniform = false; }
}
return true;
});
_texelBuffAlignProperties.storageTexelBufferOffsetAlignmentBytes = maxStorage;
_texelBuffAlignProperties.storageTexelBufferOffsetSingleTexelAlignment = singleTexelStorage;
_texelBuffAlignProperties.uniformTexelBufferOffsetAlignmentBytes = maxUniform;
_texelBuffAlignProperties.uniformTexelBufferOffsetSingleTexelAlignment = singleTexelUniform;
_properties.limits.minTexelBufferOffsetAlignment = max(maxStorage, maxUniform);
} else {
#if MVK_IOS
if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily3_v1]) {
_properties.limits.minTexelBufferOffsetAlignment = 16;
} else {
_properties.limits.minTexelBufferOffsetAlignment = 64;
}
#endif
#if MVK_MACOS
_properties.limits.minTexelBufferOffsetAlignment = 256;
#endif
_texelBuffAlignProperties.storageTexelBufferOffsetAlignmentBytes = _properties.limits.minTexelBufferOffsetAlignment;
_texelBuffAlignProperties.storageTexelBufferOffsetSingleTexelAlignment = VK_FALSE;
_texelBuffAlignProperties.uniformTexelBufferOffsetAlignmentBytes = _properties.limits.minTexelBufferOffsetAlignment;
_texelBuffAlignProperties.uniformTexelBufferOffsetSingleTexelAlignment = VK_FALSE;
}
#if MVK_IOS #if MVK_IOS
_properties.limits.maxFragmentInputComponents = 60; _properties.limits.maxFragmentInputComponents = 60;
if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily3_v1]) { if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_iOS_GPUFamily3_v1]) {
_properties.limits.minTexelBufferOffsetAlignment = 16;
_properties.limits.optimalBufferCopyOffsetAlignment = 16; _properties.limits.optimalBufferCopyOffsetAlignment = 16;
} else { } else {
_properties.limits.minTexelBufferOffsetAlignment = 64;
_properties.limits.optimalBufferCopyOffsetAlignment = 64; _properties.limits.optimalBufferCopyOffsetAlignment = 64;
} }
@ -1117,7 +1214,6 @@ void MVKPhysicalDevice::initProperties() {
#endif #endif
#if MVK_MACOS #if MVK_MACOS
_properties.limits.maxFragmentInputComponents = 128; _properties.limits.maxFragmentInputComponents = 128;
_properties.limits.minTexelBufferOffsetAlignment = 256;
_properties.limits.optimalBufferCopyOffsetAlignment = 256; _properties.limits.optimalBufferCopyOffsetAlignment = 256;
if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily1_v2]) { if ([_mtlDevice supportsFeatureSet: MTLFeatureSet_macOS_GPUFamily1_v2]) {

View File

@ -226,12 +226,40 @@ void MVKSwapchain::initCAMetalLayer(const VkSwapchainCreateInfoKHR* pCreateInfo,
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
VK_IMAGE_USAGE_STORAGE_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; _mtlLayerOrigDrawSize = _mtlLayer.updatedDrawableSizeMVK;
// TODO: set additional CAMetalLayer properties before extracting drawables: // TODO: set additional CAMetalLayer properties before extracting drawables:
// - presentsWithTransaction // - presentsWithTransaction
// - drawsAsynchronously // - drawsAsynchronously
// - colorspace (macOS only) Vulkan only supports sRGB colorspace for now.
// - wantsExtendedDynamicRangeContent (macOS only) // - wantsExtendedDynamicRangeContent (macOS only)
if ( [_mtlLayer.delegate isKindOfClass: [PLATFORM_VIEW_CLASS class]] ) { if ( [_mtlLayer.delegate isKindOfClass: [PLATFORM_VIEW_CLASS class]] ) {

View File

@ -61,6 +61,8 @@ MVK_EXTENSION(EXT_memory_budget, EXT_MEMORY_BUDGET)
MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE) MVK_EXTENSION(EXT_metal_surface, EXT_METAL_SURFACE)
MVK_EXTENSION(EXT_shader_stencil_export, EXT_SHADER_STENCIL_EXPORT) 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_shader_viewport_index_layer, EXT_SHADER_VIEWPORT_INDEX_LAYER)
MVK_EXTENSION(EXT_swapchain_colorspace, EXT_SWAPCHAIN_COLOR_SPACE)
MVK_EXTENSION(EXT_texel_buffer_alignment, EXT_TEXEL_BUFFER_ALIGNMENT)
MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR) MVK_EXTENSION(EXT_vertex_attribute_divisor, EXT_VERTEX_ATTRIBUTE_DIVISOR)
MVK_EXTENSION(EXTX_portability_subset, EXTX_PORTABILITY_SUBSET) MVK_EXTENSION(EXTX_portability_subset, EXTX_PORTABILITY_SUBSET)
MVK_EXTENSION(MVK_ios_surface, MVK_IOS_SURFACE) MVK_EXTENSION(MVK_ios_surface, MVK_IOS_SURFACE)
@ -68,6 +70,7 @@ MVK_EXTENSION(MVK_macos_surface, MVK_MACOS_SURFACE)
MVK_EXTENSION(MVK_moltenvk, MVK_MOLTENVK) MVK_EXTENSION(MVK_moltenvk, MVK_MOLTENVK)
MVK_EXTENSION(AMD_gpu_shader_half_float, AMD_GPU_SHADER_HALF_FLOAT) MVK_EXTENSION(AMD_gpu_shader_half_float, AMD_GPU_SHADER_HALF_FLOAT)
MVK_EXTENSION(AMD_negative_viewport_height, AMD_NEGATIVE_VIEWPORT_HEIGHT) MVK_EXTENSION(AMD_negative_viewport_height, AMD_NEGATIVE_VIEWPORT_HEIGHT)
MVK_EXTENSION(AMD_shader_image_load_store_lod, AMD_SHADER_IMAGE_LOAD_STORE_LOD)
MVK_EXTENSION(IMG_format_pvrtc, IMG_FORMAT_PVRTC) MVK_EXTENSION(IMG_format_pvrtc, IMG_FORMAT_PVRTC)
MVK_EXTENSION_LAST(NV_glsl_shader, NV_GLSL_SHADER) MVK_EXTENSION_LAST(NV_glsl_shader, NV_GLSL_SHADER)

View File

@ -46,17 +46,21 @@ static VkExtensionProperties kVkExtProps_ ##EXT = mvkMakeExtProps(VK_ ##EXT ##_E
// Returns whether the specified properties are valid for this platform // Returns whether the specified properties are valid for this platform
static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) { static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) {
#if !(MVK_IOS) #if MVK_MACOS
if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) { if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
return mvkOSVersion() >= 10.13; return mvkOSVersion() >= 10.13;
} }
if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) { if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) {
return mvkOSVersion() >= 10.14; return mvkOSVersion() >= 10.14;
} }
if (pProperties == &kVkExtProps_EXT_TEXEL_BUFFER_ALIGNMENT) {
return mvkOSVersion() >= 10.13;
}
if (pProperties == &kVkExtProps_MVK_IOS_SURFACE) { return false; } if (pProperties == &kVkExtProps_MVK_IOS_SURFACE) { return false; }
if (pProperties == &kVkExtProps_AMD_SHADER_IMAGE_LOAD_STORE_LOD) { return false; }
if (pProperties == &kVkExtProps_IMG_FORMAT_PVRTC) { return false; } if (pProperties == &kVkExtProps_IMG_FORMAT_PVRTC) { return false; }
#endif #endif
#if !(MVK_MACOS) #if MVK_IOS
if (pProperties == &kVkExtProps_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE) { return false; } if (pProperties == &kVkExtProps_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE) { return false; }
if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) { if (pProperties == &kVkExtProps_EXT_MEMORY_BUDGET) {
return mvkOSVersion() >= 11.0; return mvkOSVersion() >= 11.0;
@ -64,6 +68,10 @@ static bool mvkIsSupportedOnPlatform(VkExtensionProperties* pProperties) {
if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) { if (pProperties == &kVkExtProps_EXT_SHADER_STENCIL_EXPORT) {
return mvkOSVersion() >= 12.0; return mvkOSVersion() >= 12.0;
} }
if (pProperties == &kVkExtProps_EXT_SWAPCHAIN_COLOR_SPACE) { return false; }
if (pProperties == &kVkExtProps_EXT_TEXEL_BUFFER_ALIGNMENT) {
return mvkOSVersion() >= 11.0;
}
if (pProperties == &kVkExtProps_MVK_MACOS_SURFACE) { return false; } if (pProperties == &kVkExtProps_MVK_MACOS_SURFACE) { return false; }
#endif #endif

View File

@ -22,6 +22,8 @@
#include "mvk_datatypes.h" #include "mvk_datatypes.h"
#include <functional>
class MVKBaseObject; class MVKBaseObject;
/* /*
@ -75,4 +77,13 @@ MTLWinding mvkMTLWindingFromSpvExecutionModeInObj(uint32_t spvMode, MVKBaseObjec
MTLTessellationPartitionMode mvkMTLTessellationPartitionModeFromSpvExecutionModeInObj(uint32_t spvMode, MVKBaseObject* mvkObj); MTLTessellationPartitionMode mvkMTLTessellationPartitionModeFromSpvExecutionModeInObj(uint32_t spvMode, MVKBaseObject* mvkObj);
#define mvkMTLTessellationPartitionModeFromSpvExecutionMode(spvMode) mvkMTLTessellationPartitionModeFromSpvExecutionModeInObj(spvMode, this) #define mvkMTLTessellationPartitionModeFromSpvExecutionMode(spvMode) mvkMTLTessellationPartitionModeFromSpvExecutionModeInObj(spvMode, this)
#pragma mark -
#pragma mark Image properties
#pragma mark Texture formats
/** Enumerates all formats that support the given features, calling a specified function for each one. */
void mvkEnumerateSupportedFormats(VkFormatProperties properties, bool any, std::function<bool(VkFormat)> func);
#endif #endif

View File

@ -665,6 +665,25 @@ MVK_PUBLIC_SYMBOL const char* mvkMTLPixelFormatName(MTLPixelFormat mtlFormat) {
return formatDescForMTLPixelFormat(mtlFormat).mtlName; return formatDescForMTLPixelFormat(mtlFormat).mtlName;
} }
void mvkEnumerateSupportedFormats(VkFormatProperties properties, bool any, std::function<bool(VkFormat)> func) {
static const auto areFeaturesSupported = [any](uint32_t a, uint32_t b) {
if (any)
return mvkIsAnyFlagEnabled(a, b);
else
return mvkAreAllFlagsEnabled(a, b);
};
for (auto& formatDesc : _formatDescriptions) {
if (formatDesc.isSupported() &&
areFeaturesSupported(formatDesc.properties.linearTilingFeatures, properties.linearTilingFeatures) &&
areFeaturesSupported(formatDesc.properties.optimalTilingFeatures, properties.optimalTilingFeatures) &&
areFeaturesSupported(formatDesc.properties.bufferFeatures, properties.bufferFeatures)) {
if (!func(formatDesc.vk)) {
break;
}
}
}
}
#undef mvkMTLVertexFormatFromVkFormat #undef mvkMTLVertexFormatFromVkFormat
MVK_PUBLIC_SYMBOL MTLVertexFormat mvkMTLVertexFormatFromVkFormat(VkFormat vkFormat) { MVK_PUBLIC_SYMBOL MTLVertexFormat mvkMTLVertexFormatFromVkFormat(VkFormat vkFormat) {
return mvkMTLVertexFormatFromVkFormatInObj(vkFormat, nullptr); return mvkMTLVertexFormatFromVkFormatInObj(vkFormat, nullptr);